import { Buffer } from 'node:buffer'; import { AsyncEventEmitter } from '@vladfrangu/async_event_emitter'; import { Redis } from 'ioredis'; import Redis$1 from 'ioredis/built/Redis.js'; /** * Base options for a broker implementation */ interface BaseBrokerOptions { /** * Function to use for decoding messages */ decode?: (data: Buffer) => unknown; /** * Function to use for encoding messages */ encode?: (data: unknown) => Buffer; } /** * Default broker options */ declare const DefaultBrokerOptions: { readonly encode: (data: unknown) => Buffer; readonly decode: (data: Buffer) => unknown; }; type ToEventMap, TResponses extends Record | undefined = undefined> = { [TKey in keyof TRecord]: [ event: TResponses extends Record ? { ack(): Promise; reply(data: TResponses[TKey]): Promise; } : { ack(): Promise; data: TRecord[TKey]; } ]; }; interface IBaseBroker { /** * Subscribes to the given events */ subscribe(events: (keyof TEvents)[]): Promise; /** * Unsubscribes from the given events */ unsubscribe(events: (keyof TEvents)[]): Promise; } interface IPubSubBroker extends IBaseBroker, AsyncEventEmitter> { /** * Publishes an event */ publish(event: Event, data: TEvents[Event]): Promise; } interface IRPCBroker, TResponses extends Record> extends IBaseBroker, AsyncEventEmitter> { /** * Makes an RPC call */ call(event: Event, data: TEvents[Event], timeoutDuration?: number): Promise; } declare module 'ioredis' { interface Redis { xreadgroupBuffer(...args: (Buffer | string)[]): Promise<[Buffer, [Buffer, Buffer[]][]][] | null>; } } /** * Options specific for a Redis broker */ interface RedisBrokerOptions extends BaseBrokerOptions { /** * How long to block for messages when polling */ blockTimeout?: number; /** * Consumer group name to use for this broker * * @see {@link https://redis.io/commands/xreadgroup/} */ group: string; /** * Max number of messages to poll at once */ maxChunk?: number; /** * Unique consumer name. * * @see {@link https://redis.io/commands/xreadgroup/} */ name?: string; } /** * Default broker options for redis */ declare const DefaultRedisBrokerOptions: { readonly name: string; readonly maxChunk: 10; readonly blockTimeout: 5000; readonly encode: (data: unknown) => Buffer; readonly decode: (data: Buffer) => unknown; }; /** * Helper class with shared Redis logic */ declare abstract class BaseRedisBroker, TResponses extends Record | undefined = undefined> extends AsyncEventEmitter> implements IBaseBroker { protected readonly redisClient: Redis; /** * Used for Redis queues, see the 3rd argument taken by {@link https://redis.io/commands/xadd | xadd} */ static readonly STREAM_DATA_KEY = "data"; /** * Options this broker is using */ protected readonly options: Required; /** * Events this broker has subscribed to */ protected readonly subscribedEvents: Set; /** * Internal copy of the Redis client being used to read incoming payloads */ protected readonly streamReadClient: Redis; /** * Whether this broker is currently polling events */ protected listening: boolean; constructor(redisClient: Redis, options: RedisBrokerOptions); /** * {@inheritDoc IBaseBroker.subscribe} */ subscribe(events: (keyof TEvents)[]): Promise; /** * {@inheritDoc IBaseBroker.unsubscribe} */ unsubscribe(events: (keyof TEvents)[]): Promise; /** * Begins polling for events, firing them to {@link BaseRedisBroker.listen} */ protected listen(): Promise; /** * Destroys the broker, closing all connections */ destroy(): Promise; /** * Handles an incoming Redis event */ protected abstract emitEvent(id: Buffer, group: string, event: string, data: unknown): unknown; } /** * PubSub broker powered by Redis * * @example * ```ts * // publisher.js * import { PubSubRedisBroker } from '@discordjs/brokers'; * import Redis from 'ioredis'; * * const broker = new PubSubRedisBroker(new Redis()); * * await broker.publish('test', 'Hello World!'); * await broker.destroy(); * * // subscriber.js * import { PubSubRedisBroker } from '@discordjs/brokers'; * import Redis from 'ioredis'; * * const broker = new PubSubRedisBroker(new Redis()); * broker.on('test', ({ data, ack }) => { * console.log(data); * void ack(); * }); * * await broker.subscribe('subscribers', ['test']); * ``` */ declare class PubSubRedisBroker> extends BaseRedisBroker implements IPubSubBroker { /** * {@inheritDoc IPubSubBroker.publish} */ publish(event: Event, data: TEvents[Event]): Promise; protected emitEvent(id: Buffer, group: string, event: string, data: unknown): void; } interface InternalPromise { reject(error: any): void; resolve(data: any): void; timeout: NodeJS.Timeout; } /** * Options specific for an RPC Redis broker */ interface RPCRedisBrokerOptions extends RedisBrokerOptions { timeout?: number; } /** * Default values used for the {@link RPCRedisBrokerOptions} */ declare const DefaultRPCRedisBrokerOptions: { readonly timeout: 5000; readonly name: string; readonly maxChunk: 10; readonly blockTimeout: 5000; readonly encode: (data: unknown) => Buffer; readonly decode: (data: Buffer) => unknown; }; /** * RPC broker powered by Redis * * @example * ```ts * // caller.js * import { RPCRedisBroker } from '@discordjs/brokers'; * import Redis from 'ioredis'; * * const broker = new RPCRedisBroker(new Redis()); * * console.log(await broker.call('testcall', 'Hello World!')); * await broker.destroy(); * * // responder.js * import { RPCRedisBroker } from '@discordjs/brokers'; * import Redis from 'ioredis'; * * const broker = new RPCRedisBroker(new Redis()); * broker.on('testcall', ({ data, ack, reply }) => { * console.log('responder', data); * void ack(); * void reply(`Echo: ${data}`); * }); * * await broker.subscribe('responders', ['testcall']); * ``` */ declare class RPCRedisBroker, TResponses extends Record> extends BaseRedisBroker implements IRPCBroker { /** * Options this broker is using */ protected readonly options: Required; protected readonly promises: Map; constructor(redisClient: Redis$1, options: RPCRedisBrokerOptions); /** * {@inheritDoc IRPCBroker.call} */ call(event: Event, data: TEvents[Event], timeoutDuration?: number): Promise; protected emitEvent(id: Buffer, event: string, data: unknown): void; } /** * The {@link https://github.com/discordjs/discord.js/blob/main/packages/brokers#readme | @discordjs/brokers} version * that you are currently using. * * @privateRemarks This needs to explicitly be `string` so it is not typed as a "const string" that gets injected by esbuild. */ declare const version: string; export { type BaseBrokerOptions, BaseRedisBroker, DefaultBrokerOptions, DefaultRPCRedisBrokerOptions, DefaultRedisBrokerOptions, type IBaseBroker, type IPubSubBroker, type IRPCBroker, PubSubRedisBroker, RPCRedisBroker, type RPCRedisBrokerOptions, type RedisBrokerOptions, type ToEventMap, version };