diff --git a/types/rascal/index.d.ts b/types/rascal/index.d.ts new file mode 100644 index 0000000000..7f640dd971 --- /dev/null +++ b/types/rascal/index.d.ts @@ -0,0 +1,460 @@ +// Type definitions for rascal 8.0 +// Project: https://guidesmiths.github.io/rascal/ +// Definitions by: ethan +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 3.2 + +/// + +import { EventEmitter } from "events"; +import { Message, Options } from "amqplib"; + +interface BindingConfig { + source?: string; + destination?: string; + destinationType?: 'queue' | 'exchange'; + bindingKey?: string; + bindingKeys?: string[]; + options?: any; +} + +interface QueueConfig { + assert?: boolean; + check?: boolean; + options?: Options.AssertQueue; +} + +interface ExchangeConfig { + assert?: boolean; + check?: boolean; + type?: 'direct' | 'fanout' | 'headers' | 'topic'; + options?: Options.AssertExchange; +} + +interface ConnectionAttributes { + slashes?: boolean; + protocol?: string; + hostname?: string; + user?: string; + password?: string; + port?: string | number; + vhost?: string; + auth?: string; + pathname?: string; + query?: string; + url?: string; + loggableUrl?: string; + options?: { + heartbeat?: number; + timeout?: number; + channelMax?: number; + connection_timeout?: number; + [key: string]: any + }; + socketOptions?: { + timeout?: number; + }; +} + +interface RetryConfig { + factor?: number; + max?: number; + min?: number; + strategy?: 'exponential' | 'linear'; + delay?: number; +} + +interface ConnectionConfig extends ConnectionAttributes { + retry?: RetryConfig; + management?: ConnectionAttributes; +} + +interface ChannelPoolConfig { + autostart?: boolean; + evictionRunIntervalMillis?: number; + idleTimeoutMillis?: number; + max?: number; + min?: number; + testOnBorrow?: boolean; +} + +interface VhostConfig { + check?: boolean; + assert?: boolean; + namespace?: string | boolean; + publicationChannelPools?: { + regularPool?: ChannelPoolConfig; + confirmPool?: ChannelPoolConfig; + }; + connection?: ConnectionConfig; + connections?: ConnectionConfig[]; + connectionStrategy?: 'random' | 'fixed'; + exchanges?: { + [key: string]: ExchangeConfig; + } | string[]; + queues?: { + [key: string]: QueueConfig; + } | string[]; + bindings?: { + [key: string]: BindingConfig; + } | string[]; + publications?: { + [key: string]: PublicationConfig; + }; + subscriptions?: { + [key: string]: SubscriptionConfig; + }; +} + +interface PublicationConfig { + vhost?: string; + exchange?: string; + queue?: string; + routingKey?: string; + confirm?: boolean; + options?: Options.Publish; + autoCreated?: boolean; + deprecated?: boolean; + encryption?: string; +} + +interface Encryption { + key: string; + algorithm: string; + ivLength: number; +} + +interface Redelivery { + counters?: { + [key: string]: { + type: 'stub' | 'inMemory' | 'inMemoryCluster'; + size?: number; + } + }; +} + +interface Recovery { + strategy: "ack" | "nack" | "republish" | "forward"; + defer?: number; + attempts?: number; + requeue?: boolean; + publication?: string; + options?: PublicationConfig; + xDeathFix?: boolean; + immediateNack?: boolean; +} + +interface SubscriptionConfig { + vhost?: string; + queue?: string; + contentType?: string; + options?: Options.Consume; + prefetch?: number; + retry?: RetryConfig | boolean; + handler?: string; + handlers?: string[]; + recovery?: any; + deferCloseChannel?: number; + encryption?: string; + autoCreated?: boolean; + redeliveries?: { + counter: string; + limit: number; + timeout?: number; + }; +} + +export interface BrokerConfig { + vhosts?: { + [key: string]: VhostConfig; + }; + publications?: { + [key: string]: PublicationConfig; + }; + subscriptions?: { + [key: string]: SubscriptionConfig; + }; + redeliveries?: Redelivery; + recovery?: { + [key: string]: Recovery | Recovery[]; + }; + defaults?: BrokerConfig; + encryption?: { + [key: string]: Encryption; + }; +} + +export const defaultConfig: { + defaults: { + publications: { + confirm: boolean; + options: { + mandatory: boolean; + persistent: boolean; + }; + vhost: string; + }; + redeliveries: { + counters: { + inMemory: { + size: number; + }; + stub: { + }; + }; + }; + subscriptions: { + deferCloseChannel: number; + prefetch: number; + redeliveries: { + counter: string; + limit: number; + timeout: number; + }; + retry: { + factor: number; + max: number; + min: number; + strategy: string; + }; + vhost: string; + }; + vhosts: { + bindings: { + bindingKey: string; + destinationType: string; + }; + connection: { + hostname: string; + management: { + options: { + timeout: number; + }; + port: number; + protocol: string; + slashes: boolean; + }; + options: { + channelMax: number; + connection_timeout: number; + heartbeat: number; + }; + password: string; + port: string; + protocol: string; + retry: { + factor: number; + max: number; + min: number; + strategy: string; + }; + slashes: boolean; + socketOptions: { + timeout: number; + }; + user: string; + }; + connectionStrategy: string; + exchanges: { + assert: boolean; + type: string; + }; + publicationChannelPools: { + confirmPool: { + autostart: boolean; + evictionRunIntervalMillis: number; + idleTimeoutMillis: number; + max: number; + min: number; + testOnBorrow: boolean; + }; + regularPool: { + autostart: boolean; + evictionRunIntervalMillis: number; + idleTimeoutMillis: number; + max: number; + min: number; + testOnBorrow: boolean; + }; + }; + queues: { + assert: boolean; + }; + }; + }; +}; + +export const testConfig: { + defaults: { + publications: { + confirm: boolean; + options: { + mandatory: boolean; + persistent: boolean; + }; + vhost: string; + }; + redeliveries: { + counters: { + inMemory: { + size: number; + }; + stub: { + }; + }; + }; + subscriptions: { + deferCloseChannel: number; + prefetch: number; + redeliveries: { + counter: string; + limit: number; + timeout: number; + }; + retry: { + factor: number; + max: number; + min: number; + strategy: string; + }; + vhost: string; + }; + vhosts: { + bindings: { + bindingKey: string; + destinationType: string; + }; + connection: { + hostname: string; + management: { + options: { + timeout: number; + }; + port: number; + protocol: string; + slashes: boolean; + }; + options: { + channelMax: number; + connection_timeout: number; + heartbeat: number; + }; + password: string; + port: string; + protocol: string; + retry: { + factor: number; + max: number; + min: number; + strategy: string; + }; + slashes: boolean; + socketOptions: { + timeout: number; + }; + user: string; + }; + connectionStrategy: string; + exchanges: { + assert: boolean; + options: { + durable: boolean; + }; + type: string; + }; + namespace: boolean; + publicationChannelPools: { + confirmPool: { + autostart: boolean; + evictionRunIntervalMillis: number; + idleTimeoutMillis: number; + max: number; + min: number; + testOnBorrow: boolean; + }; + regularPool: { + autostart: boolean; + evictionRunIntervalMillis: number; + idleTimeoutMillis: number; + max: number; + min: number; + testOnBorrow: boolean; + }; + }; + queues: { + assert: boolean; + options: { + durable: boolean; + }; + purge: boolean; + }; + }; + }; + redeliveries: { + counters: { + inMemory: { + size: number; + }; + stub: { + }; + }; + }; +}; + +export type AckOrNackFn = (err?: Error, recovery?: Recovery | Recovery[]) => void; + +declare class SubscriptionSession extends EventEmitter { + name: string; + isCancelled(): boolean; + cancel(): Promise; + on(event: 'message', listener: (message: Message, content: any, ackOrNackFn: any) => void): this; + on(event: 'error' | 'cancelled', listener: (err: Error) => void): this; + on(event: 'invalid_content' | 'redeliveries_exceeded' | 'redeliveries_error' | 'redeliveries_error', listener: (err: Error, message: Message, ackOrNackFn: any) => void): this; +} + +declare class PublishEventemitter extends EventEmitter { + on(event: 'success', listener: (messageId: string) => void): this; + on(event: 'error', listener: (err: Error, messageId: string) => void): this; + on(event: 'return', listener: (message: Message) => void): this; +} + +declare class BrokerAsPromisedClass extends EventEmitter { + readonly config: BrokerConfig; + constructor(config: BrokerConfig, compoents: any) + connect(name: string): Promise; + nuke(): Promise; + purge(): Promise; + shutdown(): Promise; + bounce(): Promise; + unsubscribeAll(): Promise; + publish(name: string, message: any, overrides?: PublicationConfig | string): Promise; + forward(name: string, message: any, overrides?: PublicationConfig | string): Promise; + subscribe(name: string, overrides?: SubscriptionConfig): Promise; +} + +export function createBroker(config: BrokerConfig, components: any, next: any, ...args: any[]): any; + +export function createBrokerAsPromised(config: BrokerConfig, components: any): Promise; + +export function withDefaultConfig(config: BrokerConfig): BrokerConfig; + +export function withTestConfig(config: BrokerConfig): BrokerConfig; + +export namespace Broker { + function create(config: any, next: any, ...args: any[]): any; + function create(config: any, components: any, next: any, ...args: any[]): any; +} + +export namespace BrokerAsPromised { + function create(config: BrokerConfig, components?: any): Promise; +} +export namespace counters { + function inMemory(options: any): any; + function stub(options: any): any; + namespace inMemoryCluster { + function master(options: any): void; + function worker(options: any): any; + } +} + +export {}; diff --git a/types/rascal/rascal-tests.ts b/types/rascal/rascal-tests.ts new file mode 100644 index 0000000000..d0d0e76243 --- /dev/null +++ b/types/rascal/rascal-tests.ts @@ -0,0 +1,91 @@ +import { Broker, BrokerAsPromised, BrokerConfig, AckOrNackFn, withDefaultConfig } from "rascal"; +import { Message } from "amqplib"; + +const config: BrokerConfig = { + vhosts: { + "/": { + connection: { + url: "amqp://user:password@broker.example.com:5742/" + }, + exchanges: [ + "demo_ex" + ], + queues: [ + "demo_q" + ], + bindings: [ + "demo_ex[a.b.c] -> demo_q" + ], + publications: { + demo_pub: { + exchange: "demo_ex", + routingKey: "a.b.c" + } + }, + subscriptions: { + demo_sub: { + queue: "demo_q", + prefetch: 3 + } + } + } + } +}; + +(async () => { + try { + const broker = await BrokerAsPromised.create(withDefaultConfig(config)); + broker.on('error', console.error); + + // Publish a message + const publication = await broker.publish('demo_publication', 'Hello World!'); + await broker.publish("p1", "some message"); + await broker.publish("p1", "some message", "some.routing.key"); + await broker.publish("p1", "some message", { routingKey: "some.routing.key", options: { messageId: "foo", expiration: 5000 } }); + publication.on('error', console.error); + + // Consume a message + const subscription = await broker.subscribe('demo_subscription'); + await broker.subscribe("s1", { prefetch: 10, retry: false }); + await subscription.cancel(); + subscription.isCancelled(); + subscription.on('message', (message: Message, content: any, ackOrNack: AckOrNackFn) => { + ackOrNack(); + ackOrNack(new Error(), { strategy: 'nack' }); + ackOrNack(new Error(), { strategy: 'nack', defer: 1000, requeue: true }); + ackOrNack(new Error(), [ + { strategy: 'republish', defer: 1000, attempts: 10 }, + { strategy: 'nack' } + ]); + ackOrNack(new Error(), { strategy: 'republish', immediateNack: true }); + ackOrNack(new Error(), { strategy: 'forward', publication: 'some_exchange' }); + ackOrNack(new Error(), [ + { strategy: 'forward', publication: 'some_exchange', options: { routingKey: 'custom.routing.key' } }, + { strategy: 'nack' } + ]); + }).on('error', console.error); + } catch (err) { + console.error(err); + } +})(); + +Broker.create(config, (err: Error, broker: any) => { + if (err) throw err; + + broker.on('error', console.error); + + // Publish a message + broker.publish('demo_publication', 'Hello World!', (err: Error, publication: any) => { + if (err) throw err; + publication.on('error', console.error); + }); + + // Consume a message + broker.subscribe('demo_subscription', (err: Error, subscription: any) => { + if (err) throw err; + subscription.on('message', (message: Message, content: any, ackOrNack: AckOrNackFn) => { + console.log(content); + ackOrNack(); + }).on('error', console.error); + }); +}); diff --git a/types/rascal/tsconfig.json b/types/rascal/tsconfig.json new file mode 100644 index 0000000000..02a003e296 --- /dev/null +++ b/types/rascal/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "rascal-tests.ts" + ] +} diff --git a/types/rascal/tslint.json b/types/rascal/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/rascal/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }