@geekmidas/events 10.0.0-alpha.78 → 10.0.0-alpha.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/{SQSSubscriber-BXLE_1L3.mjs → SQSSubscriber-BEJBfNTe.mjs} +94 -10
  2. package/dist/SQSSubscriber-BEJBfNTe.mjs.map +1 -0
  3. package/dist/{SQSSubscriber-DtRUaZB3.cjs → SQSSubscriber-COTqWvOk.cjs} +101 -10
  4. package/dist/SQSSubscriber-COTqWvOk.cjs.map +1 -0
  5. package/dist/basic/index.cjs +16 -4
  6. package/dist/basic/index.cjs.map +1 -1
  7. package/dist/basic/index.d.cts.map +1 -1
  8. package/dist/basic/index.d.mts.map +1 -1
  9. package/dist/basic/index.mjs +16 -4
  10. package/dist/basic/index.mjs.map +1 -1
  11. package/dist/index.cjs +11 -4
  12. package/dist/index.d.cts +60 -1
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.mts +60 -1
  15. package/dist/index.d.mts.map +1 -1
  16. package/dist/index.mjs +3 -3
  17. package/dist/pgboss/index.cjs +50 -22
  18. package/dist/pgboss/index.cjs.map +1 -1
  19. package/dist/pgboss/index.d.cts.map +1 -1
  20. package/dist/pgboss/index.d.mts.map +1 -1
  21. package/dist/pgboss/index.mjs +50 -22
  22. package/dist/pgboss/index.mjs.map +1 -1
  23. package/dist/rabbitmq/index.cjs +32 -15
  24. package/dist/rabbitmq/index.cjs.map +1 -1
  25. package/dist/rabbitmq/index.d.cts.map +1 -1
  26. package/dist/rabbitmq/index.d.mts.map +1 -1
  27. package/dist/rabbitmq/index.mjs +32 -15
  28. package/dist/rabbitmq/index.mjs.map +1 -1
  29. package/dist/{registry-DLnflkMm.mjs → registry-DXLY1Xf6.mjs} +2 -2
  30. package/dist/{registry-DLnflkMm.mjs.map → registry-DXLY1Xf6.mjs.map} +1 -1
  31. package/dist/{registry-DNk5GnGq.cjs → registry-DlT36229.cjs} +3 -3
  32. package/dist/{registry-DNk5GnGq.cjs.map → registry-DlT36229.cjs.map} +1 -1
  33. package/dist/sns/index.cjs +17 -8
  34. package/dist/sns/index.cjs.map +1 -1
  35. package/dist/sns/index.d.cts.map +1 -1
  36. package/dist/sns/index.d.mts.map +1 -1
  37. package/dist/sns/index.mjs +17 -8
  38. package/dist/sns/index.mjs.map +1 -1
  39. package/dist/sqs/index.cjs +7 -72
  40. package/dist/sqs/index.cjs.map +1 -1
  41. package/dist/sqs/index.d.cts +1 -0
  42. package/dist/sqs/index.d.cts.map +1 -1
  43. package/dist/sqs/index.d.mts +1 -0
  44. package/dist/sqs/index.d.mts.map +1 -1
  45. package/dist/sqs/index.mjs +3 -66
  46. package/dist/sqs/index.mjs.map +1 -1
  47. package/dist/telemetry-DG3l807O.cjs +309 -0
  48. package/dist/telemetry-DG3l807O.cjs.map +1 -0
  49. package/dist/telemetry-DjjgJMul.mjs +244 -0
  50. package/dist/telemetry-DjjgJMul.mjs.map +1 -0
  51. package/package.json +5 -3
  52. package/dist/SQSSubscriber-BXLE_1L3.mjs.map +0 -1
  53. package/dist/SQSSubscriber-DtRUaZB3.cjs.map +0 -1
  54. package/dist/types-BcZjLxVV.cjs +0 -51
  55. package/dist/types-BcZjLxVV.cjs.map +0 -1
  56. package/dist/types-Bk5JM6MP.mjs +0 -40
  57. package/dist/types-Bk5JM6MP.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts","../../src/rabbitmq/driver.ts"],"sourcesContent":["import amqplib from 'amqplib';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\n\nexport interface RabbitMQConnectionConfig {\n\turl: string;\n\texchange?: string;\n\texchangeType?: 'topic' | 'direct' | 'fanout' | 'headers';\n\texchangeOptions?: amqplib.Options.AssertExchange;\n\ttimeout?: number; // Connection timeout in milliseconds (default: 5000)\n}\n\nexport class RabbitMQConnection implements EventConnection {\n\treadonly type = EventPublisherType.RabbitMQ;\n\tprivate connection?: amqplib.ChannelModel;\n\tprivate channel?: amqplib.Channel;\n\tprivate connecting?: Promise<void>;\n\tprivate config: Required<\n\t\tPick<RabbitMQConnectionConfig, 'exchange' | 'exchangeType' | 'timeout'>\n\t> &\n\t\tRabbitMQConnectionConfig;\n\n\tconstructor(config: RabbitMQConnectionConfig) {\n\t\tthis.config = {\n\t\t\t...config,\n\t\t\texchange: config.exchange || 'geekmidas.events',\n\t\t\texchangeType: config.exchangeType || 'topic',\n\t\t\ttimeout: config.timeout ?? 5000,\n\t\t\texchangeOptions: {\n\t\t\t\tdurable: true,\n\t\t\t\t...config.exchangeOptions,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Create a RabbitMQConnection from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString(\n\t\tconnectionString: string,\n\t): Promise<RabbitMQConnection> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\t// Extract connection URL without query params\n\t\tconst baseUrl = `amqp://${url.username ? `${url.username}:${url.password}@` : ''}${url.host}${url.pathname}`;\n\n\t\tconst timeoutParam = params.get('timeout');\n\t\tconst config: RabbitMQConnectionConfig = {\n\t\t\turl: baseUrl,\n\t\t\texchange: params.get('exchange') || 'geekmidas.events',\n\t\t\texchangeType: (params.get('type') as any) || 'topic',\n\t\t\ttimeout: timeoutParam ? Number.parseInt(timeoutParam, 10) : undefined,\n\t\t};\n\n\t\tconst connection = new RabbitMQConnection(config);\n\t\tawait connection.connect();\n\t\treturn connection;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.channel) return;\n\n\t\t// Prevent multiple simultaneous connection attempts\n\t\tif (this.connecting) {\n\t\t\tawait this.connecting;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.connecting = (async () => {\n\t\t\ttry {\n\t\t\t\tconst connection = await amqplib.connect(this.config.url, {\n\t\t\t\t\ttimeout: this.config.timeout,\n\t\t\t\t});\n\t\t\t\tconst channel = await connection.createChannel();\n\n\t\t\t\t// Assert the exchange exists\n\t\t\t\tawait channel.assertExchange(\n\t\t\t\t\tthis.config.exchange!,\n\t\t\t\t\tthis.config.exchangeType!,\n\t\t\t\t\tthis.config.exchangeOptions,\n\t\t\t\t);\n\n\t\t\t\t// Handle connection errors\n\t\t\t\tconnection.on('error', (_err: Error) => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\tconnection.on('close', () => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\t// Only set after successful setup\n\t\t\t\tthis.connection = connection;\n\t\t\t\tthis.channel = channel;\n\t\t\t} catch (error) {\n\t\t\t\tthis.cleanup();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})();\n\n\t\tawait this.connecting;\n\t\tthis.connecting = undefined;\n\t}\n\n\tasync close(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.channel?.close();\n\t\t\tawait this.connection?.close();\n\t\t} catch (_error) {\n\t\t\t// Ignore errors during close\n\t\t} finally {\n\t\t\tthis.cleanup();\n\t\t}\n\t}\n\n\tisConnected(): boolean {\n\t\treturn !!this.channel;\n\t}\n\n\tprivate cleanup(): void {\n\t\tthis.channel = undefined;\n\t\tthis.connection = undefined;\n\t\tthis.connecting = undefined;\n\t}\n\n\t/**\n\t * Get the underlying channel for publishing/subscribing\n\t */\n\tget amqpChannel(): amqplib.Channel | undefined {\n\t\treturn this.channel;\n\t}\n\n\t/**\n\t * Get the exchange name for this connection\n\t */\n\tget exchangeName(): string {\n\t\treturn this.config.exchange;\n\t}\n\n\t/**\n\t * Get the exchange type for this connection\n\t */\n\tget exchangeType(): string {\n\t\treturn this.config.exchangeType;\n\t}\n}\n","// Beside the adapter but apart from its connection module, which imports\n// the broker's client: the publisher and subscriber load that lazily, and\n// importing an error class from it would load it eagerly.\n\n/** The connection opened but has no channel to publish or consume on. */\nexport class RabbitMQChannelUnavailable extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'RabbitMQ connected without a channel. Check the broker is reachable and the connection string names a vhost the user can open channels on.',\n\t\t);\n\t\tthis.name = 'RabbitMQChannelUnavailable';\n\t}\n}\n","import type amqplib from 'amqplib';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQPublisherOptions {\n\tpublishOptions?: amqplib.Options.Publish;\n}\n\nexport class RabbitMQPublisher<TMessage extends PublishableMessage<string, any>>\n\timplements EventPublisher<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQPublisherOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQPublisher from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQPublisher<TMessage>> {\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\t\treturn new RabbitMQPublisher<TMessage>(connection);\n\t}\n\n\tasync publish(messages: TMessage[]): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\tfor (const message of messages) {\n\t\t\tconst content = Buffer.from(JSON.stringify(message.payload));\n\n\t\t\t// Use message type as routing key for topic exchanges\n\t\t\tconst routingKey = message.type;\n\n\t\t\tconst published = channel.publish(exchange, routingKey, content, {\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\ttype: message.type,\n\t\t\t\tpersistent: true,\n\t\t\t\t...this.options.publishOptions,\n\t\t\t});\n\n\t\t\t// Handle backpressure\n\t\t\tif (!published) {\n\t\t\t\tawait new Promise((resolve) => channel.once('drain', resolve));\n\t\t\t}\n\t\t}\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// Publisher doesn't own the connection\n\t\t// Connection should be closed by whoever created it\n\t}\n}\n","import type amqplib from 'amqplib';\nimport type { EventSubscriber, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQSubscriberOptions {\n\tqueueName?: string; // If not provided, a unique queue will be generated\n\tqueueOptions?: amqplib.Options.AssertQueue;\n\tconsumeOptions?: amqplib.Options.Consume;\n\tprefetch?: number; // Number of messages to prefetch (default: 1)\n}\n\nexport class RabbitMQSubscriber<\n\tTMessage extends PublishableMessage<string, any>,\n> implements EventSubscriber<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQSubscriberOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQSubscriber from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&queueName=myqueue&prefetch=10\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQSubscriber<TMessage>> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\n\t\tconst options: RabbitMQSubscriberOptions = {\n\t\t\tqueueName: params.get('queueName') || undefined,\n\t\t\tprefetch: params.get('prefetch')\n\t\t\t\t? Number.parseInt(params.get('prefetch')!, 10)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\treturn new RabbitMQSubscriber<TMessage>(connection, options);\n\t}\n\n\tasync subscribe(\n\t\tmessages: TMessage['type'][],\n\t\tlistener: (payload: TMessage) => Promise<void>,\n\t): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\t// Set prefetch if specified\n\t\tif (this.options.prefetch) {\n\t\t\tawait channel.prefetch(this.options.prefetch);\n\t\t}\n\n\t\t// Assert queue\n\t\tconst queueName = this.options.queueName || '';\n\t\tconst queueOptions: amqplib.Options.AssertQueue = {\n\t\t\tdurable: true,\n\t\t\t...this.options.queueOptions,\n\t\t};\n\n\t\tconst { queue } = await channel.assertQueue(queueName, queueOptions);\n\n\t\t// Bind queue to exchange for each message type\n\t\tfor (const messageType of messages) {\n\t\t\tawait channel.bindQueue(queue, exchange, messageType);\n\t\t}\n\n\t\t// Consume messages\n\t\tawait channel.consume(\n\t\t\tqueue,\n\t\t\tasync (msg) => {\n\t\t\t\tif (!msg) return;\n\n\t\t\t\ttry {\n\t\t\t\t\t// Parse message payload\n\t\t\t\t\tconst content = msg.content.toString();\n\t\t\t\t\tconst payload = JSON.parse(content);\n\n\t\t\t\t\t// Get message type from properties\n\t\t\t\t\tconst messageType = msg.properties.type;\n\n\t\t\t\t\t// Reconstruct full message\n\t\t\t\t\tconst fullMessage: TMessage = {\n\t\t\t\t\t\ttype: messageType,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t} as TMessage;\n\n\t\t\t\t\t// Call listener\n\t\t\t\t\tawait listener(fullMessage);\n\n\t\t\t\t\t// Ack message\n\t\t\t\t\tchannel.ack(msg);\n\t\t\t\t} catch (_error) {\n\t\t\t\t\tchannel.nack(msg, false, true);\n\t\t\t\t}\n\t\t\t},\n\t\t\tthis.options.consumeOptions,\n\t\t);\n\t}\n}\n","import type { EventsDriver } from '../registry';\nimport { EventPublisherType } from '../types';\nimport { RabbitMQConnection } from './RabbitMQConnection';\nimport { RabbitMQPublisher } from './RabbitMQPublisher';\nimport { RabbitMQSubscriber } from './RabbitMQSubscriber';\n\n/**\n * `rabbitmq://` — an AMQP exchange. Register it with\n * `registerEventsDriver(rabbitmqEventsDriver)`; this subpath is the only one\n * that imports `amqplib`.\n */\nexport const rabbitmqEventsDriver: EventsDriver = {\n\tscheme: EventPublisherType.RabbitMQ,\n\tconnect: (url) => RabbitMQConnection.fromConnectionString(url),\n\tpublisher: (url) => RabbitMQPublisher.fromConnectionString(url),\n\tpublisherFor: (connection) =>\n\t\tnew RabbitMQPublisher(connection as RabbitMQConnection),\n\tsubscriber: (url) => RabbitMQSubscriber.fromConnectionString(url),\n\tsubscriberFor: (connection) =>\n\t\tnew RabbitMQSubscriber(connection as RabbitMQConnection),\n};\n"],"mappings":";;;;;;;AAYA,IAAa,qBAAb,MAAa,mBAA8C;CAC1D,OAAS;CACT;CACA;CACA;CACA;CAKA,YAAY,QAAkC;EAC7C,KAAK,SAAS;GACb,GAAG;GACH,UAAU,OAAO,YAAY;GAC7B,cAAc,OAAO,gBAAgB;GACrC,SAAS,OAAO,WAAW;GAC3B,iBAAiB;IAChB,SAAS;IACT,GAAG,OAAO;GACX;EACD;CACD;;;;;CAMA,aAAa,qBACZ,kBAC8B;EAC9B,MAAM,MAAM,IAAI,IAAI,gBAAgB;EACpC,MAAM,SAAS,IAAI;EAGnB,MAAM,UAAU,UAAU,IAAI,WAAW,GAAG,IAAI,SAAS,GAAG,IAAI,SAAS,KAAK,KAAK,IAAI,OAAO,IAAI;EAElG,MAAM,eAAe,OAAO,IAAI,SAAS;EACzC,MAAM,SAAmC;GACxC,KAAK;GACL,UAAU,OAAO,IAAI,UAAU,KAAK;GACpC,cAAe,OAAO,IAAI,MAAM,KAAa;GAC7C,SAAS,eAAe,OAAO,SAAS,cAAc,EAAE,IAAI,KAAA;EAC7D;EAEA,MAAM,aAAa,IAAI,mBAAmB,MAAM;EAChD,MAAM,WAAW,QAAQ;EACzB,OAAO;CACR;CAEA,MAAM,UAAyB;EAC9B,IAAI,KAAK,SAAS;EAGlB,IAAI,KAAK,YAAY;GACpB,MAAM,KAAK;GACX;EACD;EAEA,KAAK,cAAc,YAAY;GAC9B,IAAI;IACH,MAAM,aAAa,MAAM,QAAA,QAAQ,QAAQ,KAAK,OAAO,KAAK,EACzD,SAAS,KAAK,OAAO,QACtB,CAAC;IACD,MAAM,UAAU,MAAM,WAAW,cAAc;IAG/C,MAAM,QAAQ,eACb,KAAK,OAAO,UACZ,KAAK,OAAO,cACZ,KAAK,OAAO,eACb;IAGA,WAAW,GAAG,UAAU,SAAgB;KACvC,KAAK,QAAQ;IACd,CAAC;IAED,WAAW,GAAG,eAAe;KAC5B,KAAK,QAAQ;IACd,CAAC;IAGD,KAAK,aAAa;IAClB,KAAK,UAAU;GAChB,SAAS,OAAO;IACf,KAAK,QAAQ;IACb,MAAM;GACP;EACD,EAAA,CAAG;EAEH,MAAM,KAAK;EACX,KAAK,aAAa,KAAA;CACnB;CAEA,MAAM,QAAuB;EAC5B,IAAI;GACH,MAAM,KAAK,SAAS,MAAM;GAC1B,MAAM,KAAK,YAAY,MAAM;EAC9B,SAAS,QAAQ,CAEjB,UAAU;GACT,KAAK,QAAQ;EACd;CACD;CAEA,cAAuB;EACtB,OAAO,CAAC,CAAC,KAAK;CACf;CAEA,UAAwB;EACvB,KAAK,UAAU,KAAA;EACf,KAAK,aAAa,KAAA;EAClB,KAAK,aAAa,KAAA;CACnB;;;;CAKA,IAAI,cAA2C;EAC9C,OAAO,KAAK;CACb;;;;CAKA,IAAI,eAAuB;EAC1B,OAAO,KAAK,OAAO;CACpB;;;;CAKA,IAAI,eAAuB;EAC1B,OAAO,KAAK,OAAO;CACpB;AACD;;;;AC9IA,IAAa,6BAAb,cAAgD,MAAM;CACrD,cAAc;EACb,MACC,4IACD;EACA,KAAK,OAAO;CACb;AACD;;;ACHA,IAAa,oBAAb,MAAa,kBAEb;CAEU;CACA;CAFT,YACC,YACA,UAA4C,CAAC,GAC5C;EAFO,KAAA,aAAA;EACA,KAAA,UAAA;CACN;;;;;CAMH,aAAa,qBAEX,kBAAgE;EACjE,MAAM,EAAE,uBAAuB,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,0BAAA;EAC/B,MAAM,aACL,MAAM,mBAAmB,qBAAqB,gBAAgB;EAC/D,OAAO,IAAI,kBAA4B,UAAU;CAClD;CAEA,MAAM,QAAQ,UAAqC;EAClD,IAAI,CAAC,KAAK,WAAW,YAAY,GAChC,MAAM,KAAK,WAAW,QAAQ;EAG/B,MAAM,UAAU,KAAK,WAAW;EAChC,IAAI,CAAC,SACJ,MAAM,IAAI,2BAA2B;EAGtC,MAAM,WAAW,KAAK,WAAW;EAEjC,KAAK,MAAM,WAAW,UAAU;GAC/B,MAAM,UAAU,OAAO,KAAK,KAAK,UAAU,QAAQ,OAAO,CAAC;GAG3D,MAAM,aAAa,QAAQ;GAW3B,IAAI,CATc,QAAQ,QAAQ,UAAU,YAAY,SAAS;IAChE,aAAa;IACb,WAAW,KAAK,IAAI;IACpB,MAAM,QAAQ;IACd,YAAY;IACZ,GAAG,KAAK,QAAQ;GACjB,CAGa,GACZ,MAAM,IAAI,SAAS,YAAY,QAAQ,KAAK,SAAS,OAAO,CAAC;EAE/D;CACD;CAEA,MAAM,QAAuB,CAG7B;AACD;;;ACvDA,IAAa,qBAAb,MAAa,mBAGb;CAEU;CACA;CAFT,YACC,YACA,UAA6C,CAAC,GAC7C;EAFO,KAAA,aAAA;EACA,KAAA,UAAA;CACN;;;;;CAMH,aAAa,qBAEX,kBAAiE;EAElE,MAAM,SAAS,IADC,IAAI,gBACH,CAAC,CAAC;EAEnB,MAAM,EAAE,uBAAuB,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,0BAAA;EAC/B,MAAM,aACL,MAAM,mBAAmB,qBAAqB,gBAAgB;EAE/D,MAAM,UAAqC;GAC1C,WAAW,OAAO,IAAI,WAAW,KAAK,KAAA;GACtC,UAAU,OAAO,IAAI,UAAU,IAC5B,OAAO,SAAS,OAAO,IAAI,UAAU,GAAI,EAAE,IAC3C,KAAA;EACJ;EAEA,OAAO,IAAI,mBAA6B,YAAY,OAAO;CAC5D;CAEA,MAAM,UACL,UACA,UACgB;EAChB,IAAI,CAAC,KAAK,WAAW,YAAY,GAChC,MAAM,KAAK,WAAW,QAAQ;EAG/B,MAAM,UAAU,KAAK,WAAW;EAChC,IAAI,CAAC,SACJ,MAAM,IAAI,2BAA2B;EAGtC,MAAM,WAAW,KAAK,WAAW;EAGjC,IAAI,KAAK,QAAQ,UAChB,MAAM,QAAQ,SAAS,KAAK,QAAQ,QAAQ;EAI7C,MAAM,YAAY,KAAK,QAAQ,aAAa;EAC5C,MAAM,eAA4C;GACjD,SAAS;GACT,GAAG,KAAK,QAAQ;EACjB;EAEA,MAAM,EAAE,UAAU,MAAM,QAAQ,YAAY,WAAW,YAAY;EAGnE,KAAK,MAAM,eAAe,UACzB,MAAM,QAAQ,UAAU,OAAO,UAAU,WAAW;EAIrD,MAAM,QAAQ,QACb,OACA,OAAO,QAAQ;GACd,IAAI,CAAC,KAAK;GAEV,IAAI;IAEH,MAAM,UAAU,IAAI,QAAQ,SAAS;IACrC,MAAM,UAAU,KAAK,MAAM,OAAO;IAYlC,MAAM,SAAS;KALd,MAJmB,IAAI,WAAW;KAKlC;IAIwB,CAAC;IAG1B,QAAQ,IAAI,GAAG;GAChB,SAAS,QAAQ;IAChB,QAAQ,KAAK,KAAK,OAAO,IAAI;GAC9B;EACD,GACA,KAAK,QAAQ,cACd;CACD;AACD;;;;;;;;ACpGA,MAAa,uBAAqC;CACjD,QAAA;CACA,UAAU,QAAQ,mBAAmB,qBAAqB,GAAG;CAC7D,YAAY,QAAQ,kBAAkB,qBAAqB,GAAG;CAC9D,eAAe,eACd,IAAI,kBAAkB,UAAgC;CACvD,aAAa,QAAQ,mBAAmB,qBAAqB,GAAG;CAChE,gBAAgB,eACf,IAAI,mBAAmB,UAAgC;AACzD"}
1
+ {"version":3,"file":"index.cjs","names":["publishTraced","consumeTraced","carrierFromAttributes"],"sources":["../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts","../../src/rabbitmq/driver.ts"],"sourcesContent":["import amqplib from 'amqplib';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\n\nexport interface RabbitMQConnectionConfig {\n\turl: string;\n\texchange?: string;\n\texchangeType?: 'topic' | 'direct' | 'fanout' | 'headers';\n\texchangeOptions?: amqplib.Options.AssertExchange;\n\ttimeout?: number; // Connection timeout in milliseconds (default: 5000)\n}\n\nexport class RabbitMQConnection implements EventConnection {\n\treadonly type = EventPublisherType.RabbitMQ;\n\tprivate connection?: amqplib.ChannelModel;\n\tprivate channel?: amqplib.Channel;\n\tprivate connecting?: Promise<void>;\n\tprivate config: Required<\n\t\tPick<RabbitMQConnectionConfig, 'exchange' | 'exchangeType' | 'timeout'>\n\t> &\n\t\tRabbitMQConnectionConfig;\n\n\tconstructor(config: RabbitMQConnectionConfig) {\n\t\tthis.config = {\n\t\t\t...config,\n\t\t\texchange: config.exchange || 'geekmidas.events',\n\t\t\texchangeType: config.exchangeType || 'topic',\n\t\t\ttimeout: config.timeout ?? 5000,\n\t\t\texchangeOptions: {\n\t\t\t\tdurable: true,\n\t\t\t\t...config.exchangeOptions,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Create a RabbitMQConnection from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString(\n\t\tconnectionString: string,\n\t): Promise<RabbitMQConnection> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\t// Extract connection URL without query params\n\t\tconst baseUrl = `amqp://${url.username ? `${url.username}:${url.password}@` : ''}${url.host}${url.pathname}`;\n\n\t\tconst timeoutParam = params.get('timeout');\n\t\tconst config: RabbitMQConnectionConfig = {\n\t\t\turl: baseUrl,\n\t\t\texchange: params.get('exchange') || 'geekmidas.events',\n\t\t\texchangeType: (params.get('type') as any) || 'topic',\n\t\t\ttimeout: timeoutParam ? Number.parseInt(timeoutParam, 10) : undefined,\n\t\t};\n\n\t\tconst connection = new RabbitMQConnection(config);\n\t\tawait connection.connect();\n\t\treturn connection;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.channel) return;\n\n\t\t// Prevent multiple simultaneous connection attempts\n\t\tif (this.connecting) {\n\t\t\tawait this.connecting;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.connecting = (async () => {\n\t\t\ttry {\n\t\t\t\tconst connection = await amqplib.connect(this.config.url, {\n\t\t\t\t\ttimeout: this.config.timeout,\n\t\t\t\t});\n\t\t\t\tconst channel = await connection.createChannel();\n\n\t\t\t\t// Assert the exchange exists\n\t\t\t\tawait channel.assertExchange(\n\t\t\t\t\tthis.config.exchange!,\n\t\t\t\t\tthis.config.exchangeType!,\n\t\t\t\t\tthis.config.exchangeOptions,\n\t\t\t\t);\n\n\t\t\t\t// Handle connection errors\n\t\t\t\tconnection.on('error', (_err: Error) => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\tconnection.on('close', () => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\t// Only set after successful setup\n\t\t\t\tthis.connection = connection;\n\t\t\t\tthis.channel = channel;\n\t\t\t} catch (error) {\n\t\t\t\tthis.cleanup();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})();\n\n\t\tawait this.connecting;\n\t\tthis.connecting = undefined;\n\t}\n\n\tasync close(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.channel?.close();\n\t\t\tawait this.connection?.close();\n\t\t} catch (_error) {\n\t\t\t// Ignore errors during close\n\t\t} finally {\n\t\t\tthis.cleanup();\n\t\t}\n\t}\n\n\tisConnected(): boolean {\n\t\treturn !!this.channel;\n\t}\n\n\tprivate cleanup(): void {\n\t\tthis.channel = undefined;\n\t\tthis.connection = undefined;\n\t\tthis.connecting = undefined;\n\t}\n\n\t/**\n\t * Get the underlying channel for publishing/subscribing\n\t */\n\tget amqpChannel(): amqplib.Channel | undefined {\n\t\treturn this.channel;\n\t}\n\n\t/**\n\t * Get the exchange name for this connection\n\t */\n\tget exchangeName(): string {\n\t\treturn this.config.exchange;\n\t}\n\n\t/**\n\t * Get the exchange type for this connection\n\t */\n\tget exchangeType(): string {\n\t\treturn this.config.exchangeType;\n\t}\n}\n","// Beside the adapter but apart from its connection module, which imports\n// the broker's client: the publisher and subscriber load that lazily, and\n// importing an error class from it would load it eagerly.\n\n/** The connection opened but has no channel to publish or consume on. */\nexport class RabbitMQChannelUnavailable extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'RabbitMQ connected without a channel. Check the broker is reachable and the connection string names a vhost the user can open channels on.',\n\t\t);\n\t\tthis.name = 'RabbitMQChannelUnavailable';\n\t}\n}\n","import type amqplib from 'amqplib';\nimport { publishTraced } from '../telemetry';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQPublisherOptions {\n\tpublishOptions?: amqplib.Options.Publish;\n}\n\nexport class RabbitMQPublisher<TMessage extends PublishableMessage<string, any>>\n\timplements EventPublisher<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQPublisherOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQPublisher from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQPublisher<TMessage>> {\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\t\treturn new RabbitMQPublisher<TMessage>(connection);\n\t}\n\n\tasync publish(messages: TMessage[]): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\tawait publishTraced(\n\t\t\tmessages,\n\t\t\t(message) => ({\n\t\t\t\tsystem: 'rabbitmq',\n\t\t\t\tdestination: exchange,\n\t\t\t\ttype: message.type,\n\t\t\t}),\n\t\t\tasync (carriers) => {\n\t\t\t\tfor (const [i, message] of messages.entries()) {\n\t\t\t\t\tconst content = Buffer.from(JSON.stringify(message.payload));\n\t\t\t\t\tconst { headers, ...publishOptions } =\n\t\t\t\t\t\tthis.options.publishOptions ?? {};\n\n\t\t\t\t\t// Use message type as routing key for topic exchanges; the trace\n\t\t\t\t\t// context goes in the message's headers.\n\t\t\t\t\tconst published = channel.publish(exchange, message.type, content, {\n\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\ttype: message.type,\n\t\t\t\t\t\tpersistent: true,\n\t\t\t\t\t\t...publishOptions,\n\t\t\t\t\t\t...((headers || carriers[i]) && {\n\t\t\t\t\t\t\theaders: { ...headers, ...carriers[i] },\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\n\t\t\t\t\t// Handle backpressure\n\t\t\t\t\tif (!published) {\n\t\t\t\t\t\tawait new Promise((resolve) => channel.once('drain', resolve));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// Publisher doesn't own the connection\n\t\t// Connection should be closed by whoever created it\n\t}\n}\n","import type amqplib from 'amqplib';\nimport { carrierFromAttributes, consumeTraced } from '../telemetry';\nimport type { EventSubscriber, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQSubscriberOptions {\n\tqueueName?: string; // If not provided, a unique queue will be generated\n\tqueueOptions?: amqplib.Options.AssertQueue;\n\tconsumeOptions?: amqplib.Options.Consume;\n\tprefetch?: number; // Number of messages to prefetch (default: 1)\n}\n\nexport class RabbitMQSubscriber<\n\tTMessage extends PublishableMessage<string, any>,\n> implements EventSubscriber<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQSubscriberOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQSubscriber from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&queueName=myqueue&prefetch=10\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQSubscriber<TMessage>> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\n\t\tconst options: RabbitMQSubscriberOptions = {\n\t\t\tqueueName: params.get('queueName') || undefined,\n\t\t\tprefetch: params.get('prefetch')\n\t\t\t\t? Number.parseInt(params.get('prefetch')!, 10)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\treturn new RabbitMQSubscriber<TMessage>(connection, options);\n\t}\n\n\tasync subscribe(\n\t\tmessages: TMessage['type'][],\n\t\tlistener: (payload: TMessage) => Promise<void>,\n\t): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\t// Set prefetch if specified\n\t\tif (this.options.prefetch) {\n\t\t\tawait channel.prefetch(this.options.prefetch);\n\t\t}\n\n\t\t// Assert queue\n\t\tconst queueName = this.options.queueName || '';\n\t\tconst queueOptions: amqplib.Options.AssertQueue = {\n\t\t\tdurable: true,\n\t\t\t...this.options.queueOptions,\n\t\t};\n\n\t\tconst { queue } = await channel.assertQueue(queueName, queueOptions);\n\n\t\t// Bind queue to exchange for each message type\n\t\tfor (const messageType of messages) {\n\t\t\tawait channel.bindQueue(queue, exchange, messageType);\n\t\t}\n\n\t\t// Consume messages\n\t\tawait channel.consume(\n\t\t\tqueue,\n\t\t\tasync (msg) => {\n\t\t\t\tif (!msg) return;\n\n\t\t\t\ttry {\n\t\t\t\t\t// Parse message payload\n\t\t\t\t\tconst content = msg.content.toString();\n\t\t\t\t\tconst payload = JSON.parse(content);\n\n\t\t\t\t\t// Get message type from properties\n\t\t\t\t\tconst messageType = msg.properties.type;\n\n\t\t\t\t\t// Reconstruct full message\n\t\t\t\t\tconst fullMessage: TMessage = {\n\t\t\t\t\t\ttype: messageType,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t} as TMessage;\n\n\t\t\t\t\t// Call listener, as a child of the publisher's span\n\t\t\t\t\tawait consumeTraced(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsystem: 'rabbitmq',\n\t\t\t\t\t\t\tdestination: queue,\n\t\t\t\t\t\t\ttype: messageType,\n\t\t\t\t\t\t\tmessageId: msg.properties.messageId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcarrierFromAttributes(msg.properties.headers),\n\t\t\t\t\t\t() => listener(fullMessage),\n\t\t\t\t\t);\n\n\t\t\t\t\t// Ack message\n\t\t\t\t\tchannel.ack(msg);\n\t\t\t\t} catch (_error) {\n\t\t\t\t\tchannel.nack(msg, false, true);\n\t\t\t\t}\n\t\t\t},\n\t\t\tthis.options.consumeOptions,\n\t\t);\n\t}\n}\n","import type { EventsDriver } from '../registry';\nimport { EventPublisherType } from '../types';\nimport { RabbitMQConnection } from './RabbitMQConnection';\nimport { RabbitMQPublisher } from './RabbitMQPublisher';\nimport { RabbitMQSubscriber } from './RabbitMQSubscriber';\n\n/**\n * `rabbitmq://` — an AMQP exchange. Register it with\n * `registerEventsDriver(rabbitmqEventsDriver)`; this subpath is the only one\n * that imports `amqplib`.\n */\nexport const rabbitmqEventsDriver: EventsDriver = {\n\tscheme: EventPublisherType.RabbitMQ,\n\tconnect: (url) => RabbitMQConnection.fromConnectionString(url),\n\tpublisher: (url) => RabbitMQPublisher.fromConnectionString(url),\n\tpublisherFor: (connection) =>\n\t\tnew RabbitMQPublisher(connection as RabbitMQConnection),\n\tsubscriber: (url) => RabbitMQSubscriber.fromConnectionString(url),\n\tsubscriberFor: (connection) =>\n\t\tnew RabbitMQSubscriber(connection as RabbitMQConnection),\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/rabbitmq/driver.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts"],"mappings":";;;;;;;;qBAWa,sBAAsB;;;;qBCNtB,mCAAmC;EAC/C;;;;UCFgB;EAChB;EACA;EACA;EACA,kBAAkB,QAAQ,QAAQ;EAClC;;qBAGY,8BAA8B;WACjC,OAAI,mBAAA;UACL;UACA;UACA;UACA;EAKR,YAAY,QAAQ;;;;;SAiBP,qBACZ,2BACE,QAAQ;EAoBL,WAAW;EA6CX,SAAS;EAWf;UAIQ;;;;MASJ,eAAe,QAAQ;;;;MAOvB;;;;MAOA;;;;UC3IY;EAChB,iBAAiB,QAAQ,QAAQ;;qBAGrB,kBAAkB,iBAAiB,4CACpC,eAAe;UAGjB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,kBAAkB;EAOjD,QAAQ,UAAU,aAAa;EAiC/B,SAAS;;;;UC1DC;EAChB;EACA,eAAe,QAAQ,QAAQ;EAC/B,iBAAiB,QAAQ,QAAQ;EACjC;;qBAGY,mBACZ,iBAAiB,4CACL,gBAAgB;UAGnB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,mBAAmB;EAkBlD,UACL,UAAU,oBACV,WAAW,SAAS,aAAa,gBAC/B"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/rabbitmq/driver.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts"],"mappings":";;;;;;;;qBAWa,sBAAsB;;;;qBCNtB,mCAAmC;EAC/C;;;;UCFgB;EAChB;EACA;EACA;EACA,kBAAkB,QAAQ,QAAQ;EAClC;;qBAGY,8BAA8B;WACjC,OAAI,mBAAA;UACL;UACA;UACA;UACA;EAKR,YAAY,QAAQ;;;;;SAiBP,qBACZ,2BACE,QAAQ;EAoBL,WAAW;EA6CX,SAAS;EAWf;UAIQ;;;;MASJ,eAAe,QAAQ;;;;MAOvB;;;;MAOA;;;;UC1IY;EAChB,iBAAiB,QAAQ,QAAQ;;qBAGrB,kBAAkB,iBAAiB,4CACpC,eAAe;UAGjB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,kBAAkB;EAOjD,QAAQ,UAAU,aAAa;EA+C/B,SAAS;;;;UCxEC;EAChB;EACA,eAAe,QAAQ,QAAQ;EAC/B,iBAAiB,QAAQ,QAAQ;EACjC;;qBAGY,mBACZ,iBAAiB,4CACL,gBAAgB;UAGnB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,mBAAmB;EAkBlD,UACL,UAAU,oBACV,WAAW,SAAS,aAAa,gBAC/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/rabbitmq/driver.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts"],"mappings":";;;;;;;;qBAWa,sBAAsB;;;;qBCNtB,mCAAmC;EAC/C;;;;UCFgB;EAChB;EACA;EACA;EACA,kBAAkB,QAAQ,QAAQ;EAClC;;qBAGY,8BAA8B;WACjC,OAAI,mBAAA;UACL;UACA;UACA;UACA;EAKR,YAAY,QAAQ;;;;;SAiBP,qBACZ,2BACE,QAAQ;EAoBL,WAAW;EA6CX,SAAS;EAWf;UAIQ;;;;MASJ,eAAe,QAAQ;;;;MAOvB;;;;MAOA;;;;UC3IY;EAChB,iBAAiB,QAAQ,QAAQ;;qBAGrB,kBAAkB,iBAAiB,4CACpC,eAAe;UAGjB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,kBAAkB;EAOjD,QAAQ,UAAU,aAAa;EAiC/B,SAAS;;;;UC1DC;EAChB;EACA,eAAe,QAAQ,QAAQ;EAC/B,iBAAiB,QAAQ,QAAQ;EACjC;;qBAGY,mBACZ,iBAAiB,4CACL,gBAAgB;UAGnB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,mBAAmB;EAkBlD,UACL,UAAU,oBACV,WAAW,SAAS,aAAa,gBAC/B"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/rabbitmq/driver.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts"],"mappings":";;;;;;;;qBAWa,sBAAsB;;;;qBCNtB,mCAAmC;EAC/C;;;;UCFgB;EAChB;EACA;EACA;EACA,kBAAkB,QAAQ,QAAQ;EAClC;;qBAGY,8BAA8B;WACjC,OAAI,mBAAA;UACL;UACA;UACA;UACA;EAKR,YAAY,QAAQ;;;;;SAiBP,qBACZ,2BACE,QAAQ;EAoBL,WAAW;EA6CX,SAAS;EAWf;UAIQ;;;;MASJ,eAAe,QAAQ;;;;MAOvB;;;;MAOA;;;;UC1IY;EAChB,iBAAiB,QAAQ,QAAQ;;qBAGrB,kBAAkB,iBAAiB,4CACpC,eAAe;UAGjB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,kBAAkB;EAOjD,QAAQ,UAAU,aAAa;EA+C/B,SAAS;;;;UCxEC;EAChB;EACA,eAAe,QAAQ,QAAQ;EAC/B,iBAAiB,QAAQ,QAAQ;EACjC;;qBAGY,mBACZ,iBAAiB,4CACL,gBAAgB;UAGnB;UACA;EAFT,YACS,YAAY,oBACZ,UAAS;;;;;SAOL,qBACZ,iBAAiB,iCAChB,2BAA2B,QAAQ,mBAAmB;EAkBlD,UACL,UAAU,oBACV,WAAW,SAAS,aAAa,gBAC/B"}
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.mjs";
2
- import "../types-Bk5JM6MP.mjs";
2
+ import { a as consumeTraced, r as carrierFromAttributes, s as publishTraced } from "../telemetry-DjjgJMul.mjs";
3
3
  import amqplib from "amqplib";
4
4
  //#region src/rabbitmq/RabbitMQConnection.ts
5
5
  var RabbitMQConnection_exports = /* @__PURE__ */ __exportAll({ RabbitMQConnection: () => RabbitMQConnection });
@@ -134,17 +134,27 @@ var RabbitMQPublisher = class RabbitMQPublisher {
134
134
  const channel = this.connection.amqpChannel;
135
135
  if (!channel) throw new RabbitMQChannelUnavailable();
136
136
  const exchange = this.connection.exchangeName;
137
- for (const message of messages) {
138
- const content = Buffer.from(JSON.stringify(message.payload));
139
- const routingKey = message.type;
140
- if (!channel.publish(exchange, routingKey, content, {
141
- contentType: "application/json",
142
- timestamp: Date.now(),
143
- type: message.type,
144
- persistent: true,
145
- ...this.options.publishOptions
146
- })) await new Promise((resolve) => channel.once("drain", resolve));
147
- }
137
+ await publishTraced(messages, (message) => ({
138
+ system: "rabbitmq",
139
+ destination: exchange,
140
+ type: message.type
141
+ }), async (carriers) => {
142
+ for (const [i, message] of messages.entries()) {
143
+ const content = Buffer.from(JSON.stringify(message.payload));
144
+ const { headers, ...publishOptions } = this.options.publishOptions ?? {};
145
+ if (!channel.publish(exchange, message.type, content, {
146
+ contentType: "application/json",
147
+ timestamp: Date.now(),
148
+ type: message.type,
149
+ persistent: true,
150
+ ...publishOptions,
151
+ ...(headers || carriers[i]) && { headers: {
152
+ ...headers,
153
+ ...carriers[i]
154
+ } }
155
+ })) await new Promise((resolve) => channel.once("drain", resolve));
156
+ }
157
+ });
148
158
  }
149
159
  async close() {}
150
160
  };
@@ -189,10 +199,17 @@ var RabbitMQSubscriber = class RabbitMQSubscriber {
189
199
  try {
190
200
  const content = msg.content.toString();
191
201
  const payload = JSON.parse(content);
192
- await listener({
193
- type: msg.properties.type,
202
+ const messageType = msg.properties.type;
203
+ const fullMessage = {
204
+ type: messageType,
194
205
  payload
195
- });
206
+ };
207
+ await consumeTraced({
208
+ system: "rabbitmq",
209
+ destination: queue,
210
+ type: messageType,
211
+ messageId: msg.properties.messageId
212
+ }, carrierFromAttributes(msg.properties.headers), () => listener(fullMessage));
196
213
  channel.ack(msg);
197
214
  } catch (_error) {
198
215
  channel.nack(msg, false, true);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts","../../src/rabbitmq/driver.ts"],"sourcesContent":["import amqplib from 'amqplib';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\n\nexport interface RabbitMQConnectionConfig {\n\turl: string;\n\texchange?: string;\n\texchangeType?: 'topic' | 'direct' | 'fanout' | 'headers';\n\texchangeOptions?: amqplib.Options.AssertExchange;\n\ttimeout?: number; // Connection timeout in milliseconds (default: 5000)\n}\n\nexport class RabbitMQConnection implements EventConnection {\n\treadonly type = EventPublisherType.RabbitMQ;\n\tprivate connection?: amqplib.ChannelModel;\n\tprivate channel?: amqplib.Channel;\n\tprivate connecting?: Promise<void>;\n\tprivate config: Required<\n\t\tPick<RabbitMQConnectionConfig, 'exchange' | 'exchangeType' | 'timeout'>\n\t> &\n\t\tRabbitMQConnectionConfig;\n\n\tconstructor(config: RabbitMQConnectionConfig) {\n\t\tthis.config = {\n\t\t\t...config,\n\t\t\texchange: config.exchange || 'geekmidas.events',\n\t\t\texchangeType: config.exchangeType || 'topic',\n\t\t\ttimeout: config.timeout ?? 5000,\n\t\t\texchangeOptions: {\n\t\t\t\tdurable: true,\n\t\t\t\t...config.exchangeOptions,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Create a RabbitMQConnection from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString(\n\t\tconnectionString: string,\n\t): Promise<RabbitMQConnection> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\t// Extract connection URL without query params\n\t\tconst baseUrl = `amqp://${url.username ? `${url.username}:${url.password}@` : ''}${url.host}${url.pathname}`;\n\n\t\tconst timeoutParam = params.get('timeout');\n\t\tconst config: RabbitMQConnectionConfig = {\n\t\t\turl: baseUrl,\n\t\t\texchange: params.get('exchange') || 'geekmidas.events',\n\t\t\texchangeType: (params.get('type') as any) || 'topic',\n\t\t\ttimeout: timeoutParam ? Number.parseInt(timeoutParam, 10) : undefined,\n\t\t};\n\n\t\tconst connection = new RabbitMQConnection(config);\n\t\tawait connection.connect();\n\t\treturn connection;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.channel) return;\n\n\t\t// Prevent multiple simultaneous connection attempts\n\t\tif (this.connecting) {\n\t\t\tawait this.connecting;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.connecting = (async () => {\n\t\t\ttry {\n\t\t\t\tconst connection = await amqplib.connect(this.config.url, {\n\t\t\t\t\ttimeout: this.config.timeout,\n\t\t\t\t});\n\t\t\t\tconst channel = await connection.createChannel();\n\n\t\t\t\t// Assert the exchange exists\n\t\t\t\tawait channel.assertExchange(\n\t\t\t\t\tthis.config.exchange!,\n\t\t\t\t\tthis.config.exchangeType!,\n\t\t\t\t\tthis.config.exchangeOptions,\n\t\t\t\t);\n\n\t\t\t\t// Handle connection errors\n\t\t\t\tconnection.on('error', (_err: Error) => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\tconnection.on('close', () => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\t// Only set after successful setup\n\t\t\t\tthis.connection = connection;\n\t\t\t\tthis.channel = channel;\n\t\t\t} catch (error) {\n\t\t\t\tthis.cleanup();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})();\n\n\t\tawait this.connecting;\n\t\tthis.connecting = undefined;\n\t}\n\n\tasync close(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.channel?.close();\n\t\t\tawait this.connection?.close();\n\t\t} catch (_error) {\n\t\t\t// Ignore errors during close\n\t\t} finally {\n\t\t\tthis.cleanup();\n\t\t}\n\t}\n\n\tisConnected(): boolean {\n\t\treturn !!this.channel;\n\t}\n\n\tprivate cleanup(): void {\n\t\tthis.channel = undefined;\n\t\tthis.connection = undefined;\n\t\tthis.connecting = undefined;\n\t}\n\n\t/**\n\t * Get the underlying channel for publishing/subscribing\n\t */\n\tget amqpChannel(): amqplib.Channel | undefined {\n\t\treturn this.channel;\n\t}\n\n\t/**\n\t * Get the exchange name for this connection\n\t */\n\tget exchangeName(): string {\n\t\treturn this.config.exchange;\n\t}\n\n\t/**\n\t * Get the exchange type for this connection\n\t */\n\tget exchangeType(): string {\n\t\treturn this.config.exchangeType;\n\t}\n}\n","// Beside the adapter but apart from its connection module, which imports\n// the broker's client: the publisher and subscriber load that lazily, and\n// importing an error class from it would load it eagerly.\n\n/** The connection opened but has no channel to publish or consume on. */\nexport class RabbitMQChannelUnavailable extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'RabbitMQ connected without a channel. Check the broker is reachable and the connection string names a vhost the user can open channels on.',\n\t\t);\n\t\tthis.name = 'RabbitMQChannelUnavailable';\n\t}\n}\n","import type amqplib from 'amqplib';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQPublisherOptions {\n\tpublishOptions?: amqplib.Options.Publish;\n}\n\nexport class RabbitMQPublisher<TMessage extends PublishableMessage<string, any>>\n\timplements EventPublisher<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQPublisherOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQPublisher from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQPublisher<TMessage>> {\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\t\treturn new RabbitMQPublisher<TMessage>(connection);\n\t}\n\n\tasync publish(messages: TMessage[]): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\tfor (const message of messages) {\n\t\t\tconst content = Buffer.from(JSON.stringify(message.payload));\n\n\t\t\t// Use message type as routing key for topic exchanges\n\t\t\tconst routingKey = message.type;\n\n\t\t\tconst published = channel.publish(exchange, routingKey, content, {\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\ttype: message.type,\n\t\t\t\tpersistent: true,\n\t\t\t\t...this.options.publishOptions,\n\t\t\t});\n\n\t\t\t// Handle backpressure\n\t\t\tif (!published) {\n\t\t\t\tawait new Promise((resolve) => channel.once('drain', resolve));\n\t\t\t}\n\t\t}\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// Publisher doesn't own the connection\n\t\t// Connection should be closed by whoever created it\n\t}\n}\n","import type amqplib from 'amqplib';\nimport type { EventSubscriber, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQSubscriberOptions {\n\tqueueName?: string; // If not provided, a unique queue will be generated\n\tqueueOptions?: amqplib.Options.AssertQueue;\n\tconsumeOptions?: amqplib.Options.Consume;\n\tprefetch?: number; // Number of messages to prefetch (default: 1)\n}\n\nexport class RabbitMQSubscriber<\n\tTMessage extends PublishableMessage<string, any>,\n> implements EventSubscriber<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQSubscriberOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQSubscriber from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&queueName=myqueue&prefetch=10\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQSubscriber<TMessage>> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\n\t\tconst options: RabbitMQSubscriberOptions = {\n\t\t\tqueueName: params.get('queueName') || undefined,\n\t\t\tprefetch: params.get('prefetch')\n\t\t\t\t? Number.parseInt(params.get('prefetch')!, 10)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\treturn new RabbitMQSubscriber<TMessage>(connection, options);\n\t}\n\n\tasync subscribe(\n\t\tmessages: TMessage['type'][],\n\t\tlistener: (payload: TMessage) => Promise<void>,\n\t): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\t// Set prefetch if specified\n\t\tif (this.options.prefetch) {\n\t\t\tawait channel.prefetch(this.options.prefetch);\n\t\t}\n\n\t\t// Assert queue\n\t\tconst queueName = this.options.queueName || '';\n\t\tconst queueOptions: amqplib.Options.AssertQueue = {\n\t\t\tdurable: true,\n\t\t\t...this.options.queueOptions,\n\t\t};\n\n\t\tconst { queue } = await channel.assertQueue(queueName, queueOptions);\n\n\t\t// Bind queue to exchange for each message type\n\t\tfor (const messageType of messages) {\n\t\t\tawait channel.bindQueue(queue, exchange, messageType);\n\t\t}\n\n\t\t// Consume messages\n\t\tawait channel.consume(\n\t\t\tqueue,\n\t\t\tasync (msg) => {\n\t\t\t\tif (!msg) return;\n\n\t\t\t\ttry {\n\t\t\t\t\t// Parse message payload\n\t\t\t\t\tconst content = msg.content.toString();\n\t\t\t\t\tconst payload = JSON.parse(content);\n\n\t\t\t\t\t// Get message type from properties\n\t\t\t\t\tconst messageType = msg.properties.type;\n\n\t\t\t\t\t// Reconstruct full message\n\t\t\t\t\tconst fullMessage: TMessage = {\n\t\t\t\t\t\ttype: messageType,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t} as TMessage;\n\n\t\t\t\t\t// Call listener\n\t\t\t\t\tawait listener(fullMessage);\n\n\t\t\t\t\t// Ack message\n\t\t\t\t\tchannel.ack(msg);\n\t\t\t\t} catch (_error) {\n\t\t\t\t\tchannel.nack(msg, false, true);\n\t\t\t\t}\n\t\t\t},\n\t\t\tthis.options.consumeOptions,\n\t\t);\n\t}\n}\n","import type { EventsDriver } from '../registry';\nimport { EventPublisherType } from '../types';\nimport { RabbitMQConnection } from './RabbitMQConnection';\nimport { RabbitMQPublisher } from './RabbitMQPublisher';\nimport { RabbitMQSubscriber } from './RabbitMQSubscriber';\n\n/**\n * `rabbitmq://` — an AMQP exchange. Register it with\n * `registerEventsDriver(rabbitmqEventsDriver)`; this subpath is the only one\n * that imports `amqplib`.\n */\nexport const rabbitmqEventsDriver: EventsDriver = {\n\tscheme: EventPublisherType.RabbitMQ,\n\tconnect: (url) => RabbitMQConnection.fromConnectionString(url),\n\tpublisher: (url) => RabbitMQPublisher.fromConnectionString(url),\n\tpublisherFor: (connection) =>\n\t\tnew RabbitMQPublisher(connection as RabbitMQConnection),\n\tsubscriber: (url) => RabbitMQSubscriber.fromConnectionString(url),\n\tsubscriberFor: (connection) =>\n\t\tnew RabbitMQSubscriber(connection as RabbitMQConnection),\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/rabbitmq/RabbitMQConnection.ts","../../src/rabbitmq/errors.ts","../../src/rabbitmq/RabbitMQPublisher.ts","../../src/rabbitmq/RabbitMQSubscriber.ts","../../src/rabbitmq/driver.ts"],"sourcesContent":["import amqplib from 'amqplib';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\n\nexport interface RabbitMQConnectionConfig {\n\turl: string;\n\texchange?: string;\n\texchangeType?: 'topic' | 'direct' | 'fanout' | 'headers';\n\texchangeOptions?: amqplib.Options.AssertExchange;\n\ttimeout?: number; // Connection timeout in milliseconds (default: 5000)\n}\n\nexport class RabbitMQConnection implements EventConnection {\n\treadonly type = EventPublisherType.RabbitMQ;\n\tprivate connection?: amqplib.ChannelModel;\n\tprivate channel?: amqplib.Channel;\n\tprivate connecting?: Promise<void>;\n\tprivate config: Required<\n\t\tPick<RabbitMQConnectionConfig, 'exchange' | 'exchangeType' | 'timeout'>\n\t> &\n\t\tRabbitMQConnectionConfig;\n\n\tconstructor(config: RabbitMQConnectionConfig) {\n\t\tthis.config = {\n\t\t\t...config,\n\t\t\texchange: config.exchange || 'geekmidas.events',\n\t\t\texchangeType: config.exchangeType || 'topic',\n\t\t\ttimeout: config.timeout ?? 5000,\n\t\t\texchangeOptions: {\n\t\t\t\tdurable: true,\n\t\t\t\t...config.exchangeOptions,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Create a RabbitMQConnection from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString(\n\t\tconnectionString: string,\n\t): Promise<RabbitMQConnection> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\t// Extract connection URL without query params\n\t\tconst baseUrl = `amqp://${url.username ? `${url.username}:${url.password}@` : ''}${url.host}${url.pathname}`;\n\n\t\tconst timeoutParam = params.get('timeout');\n\t\tconst config: RabbitMQConnectionConfig = {\n\t\t\turl: baseUrl,\n\t\t\texchange: params.get('exchange') || 'geekmidas.events',\n\t\t\texchangeType: (params.get('type') as any) || 'topic',\n\t\t\ttimeout: timeoutParam ? Number.parseInt(timeoutParam, 10) : undefined,\n\t\t};\n\n\t\tconst connection = new RabbitMQConnection(config);\n\t\tawait connection.connect();\n\t\treturn connection;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.channel) return;\n\n\t\t// Prevent multiple simultaneous connection attempts\n\t\tif (this.connecting) {\n\t\t\tawait this.connecting;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.connecting = (async () => {\n\t\t\ttry {\n\t\t\t\tconst connection = await amqplib.connect(this.config.url, {\n\t\t\t\t\ttimeout: this.config.timeout,\n\t\t\t\t});\n\t\t\t\tconst channel = await connection.createChannel();\n\n\t\t\t\t// Assert the exchange exists\n\t\t\t\tawait channel.assertExchange(\n\t\t\t\t\tthis.config.exchange!,\n\t\t\t\t\tthis.config.exchangeType!,\n\t\t\t\t\tthis.config.exchangeOptions,\n\t\t\t\t);\n\n\t\t\t\t// Handle connection errors\n\t\t\t\tconnection.on('error', (_err: Error) => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\tconnection.on('close', () => {\n\t\t\t\t\tthis.cleanup();\n\t\t\t\t});\n\n\t\t\t\t// Only set after successful setup\n\t\t\t\tthis.connection = connection;\n\t\t\t\tthis.channel = channel;\n\t\t\t} catch (error) {\n\t\t\t\tthis.cleanup();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})();\n\n\t\tawait this.connecting;\n\t\tthis.connecting = undefined;\n\t}\n\n\tasync close(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.channel?.close();\n\t\t\tawait this.connection?.close();\n\t\t} catch (_error) {\n\t\t\t// Ignore errors during close\n\t\t} finally {\n\t\t\tthis.cleanup();\n\t\t}\n\t}\n\n\tisConnected(): boolean {\n\t\treturn !!this.channel;\n\t}\n\n\tprivate cleanup(): void {\n\t\tthis.channel = undefined;\n\t\tthis.connection = undefined;\n\t\tthis.connecting = undefined;\n\t}\n\n\t/**\n\t * Get the underlying channel for publishing/subscribing\n\t */\n\tget amqpChannel(): amqplib.Channel | undefined {\n\t\treturn this.channel;\n\t}\n\n\t/**\n\t * Get the exchange name for this connection\n\t */\n\tget exchangeName(): string {\n\t\treturn this.config.exchange;\n\t}\n\n\t/**\n\t * Get the exchange type for this connection\n\t */\n\tget exchangeType(): string {\n\t\treturn this.config.exchangeType;\n\t}\n}\n","// Beside the adapter but apart from its connection module, which imports\n// the broker's client: the publisher and subscriber load that lazily, and\n// importing an error class from it would load it eagerly.\n\n/** The connection opened but has no channel to publish or consume on. */\nexport class RabbitMQChannelUnavailable extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'RabbitMQ connected without a channel. Check the broker is reachable and the connection string names a vhost the user can open channels on.',\n\t\t);\n\t\tthis.name = 'RabbitMQChannelUnavailable';\n\t}\n}\n","import type amqplib from 'amqplib';\nimport { publishTraced } from '../telemetry';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQPublisherOptions {\n\tpublishOptions?: amqplib.Options.Publish;\n}\n\nexport class RabbitMQPublisher<TMessage extends PublishableMessage<string, any>>\n\timplements EventPublisher<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQPublisherOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQPublisher from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&timeout=5000\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQPublisher<TMessage>> {\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\t\treturn new RabbitMQPublisher<TMessage>(connection);\n\t}\n\n\tasync publish(messages: TMessage[]): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\tawait publishTraced(\n\t\t\tmessages,\n\t\t\t(message) => ({\n\t\t\t\tsystem: 'rabbitmq',\n\t\t\t\tdestination: exchange,\n\t\t\t\ttype: message.type,\n\t\t\t}),\n\t\t\tasync (carriers) => {\n\t\t\t\tfor (const [i, message] of messages.entries()) {\n\t\t\t\t\tconst content = Buffer.from(JSON.stringify(message.payload));\n\t\t\t\t\tconst { headers, ...publishOptions } =\n\t\t\t\t\t\tthis.options.publishOptions ?? {};\n\n\t\t\t\t\t// Use message type as routing key for topic exchanges; the trace\n\t\t\t\t\t// context goes in the message's headers.\n\t\t\t\t\tconst published = channel.publish(exchange, message.type, content, {\n\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\ttype: message.type,\n\t\t\t\t\t\tpersistent: true,\n\t\t\t\t\t\t...publishOptions,\n\t\t\t\t\t\t...((headers || carriers[i]) && {\n\t\t\t\t\t\t\theaders: { ...headers, ...carriers[i] },\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\n\t\t\t\t\t// Handle backpressure\n\t\t\t\t\tif (!published) {\n\t\t\t\t\t\tawait new Promise((resolve) => channel.once('drain', resolve));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// Publisher doesn't own the connection\n\t\t// Connection should be closed by whoever created it\n\t}\n}\n","import type amqplib from 'amqplib';\nimport { carrierFromAttributes, consumeTraced } from '../telemetry';\nimport type { EventSubscriber, PublishableMessage } from '../types';\nimport { RabbitMQChannelUnavailable } from './errors';\nimport type { RabbitMQConnection } from './RabbitMQConnection';\n\nexport interface RabbitMQSubscriberOptions {\n\tqueueName?: string; // If not provided, a unique queue will be generated\n\tqueueOptions?: amqplib.Options.AssertQueue;\n\tconsumeOptions?: amqplib.Options.Consume;\n\tprefetch?: number; // Number of messages to prefetch (default: 1)\n}\n\nexport class RabbitMQSubscriber<\n\tTMessage extends PublishableMessage<string, any>,\n> implements EventSubscriber<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: RabbitMQConnection,\n\t\tprivate options: RabbitMQSubscriberOptions = {},\n\t) {}\n\n\t/**\n\t * Create a RabbitMQSubscriber from a connection string\n\t * Format: rabbitmq://user:pass@host:port/vhost?exchange=name&type=topic&queueName=myqueue&prefetch=10\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<RabbitMQSubscriber<TMessage>> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\tconst { RabbitMQConnection } = await import('./RabbitMQConnection');\n\t\tconst connection =\n\t\t\tawait RabbitMQConnection.fromConnectionString(connectionString);\n\n\t\tconst options: RabbitMQSubscriberOptions = {\n\t\t\tqueueName: params.get('queueName') || undefined,\n\t\t\tprefetch: params.get('prefetch')\n\t\t\t\t? Number.parseInt(params.get('prefetch')!, 10)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\treturn new RabbitMQSubscriber<TMessage>(connection, options);\n\t}\n\n\tasync subscribe(\n\t\tmessages: TMessage['type'][],\n\t\tlistener: (payload: TMessage) => Promise<void>,\n\t): Promise<void> {\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\tconst channel = this.connection.amqpChannel;\n\t\tif (!channel) {\n\t\t\tthrow new RabbitMQChannelUnavailable();\n\t\t}\n\n\t\tconst exchange = this.connection.exchangeName;\n\n\t\t// Set prefetch if specified\n\t\tif (this.options.prefetch) {\n\t\t\tawait channel.prefetch(this.options.prefetch);\n\t\t}\n\n\t\t// Assert queue\n\t\tconst queueName = this.options.queueName || '';\n\t\tconst queueOptions: amqplib.Options.AssertQueue = {\n\t\t\tdurable: true,\n\t\t\t...this.options.queueOptions,\n\t\t};\n\n\t\tconst { queue } = await channel.assertQueue(queueName, queueOptions);\n\n\t\t// Bind queue to exchange for each message type\n\t\tfor (const messageType of messages) {\n\t\t\tawait channel.bindQueue(queue, exchange, messageType);\n\t\t}\n\n\t\t// Consume messages\n\t\tawait channel.consume(\n\t\t\tqueue,\n\t\t\tasync (msg) => {\n\t\t\t\tif (!msg) return;\n\n\t\t\t\ttry {\n\t\t\t\t\t// Parse message payload\n\t\t\t\t\tconst content = msg.content.toString();\n\t\t\t\t\tconst payload = JSON.parse(content);\n\n\t\t\t\t\t// Get message type from properties\n\t\t\t\t\tconst messageType = msg.properties.type;\n\n\t\t\t\t\t// Reconstruct full message\n\t\t\t\t\tconst fullMessage: TMessage = {\n\t\t\t\t\t\ttype: messageType,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t} as TMessage;\n\n\t\t\t\t\t// Call listener, as a child of the publisher's span\n\t\t\t\t\tawait consumeTraced(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsystem: 'rabbitmq',\n\t\t\t\t\t\t\tdestination: queue,\n\t\t\t\t\t\t\ttype: messageType,\n\t\t\t\t\t\t\tmessageId: msg.properties.messageId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcarrierFromAttributes(msg.properties.headers),\n\t\t\t\t\t\t() => listener(fullMessage),\n\t\t\t\t\t);\n\n\t\t\t\t\t// Ack message\n\t\t\t\t\tchannel.ack(msg);\n\t\t\t\t} catch (_error) {\n\t\t\t\t\tchannel.nack(msg, false, true);\n\t\t\t\t}\n\t\t\t},\n\t\t\tthis.options.consumeOptions,\n\t\t);\n\t}\n}\n","import type { EventsDriver } from '../registry';\nimport { EventPublisherType } from '../types';\nimport { RabbitMQConnection } from './RabbitMQConnection';\nimport { RabbitMQPublisher } from './RabbitMQPublisher';\nimport { RabbitMQSubscriber } from './RabbitMQSubscriber';\n\n/**\n * `rabbitmq://` — an AMQP exchange. Register it with\n * `registerEventsDriver(rabbitmqEventsDriver)`; this subpath is the only one\n * that imports `amqplib`.\n */\nexport const rabbitmqEventsDriver: EventsDriver = {\n\tscheme: EventPublisherType.RabbitMQ,\n\tconnect: (url) => RabbitMQConnection.fromConnectionString(url),\n\tpublisher: (url) => RabbitMQPublisher.fromConnectionString(url),\n\tpublisherFor: (connection) =>\n\t\tnew RabbitMQPublisher(connection as RabbitMQConnection),\n\tsubscriber: (url) => RabbitMQSubscriber.fromConnectionString(url),\n\tsubscriberFor: (connection) =>\n\t\tnew RabbitMQSubscriber(connection as RabbitMQConnection),\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as UnsupportedEventTransport } from "./types-Bk5JM6MP.mjs";
1
+ import { d as UnsupportedEventTransport } from "./telemetry-DjjgJMul.mjs";
2
2
  //#region src/registry.ts
3
3
  /**
4
4
  * Where each built-in driver lives, so a missing one can be named exactly —
@@ -96,4 +96,4 @@ var UnregisteredEventsScheme = class extends Error {
96
96
  //#endregion
97
97
  export { registeredEventsSchemes as i, eventsDriverFor as n, registerEventsDriver as r, UnregisteredEventsScheme as t };
98
98
 
99
- //# sourceMappingURL=registry-DLnflkMm.mjs.map
99
+ //# sourceMappingURL=registry-DXLY1Xf6.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-DLnflkMm.mjs","names":[],"sources":["../src/registry.ts"],"sourcesContent":["/**\n * Events drivers, keyed by connection-string scheme.\n *\n * The same shape `@geekmidas/storage` and `@geekmidas/cache` use, for the same\n * reason: a topic or a queue is handed one connection string, and the scheme in\n * it (`pgboss://`, `sns://`, …) picks the broker. Which brokers exist is the\n * entry point's decision — a generated server registering pg-boss, a Lambda\n * registering SNS and SQS — so a bundle only ever contains the broker its\n * target uses, and never resolves the others' optional peer dependencies.\n *\n * Registration is explicit rather than an import side effect, because a\n * side-effecting module is exactly what a bundler is entitled to drop.\n */\n\nimport type { PublisherOptions } from './Publisher';\nimport type {\n\tEventConnection,\n\tEventPublisher,\n\tEventSubscriber,\n\tPublishableMessage,\n} from './types';\nimport { EventPublisherType, UnsupportedEventTransport } from './types';\n\ntype AnyMessage = PublishableMessage<string, any>;\n\n/** How a subscriber built from a connection is used, beyond its address. */\nexport interface SubscriberOptions {\n\t/**\n\t * The topic subscribed to. pg-boss needs it, with {@link subscription}, to\n\t * give each subscriber a queue of its own; the other brokers carry the topic\n\t * in their address and ignore it.\n\t */\n\ttopic?: string;\n\t/** The subscriber's name — its own queue on pg-boss. */\n\tsubscription?: string;\n}\n\n/**\n * One broker: the connections, publishers and subscribers for its scheme.\n *\n * A driver owns parsing — the shape of an `sns://` string is SNS's business —\n * and is the only module that imports its broker's client library.\n */\nexport interface EventsDriver {\n\t/**\n\t * The scheme this driver handles, without the colon — `'pgboss'`, `'sns'`.\n\t * It is also the `type` of every connection the driver builds, which is how\n\t * a connection finds its way back here.\n\t */\n\treadonly scheme: `${EventPublisherType}`;\n\t/** A connection, connected, for a connection string. */\n\tconnect(connectionString: string): Promise<EventConnection>;\n\t/** A publisher, with a connection of its own, for a connection string. */\n\tpublisher<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t\toptions: PublisherOptions,\n\t): Promise<EventPublisher<TMessage>>;\n\t/** A publisher on a connection this driver built. */\n\tpublisherFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: PublisherOptions,\n\t): EventPublisher<TMessage>;\n\t/** A subscriber, with a connection of its own, for a connection string. */\n\tsubscriber<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t): Promise<EventSubscriber<TMessage>>;\n\t/** A subscriber on a connection this driver built. */\n\tsubscriberFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: SubscriberOptions,\n\t): EventSubscriber<TMessage>;\n}\n\n/**\n * Where each built-in driver lives, so a missing one can be named exactly —\n * the subpath to import and the export to register.\n */\nconst BUILT_IN: Readonly<Record<string, { subpath: string; driver: string }>> =\n\t{\n\t\t[EventPublisherType.Basic]: {\n\t\t\tsubpath: '@geekmidas/events/basic',\n\t\t\tdriver: 'basicEventsDriver',\n\t\t},\n\t\t[EventPublisherType.PgBoss]: {\n\t\t\tsubpath: '@geekmidas/events/pgboss',\n\t\t\tdriver: 'pgbossEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SNS]: {\n\t\t\tsubpath: '@geekmidas/events/sns',\n\t\t\tdriver: 'snsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SQS]: {\n\t\t\tsubpath: '@geekmidas/events/sqs',\n\t\t\tdriver: 'sqsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.RabbitMQ]: {\n\t\t\tsubpath: '@geekmidas/events/rabbitmq',\n\t\t\tdriver: 'rabbitmqEventsDriver',\n\t\t},\n\t};\n\n/**\n * The registry lives on `globalThis`, so one registration is seen by every\n * copy of this module — the ESM and the CJS build of one install, which a\n * process can load side by side, as `Credentials` already has to allow for.\n */\nconst REGISTRY = Symbol.for('@geekmidas/events/drivers');\n\nfunction drivers(): Map<string, EventsDriver> {\n\tconst global = globalThis as { [REGISTRY]?: Map<string, EventsDriver> };\n\tglobal[REGISTRY] ??= new Map();\n\treturn global[REGISTRY];\n}\n\n/** Make a driver available to `Publisher`, `Subscriber` and friends. Idempotent. */\nexport function registerEventsDriver(driver: EventsDriver): void {\n\tdrivers().set(driver.scheme, driver);\n}\n\n/** Which schemes are currently registered — the useful half of a failure. */\nexport function registeredEventsSchemes(): string[] {\n\treturn [...drivers().keys()].sort();\n}\n\n/**\n * The driver for a scheme — `'pgboss'`, `'pgboss:'`, or a whole connection\n * string, whichever the caller has.\n *\n * @throws {UnregisteredEventsScheme} when the scheme is a broker this package\n * implements but nothing registered its driver.\n * @throws {UnsupportedEventTransport} when no broker here has that scheme.\n */\nexport function eventsDriverFor(\n\tscheme: string,\n\trole: 'publisher' | 'subscriber' | 'connection' = 'connection',\n): EventsDriver {\n\tconst name = schemeOf(scheme);\n\tconst driver = drivers().get(name);\n\tif (driver) return driver;\n\n\tif (BUILT_IN[name]) {\n\t\tthrow new UnregisteredEventsScheme(name, registeredEventsSchemes());\n\t}\n\tthrow new UnsupportedEventTransport(name, role);\n}\n\n/** `pgboss` from `pgboss`, `pgboss:` or `pgboss://…`. */\nfunction schemeOf(value: string): string {\n\tconst separator = value.indexOf(':');\n\treturn separator === -1 ? value : value.slice(0, separator);\n}\n\n/**\n * A connection string for a broker whose driver nothing registered.\n *\n * The broker exists — this is not a typo'd scheme — but the process was never\n * told about it. Usually a script building its own publisher, or a build that\n * registered the drivers for a different target than the one that composed\n * the connection string.\n */\nexport class UnregisteredEventsScheme extends Error {\n\t/** The subpath that exports the missing driver. */\n\treadonly subpath: string;\n\t/** The driver's export name. */\n\treadonly driver: string;\n\n\tconstructor(\n\t\t/** The scheme with no driver, without the colon — `'pgboss'`. */\n\t\treadonly scheme: string,\n\t\t/** What is registered, so the caller can see what was chosen instead. */\n\t\treadonly registered: readonly string[],\n\t) {\n\t\tconst { subpath, driver } = BUILT_IN[scheme] ?? {\n\t\t\tsubpath: `@geekmidas/events/${scheme}`,\n\t\t\tdriver: `${scheme}EventsDriver`,\n\t\t};\n\t\tsuper(\n\t\t\t`No events driver is registered for '${scheme}://'. ` +\n\t\t\t\t(registered.length\n\t\t\t\t\t? `Registered: ${registered.join(', ')}. `\n\t\t\t\t\t: 'Nothing is registered. ') +\n\t\t\t\t`Register it once where the process starts: ` +\n\t\t\t\t`import { registerEventsDriver } from '@geekmidas/events'; ` +\n\t\t\t\t`import { ${driver} } from '${subpath}'; ` +\n\t\t\t\t`registerEventsDriver(${driver});`,\n\t\t);\n\t\tthis.name = 'UnregisteredEventsScheme';\n\t\tthis.subpath = subpath;\n\t\tthis.driver = driver;\n\t}\n}\n"],"mappings":";;;;;;AA6EA,MAAM,WACL;EAC6B,UAAA;EAC3B,SAAS;EACT,QAAQ;CACT;EAC6B,WAAA;EAC5B,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC+B,aAAA;EAC9B,SAAS;EACT,QAAQ;CACT;AACD;;;;;;AAOD,MAAM,WAAW,OAAO,IAAI,2BAA2B;AAEvD,SAAS,UAAqC;CAC7C,MAAM,SAAS;CACf,OAAO,8BAAc,IAAI,IAAI;CAC7B,OAAO,OAAO;AACf;;AAGA,SAAgB,qBAAqB,QAA4B;CAChE,QAAQ,CAAC,CAAC,IAAI,OAAO,QAAQ,MAAM;AACpC;;AAGA,SAAgB,0BAAoC;CACnD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;AACnC;;;;;;;;;AAUA,SAAgB,gBACf,QACA,OAAkD,cACnC;CACf,MAAM,OAAO,SAAS,MAAM;CAC5B,MAAM,SAAS,QAAQ,CAAC,CAAC,IAAI,IAAI;CACjC,IAAI,QAAQ,OAAO;CAEnB,IAAI,SAAS,OACZ,MAAM,IAAI,yBAAyB,MAAM,wBAAwB,CAAC;CAEnE,MAAM,IAAI,0BAA0B,MAAM,IAAI;AAC/C;;AAGA,SAAS,SAAS,OAAuB;CACxC,MAAM,YAAY,MAAM,QAAQ,GAAG;CACnC,OAAO,cAAc,KAAK,QAAQ,MAAM,MAAM,GAAG,SAAS;AAC3D;;;;;;;;;AAUA,IAAa,2BAAb,cAA8C,MAAM;CAQzC;CAEA;;CARV;;CAEA;CAEA,YAEC,QAEA,YACC;EACD,MAAM,EAAE,SAAS,WAAW,SAAS,WAAW;GAC/C,SAAS,qBAAqB;GAC9B,QAAQ,GAAG,OAAO;EACnB;EACA,MACC,uCAAuC,OAAO,WAC5C,WAAW,SACT,eAAe,WAAW,KAAK,IAAI,EAAE,MACrC,6BACH,iHAEY,OAAO,WAAW,QAAQ,0BACd,OAAO,GACjC;EAjBS,KAAA,SAAA;EAEA,KAAA,aAAA;EAgBT,KAAK,OAAO;EACZ,KAAK,UAAU;EACf,KAAK,SAAS;CACf;AACD"}
1
+ {"version":3,"file":"registry-DXLY1Xf6.mjs","names":[],"sources":["../src/registry.ts"],"sourcesContent":["/**\n * Events drivers, keyed by connection-string scheme.\n *\n * The same shape `@geekmidas/storage` and `@geekmidas/cache` use, for the same\n * reason: a topic or a queue is handed one connection string, and the scheme in\n * it (`pgboss://`, `sns://`, …) picks the broker. Which brokers exist is the\n * entry point's decision — a generated server registering pg-boss, a Lambda\n * registering SNS and SQS — so a bundle only ever contains the broker its\n * target uses, and never resolves the others' optional peer dependencies.\n *\n * Registration is explicit rather than an import side effect, because a\n * side-effecting module is exactly what a bundler is entitled to drop.\n */\n\nimport type { PublisherOptions } from './Publisher';\nimport type {\n\tEventConnection,\n\tEventPublisher,\n\tEventSubscriber,\n\tPublishableMessage,\n} from './types';\nimport { EventPublisherType, UnsupportedEventTransport } from './types';\n\ntype AnyMessage = PublishableMessage<string, any>;\n\n/** How a subscriber built from a connection is used, beyond its address. */\nexport interface SubscriberOptions {\n\t/**\n\t * The topic subscribed to. pg-boss needs it, with {@link subscription}, to\n\t * give each subscriber a queue of its own; the other brokers carry the topic\n\t * in their address and ignore it.\n\t */\n\ttopic?: string;\n\t/** The subscriber's name — its own queue on pg-boss. */\n\tsubscription?: string;\n}\n\n/**\n * One broker: the connections, publishers and subscribers for its scheme.\n *\n * A driver owns parsing — the shape of an `sns://` string is SNS's business —\n * and is the only module that imports its broker's client library.\n */\nexport interface EventsDriver {\n\t/**\n\t * The scheme this driver handles, without the colon — `'pgboss'`, `'sns'`.\n\t * It is also the `type` of every connection the driver builds, which is how\n\t * a connection finds its way back here.\n\t */\n\treadonly scheme: `${EventPublisherType}`;\n\t/** A connection, connected, for a connection string. */\n\tconnect(connectionString: string): Promise<EventConnection>;\n\t/** A publisher, with a connection of its own, for a connection string. */\n\tpublisher<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t\toptions: PublisherOptions,\n\t): Promise<EventPublisher<TMessage>>;\n\t/** A publisher on a connection this driver built. */\n\tpublisherFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: PublisherOptions,\n\t): EventPublisher<TMessage>;\n\t/** A subscriber, with a connection of its own, for a connection string. */\n\tsubscriber<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t): Promise<EventSubscriber<TMessage>>;\n\t/** A subscriber on a connection this driver built. */\n\tsubscriberFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: SubscriberOptions,\n\t): EventSubscriber<TMessage>;\n}\n\n/**\n * Where each built-in driver lives, so a missing one can be named exactly —\n * the subpath to import and the export to register.\n */\nconst BUILT_IN: Readonly<Record<string, { subpath: string; driver: string }>> =\n\t{\n\t\t[EventPublisherType.Basic]: {\n\t\t\tsubpath: '@geekmidas/events/basic',\n\t\t\tdriver: 'basicEventsDriver',\n\t\t},\n\t\t[EventPublisherType.PgBoss]: {\n\t\t\tsubpath: '@geekmidas/events/pgboss',\n\t\t\tdriver: 'pgbossEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SNS]: {\n\t\t\tsubpath: '@geekmidas/events/sns',\n\t\t\tdriver: 'snsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SQS]: {\n\t\t\tsubpath: '@geekmidas/events/sqs',\n\t\t\tdriver: 'sqsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.RabbitMQ]: {\n\t\t\tsubpath: '@geekmidas/events/rabbitmq',\n\t\t\tdriver: 'rabbitmqEventsDriver',\n\t\t},\n\t};\n\n/**\n * The registry lives on `globalThis`, so one registration is seen by every\n * copy of this module — the ESM and the CJS build of one install, which a\n * process can load side by side, as `Credentials` already has to allow for.\n */\nconst REGISTRY = Symbol.for('@geekmidas/events/drivers');\n\nfunction drivers(): Map<string, EventsDriver> {\n\tconst global = globalThis as { [REGISTRY]?: Map<string, EventsDriver> };\n\tglobal[REGISTRY] ??= new Map();\n\treturn global[REGISTRY];\n}\n\n/** Make a driver available to `Publisher`, `Subscriber` and friends. Idempotent. */\nexport function registerEventsDriver(driver: EventsDriver): void {\n\tdrivers().set(driver.scheme, driver);\n}\n\n/** Which schemes are currently registered — the useful half of a failure. */\nexport function registeredEventsSchemes(): string[] {\n\treturn [...drivers().keys()].sort();\n}\n\n/**\n * The driver for a scheme — `'pgboss'`, `'pgboss:'`, or a whole connection\n * string, whichever the caller has.\n *\n * @throws {UnregisteredEventsScheme} when the scheme is a broker this package\n * implements but nothing registered its driver.\n * @throws {UnsupportedEventTransport} when no broker here has that scheme.\n */\nexport function eventsDriverFor(\n\tscheme: string,\n\trole: 'publisher' | 'subscriber' | 'connection' = 'connection',\n): EventsDriver {\n\tconst name = schemeOf(scheme);\n\tconst driver = drivers().get(name);\n\tif (driver) return driver;\n\n\tif (BUILT_IN[name]) {\n\t\tthrow new UnregisteredEventsScheme(name, registeredEventsSchemes());\n\t}\n\tthrow new UnsupportedEventTransport(name, role);\n}\n\n/** `pgboss` from `pgboss`, `pgboss:` or `pgboss://…`. */\nfunction schemeOf(value: string): string {\n\tconst separator = value.indexOf(':');\n\treturn separator === -1 ? value : value.slice(0, separator);\n}\n\n/**\n * A connection string for a broker whose driver nothing registered.\n *\n * The broker exists — this is not a typo'd scheme — but the process was never\n * told about it. Usually a script building its own publisher, or a build that\n * registered the drivers for a different target than the one that composed\n * the connection string.\n */\nexport class UnregisteredEventsScheme extends Error {\n\t/** The subpath that exports the missing driver. */\n\treadonly subpath: string;\n\t/** The driver's export name. */\n\treadonly driver: string;\n\n\tconstructor(\n\t\t/** The scheme with no driver, without the colon — `'pgboss'`. */\n\t\treadonly scheme: string,\n\t\t/** What is registered, so the caller can see what was chosen instead. */\n\t\treadonly registered: readonly string[],\n\t) {\n\t\tconst { subpath, driver } = BUILT_IN[scheme] ?? {\n\t\t\tsubpath: `@geekmidas/events/${scheme}`,\n\t\t\tdriver: `${scheme}EventsDriver`,\n\t\t};\n\t\tsuper(\n\t\t\t`No events driver is registered for '${scheme}://'. ` +\n\t\t\t\t(registered.length\n\t\t\t\t\t? `Registered: ${registered.join(', ')}. `\n\t\t\t\t\t: 'Nothing is registered. ') +\n\t\t\t\t`Register it once where the process starts: ` +\n\t\t\t\t`import { registerEventsDriver } from '@geekmidas/events'; ` +\n\t\t\t\t`import { ${driver} } from '${subpath}'; ` +\n\t\t\t\t`registerEventsDriver(${driver});`,\n\t\t);\n\t\tthis.name = 'UnregisteredEventsScheme';\n\t\tthis.subpath = subpath;\n\t\tthis.driver = driver;\n\t}\n}\n"],"mappings":";;;;;;AA6EA,MAAM,WACL;EAC6B,UAAA;EAC3B,SAAS;EACT,QAAQ;CACT;EAC6B,WAAA;EAC5B,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC+B,aAAA;EAC9B,SAAS;EACT,QAAQ;CACT;AACD;;;;;;AAOD,MAAM,WAAW,OAAO,IAAI,2BAA2B;AAEvD,SAAS,UAAqC;CAC7C,MAAM,SAAS;CACf,OAAO,8BAAc,IAAI,IAAI;CAC7B,OAAO,OAAO;AACf;;AAGA,SAAgB,qBAAqB,QAA4B;CAChE,QAAQ,CAAC,CAAC,IAAI,OAAO,QAAQ,MAAM;AACpC;;AAGA,SAAgB,0BAAoC;CACnD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;AACnC;;;;;;;;;AAUA,SAAgB,gBACf,QACA,OAAkD,cACnC;CACf,MAAM,OAAO,SAAS,MAAM;CAC5B,MAAM,SAAS,QAAQ,CAAC,CAAC,IAAI,IAAI;CACjC,IAAI,QAAQ,OAAO;CAEnB,IAAI,SAAS,OACZ,MAAM,IAAI,yBAAyB,MAAM,wBAAwB,CAAC;CAEnE,MAAM,IAAI,0BAA0B,MAAM,IAAI;AAC/C;;AAGA,SAAS,SAAS,OAAuB;CACxC,MAAM,YAAY,MAAM,QAAQ,GAAG;CACnC,OAAO,cAAc,KAAK,QAAQ,MAAM,MAAM,GAAG,SAAS;AAC3D;;;;;;;;;AAUA,IAAa,2BAAb,cAA8C,MAAM;CAQzC;CAEA;;CARV;;CAEA;CAEA,YAEC,QAEA,YACC;EACD,MAAM,EAAE,SAAS,WAAW,SAAS,WAAW;GAC/C,SAAS,qBAAqB;GAC9B,QAAQ,GAAG,OAAO;EACnB;EACA,MACC,uCAAuC,OAAO,WAC5C,WAAW,SACT,eAAe,WAAW,KAAK,IAAI,EAAE,MACrC,6BACH,iHAEY,OAAO,WAAW,QAAQ,0BACd,OAAO,GACjC;EAjBS,KAAA,SAAA;EAEA,KAAA,aAAA;EAgBT,KAAK,OAAO;EACZ,KAAK,UAAU;EACf,KAAK,SAAS;CACf;AACD"}
@@ -1,4 +1,4 @@
1
- const require_types = require("./types-BcZjLxVV.cjs");
1
+ const require_telemetry = require("./telemetry-DG3l807O.cjs");
2
2
  //#region src/registry.ts
3
3
  /**
4
4
  * Where each built-in driver lives, so a missing one can be named exactly —
@@ -58,7 +58,7 @@ function eventsDriverFor(scheme, role = "connection") {
58
58
  const driver = drivers().get(name);
59
59
  if (driver) return driver;
60
60
  if (BUILT_IN[name]) throw new UnregisteredEventsScheme(name, registeredEventsSchemes());
61
- throw new require_types.UnsupportedEventTransport(name, role);
61
+ throw new require_telemetry.UnsupportedEventTransport(name, role);
62
62
  }
63
63
  /** `pgboss` from `pgboss`, `pgboss:` or `pgboss://…`. */
64
64
  function schemeOf(value) {
@@ -119,4 +119,4 @@ Object.defineProperty(exports, "registeredEventsSchemes", {
119
119
  }
120
120
  });
121
121
 
122
- //# sourceMappingURL=registry-DNk5GnGq.cjs.map
122
+ //# sourceMappingURL=registry-DlT36229.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-DNk5GnGq.cjs","names":["UnsupportedEventTransport"],"sources":["../src/registry.ts"],"sourcesContent":["/**\n * Events drivers, keyed by connection-string scheme.\n *\n * The same shape `@geekmidas/storage` and `@geekmidas/cache` use, for the same\n * reason: a topic or a queue is handed one connection string, and the scheme in\n * it (`pgboss://`, `sns://`, …) picks the broker. Which brokers exist is the\n * entry point's decision — a generated server registering pg-boss, a Lambda\n * registering SNS and SQS — so a bundle only ever contains the broker its\n * target uses, and never resolves the others' optional peer dependencies.\n *\n * Registration is explicit rather than an import side effect, because a\n * side-effecting module is exactly what a bundler is entitled to drop.\n */\n\nimport type { PublisherOptions } from './Publisher';\nimport type {\n\tEventConnection,\n\tEventPublisher,\n\tEventSubscriber,\n\tPublishableMessage,\n} from './types';\nimport { EventPublisherType, UnsupportedEventTransport } from './types';\n\ntype AnyMessage = PublishableMessage<string, any>;\n\n/** How a subscriber built from a connection is used, beyond its address. */\nexport interface SubscriberOptions {\n\t/**\n\t * The topic subscribed to. pg-boss needs it, with {@link subscription}, to\n\t * give each subscriber a queue of its own; the other brokers carry the topic\n\t * in their address and ignore it.\n\t */\n\ttopic?: string;\n\t/** The subscriber's name — its own queue on pg-boss. */\n\tsubscription?: string;\n}\n\n/**\n * One broker: the connections, publishers and subscribers for its scheme.\n *\n * A driver owns parsing — the shape of an `sns://` string is SNS's business —\n * and is the only module that imports its broker's client library.\n */\nexport interface EventsDriver {\n\t/**\n\t * The scheme this driver handles, without the colon — `'pgboss'`, `'sns'`.\n\t * It is also the `type` of every connection the driver builds, which is how\n\t * a connection finds its way back here.\n\t */\n\treadonly scheme: `${EventPublisherType}`;\n\t/** A connection, connected, for a connection string. */\n\tconnect(connectionString: string): Promise<EventConnection>;\n\t/** A publisher, with a connection of its own, for a connection string. */\n\tpublisher<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t\toptions: PublisherOptions,\n\t): Promise<EventPublisher<TMessage>>;\n\t/** A publisher on a connection this driver built. */\n\tpublisherFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: PublisherOptions,\n\t): EventPublisher<TMessage>;\n\t/** A subscriber, with a connection of its own, for a connection string. */\n\tsubscriber<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t): Promise<EventSubscriber<TMessage>>;\n\t/** A subscriber on a connection this driver built. */\n\tsubscriberFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: SubscriberOptions,\n\t): EventSubscriber<TMessage>;\n}\n\n/**\n * Where each built-in driver lives, so a missing one can be named exactly —\n * the subpath to import and the export to register.\n */\nconst BUILT_IN: Readonly<Record<string, { subpath: string; driver: string }>> =\n\t{\n\t\t[EventPublisherType.Basic]: {\n\t\t\tsubpath: '@geekmidas/events/basic',\n\t\t\tdriver: 'basicEventsDriver',\n\t\t},\n\t\t[EventPublisherType.PgBoss]: {\n\t\t\tsubpath: '@geekmidas/events/pgboss',\n\t\t\tdriver: 'pgbossEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SNS]: {\n\t\t\tsubpath: '@geekmidas/events/sns',\n\t\t\tdriver: 'snsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SQS]: {\n\t\t\tsubpath: '@geekmidas/events/sqs',\n\t\t\tdriver: 'sqsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.RabbitMQ]: {\n\t\t\tsubpath: '@geekmidas/events/rabbitmq',\n\t\t\tdriver: 'rabbitmqEventsDriver',\n\t\t},\n\t};\n\n/**\n * The registry lives on `globalThis`, so one registration is seen by every\n * copy of this module — the ESM and the CJS build of one install, which a\n * process can load side by side, as `Credentials` already has to allow for.\n */\nconst REGISTRY = Symbol.for('@geekmidas/events/drivers');\n\nfunction drivers(): Map<string, EventsDriver> {\n\tconst global = globalThis as { [REGISTRY]?: Map<string, EventsDriver> };\n\tglobal[REGISTRY] ??= new Map();\n\treturn global[REGISTRY];\n}\n\n/** Make a driver available to `Publisher`, `Subscriber` and friends. Idempotent. */\nexport function registerEventsDriver(driver: EventsDriver): void {\n\tdrivers().set(driver.scheme, driver);\n}\n\n/** Which schemes are currently registered — the useful half of a failure. */\nexport function registeredEventsSchemes(): string[] {\n\treturn [...drivers().keys()].sort();\n}\n\n/**\n * The driver for a scheme — `'pgboss'`, `'pgboss:'`, or a whole connection\n * string, whichever the caller has.\n *\n * @throws {UnregisteredEventsScheme} when the scheme is a broker this package\n * implements but nothing registered its driver.\n * @throws {UnsupportedEventTransport} when no broker here has that scheme.\n */\nexport function eventsDriverFor(\n\tscheme: string,\n\trole: 'publisher' | 'subscriber' | 'connection' = 'connection',\n): EventsDriver {\n\tconst name = schemeOf(scheme);\n\tconst driver = drivers().get(name);\n\tif (driver) return driver;\n\n\tif (BUILT_IN[name]) {\n\t\tthrow new UnregisteredEventsScheme(name, registeredEventsSchemes());\n\t}\n\tthrow new UnsupportedEventTransport(name, role);\n}\n\n/** `pgboss` from `pgboss`, `pgboss:` or `pgboss://…`. */\nfunction schemeOf(value: string): string {\n\tconst separator = value.indexOf(':');\n\treturn separator === -1 ? value : value.slice(0, separator);\n}\n\n/**\n * A connection string for a broker whose driver nothing registered.\n *\n * The broker exists — this is not a typo'd scheme — but the process was never\n * told about it. Usually a script building its own publisher, or a build that\n * registered the drivers for a different target than the one that composed\n * the connection string.\n */\nexport class UnregisteredEventsScheme extends Error {\n\t/** The subpath that exports the missing driver. */\n\treadonly subpath: string;\n\t/** The driver's export name. */\n\treadonly driver: string;\n\n\tconstructor(\n\t\t/** The scheme with no driver, without the colon — `'pgboss'`. */\n\t\treadonly scheme: string,\n\t\t/** What is registered, so the caller can see what was chosen instead. */\n\t\treadonly registered: readonly string[],\n\t) {\n\t\tconst { subpath, driver } = BUILT_IN[scheme] ?? {\n\t\t\tsubpath: `@geekmidas/events/${scheme}`,\n\t\t\tdriver: `${scheme}EventsDriver`,\n\t\t};\n\t\tsuper(\n\t\t\t`No events driver is registered for '${scheme}://'. ` +\n\t\t\t\t(registered.length\n\t\t\t\t\t? `Registered: ${registered.join(', ')}. `\n\t\t\t\t\t: 'Nothing is registered. ') +\n\t\t\t\t`Register it once where the process starts: ` +\n\t\t\t\t`import { registerEventsDriver } from '@geekmidas/events'; ` +\n\t\t\t\t`import { ${driver} } from '${subpath}'; ` +\n\t\t\t\t`registerEventsDriver(${driver});`,\n\t\t);\n\t\tthis.name = 'UnregisteredEventsScheme';\n\t\tthis.subpath = subpath;\n\t\tthis.driver = driver;\n\t}\n}\n"],"mappings":";;;;;;AA6EA,MAAM,WACL;EAC6B,UAAA;EAC3B,SAAS;EACT,QAAQ;CACT;EAC6B,WAAA;EAC5B,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC+B,aAAA;EAC9B,SAAS;EACT,QAAQ;CACT;AACD;;;;;;AAOD,MAAM,WAAW,OAAO,IAAI,2BAA2B;AAEvD,SAAS,UAAqC;CAC7C,MAAM,SAAS;CACf,OAAO,8BAAc,IAAI,IAAI;CAC7B,OAAO,OAAO;AACf;;AAGA,SAAgB,qBAAqB,QAA4B;CAChE,QAAQ,CAAC,CAAC,IAAI,OAAO,QAAQ,MAAM;AACpC;;AAGA,SAAgB,0BAAoC;CACnD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;AACnC;;;;;;;;;AAUA,SAAgB,gBACf,QACA,OAAkD,cACnC;CACf,MAAM,OAAO,SAAS,MAAM;CAC5B,MAAM,SAAS,QAAQ,CAAC,CAAC,IAAI,IAAI;CACjC,IAAI,QAAQ,OAAO;CAEnB,IAAI,SAAS,OACZ,MAAM,IAAI,yBAAyB,MAAM,wBAAwB,CAAC;CAEnE,MAAM,IAAIA,cAAAA,0BAA0B,MAAM,IAAI;AAC/C;;AAGA,SAAS,SAAS,OAAuB;CACxC,MAAM,YAAY,MAAM,QAAQ,GAAG;CACnC,OAAO,cAAc,KAAK,QAAQ,MAAM,MAAM,GAAG,SAAS;AAC3D;;;;;;;;;AAUA,IAAa,2BAAb,cAA8C,MAAM;CAQzC;CAEA;;CARV;;CAEA;CAEA,YAEC,QAEA,YACC;EACD,MAAM,EAAE,SAAS,WAAW,SAAS,WAAW;GAC/C,SAAS,qBAAqB;GAC9B,QAAQ,GAAG,OAAO;EACnB;EACA,MACC,uCAAuC,OAAO,WAC5C,WAAW,SACT,eAAe,WAAW,KAAK,IAAI,EAAE,MACrC,6BACH,iHAEY,OAAO,WAAW,QAAQ,0BACd,OAAO,GACjC;EAjBS,KAAA,SAAA;EAEA,KAAA,aAAA;EAgBT,KAAK,OAAO;EACZ,KAAK,UAAU;EACf,KAAK,SAAS;CACf;AACD"}
1
+ {"version":3,"file":"registry-DlT36229.cjs","names":["UnsupportedEventTransport"],"sources":["../src/registry.ts"],"sourcesContent":["/**\n * Events drivers, keyed by connection-string scheme.\n *\n * The same shape `@geekmidas/storage` and `@geekmidas/cache` use, for the same\n * reason: a topic or a queue is handed one connection string, and the scheme in\n * it (`pgboss://`, `sns://`, …) picks the broker. Which brokers exist is the\n * entry point's decision — a generated server registering pg-boss, a Lambda\n * registering SNS and SQS — so a bundle only ever contains the broker its\n * target uses, and never resolves the others' optional peer dependencies.\n *\n * Registration is explicit rather than an import side effect, because a\n * side-effecting module is exactly what a bundler is entitled to drop.\n */\n\nimport type { PublisherOptions } from './Publisher';\nimport type {\n\tEventConnection,\n\tEventPublisher,\n\tEventSubscriber,\n\tPublishableMessage,\n} from './types';\nimport { EventPublisherType, UnsupportedEventTransport } from './types';\n\ntype AnyMessage = PublishableMessage<string, any>;\n\n/** How a subscriber built from a connection is used, beyond its address. */\nexport interface SubscriberOptions {\n\t/**\n\t * The topic subscribed to. pg-boss needs it, with {@link subscription}, to\n\t * give each subscriber a queue of its own; the other brokers carry the topic\n\t * in their address and ignore it.\n\t */\n\ttopic?: string;\n\t/** The subscriber's name — its own queue on pg-boss. */\n\tsubscription?: string;\n}\n\n/**\n * One broker: the connections, publishers and subscribers for its scheme.\n *\n * A driver owns parsing — the shape of an `sns://` string is SNS's business —\n * and is the only module that imports its broker's client library.\n */\nexport interface EventsDriver {\n\t/**\n\t * The scheme this driver handles, without the colon — `'pgboss'`, `'sns'`.\n\t * It is also the `type` of every connection the driver builds, which is how\n\t * a connection finds its way back here.\n\t */\n\treadonly scheme: `${EventPublisherType}`;\n\t/** A connection, connected, for a connection string. */\n\tconnect(connectionString: string): Promise<EventConnection>;\n\t/** A publisher, with a connection of its own, for a connection string. */\n\tpublisher<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t\toptions: PublisherOptions,\n\t): Promise<EventPublisher<TMessage>>;\n\t/** A publisher on a connection this driver built. */\n\tpublisherFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: PublisherOptions,\n\t): EventPublisher<TMessage>;\n\t/** A subscriber, with a connection of its own, for a connection string. */\n\tsubscriber<TMessage extends AnyMessage>(\n\t\tconnectionString: string,\n\t): Promise<EventSubscriber<TMessage>>;\n\t/** A subscriber on a connection this driver built. */\n\tsubscriberFor<TMessage extends AnyMessage>(\n\t\tconnection: EventConnection,\n\t\toptions: SubscriberOptions,\n\t): EventSubscriber<TMessage>;\n}\n\n/**\n * Where each built-in driver lives, so a missing one can be named exactly —\n * the subpath to import and the export to register.\n */\nconst BUILT_IN: Readonly<Record<string, { subpath: string; driver: string }>> =\n\t{\n\t\t[EventPublisherType.Basic]: {\n\t\t\tsubpath: '@geekmidas/events/basic',\n\t\t\tdriver: 'basicEventsDriver',\n\t\t},\n\t\t[EventPublisherType.PgBoss]: {\n\t\t\tsubpath: '@geekmidas/events/pgboss',\n\t\t\tdriver: 'pgbossEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SNS]: {\n\t\t\tsubpath: '@geekmidas/events/sns',\n\t\t\tdriver: 'snsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.SQS]: {\n\t\t\tsubpath: '@geekmidas/events/sqs',\n\t\t\tdriver: 'sqsEventsDriver',\n\t\t},\n\t\t[EventPublisherType.RabbitMQ]: {\n\t\t\tsubpath: '@geekmidas/events/rabbitmq',\n\t\t\tdriver: 'rabbitmqEventsDriver',\n\t\t},\n\t};\n\n/**\n * The registry lives on `globalThis`, so one registration is seen by every\n * copy of this module — the ESM and the CJS build of one install, which a\n * process can load side by side, as `Credentials` already has to allow for.\n */\nconst REGISTRY = Symbol.for('@geekmidas/events/drivers');\n\nfunction drivers(): Map<string, EventsDriver> {\n\tconst global = globalThis as { [REGISTRY]?: Map<string, EventsDriver> };\n\tglobal[REGISTRY] ??= new Map();\n\treturn global[REGISTRY];\n}\n\n/** Make a driver available to `Publisher`, `Subscriber` and friends. Idempotent. */\nexport function registerEventsDriver(driver: EventsDriver): void {\n\tdrivers().set(driver.scheme, driver);\n}\n\n/** Which schemes are currently registered — the useful half of a failure. */\nexport function registeredEventsSchemes(): string[] {\n\treturn [...drivers().keys()].sort();\n}\n\n/**\n * The driver for a scheme — `'pgboss'`, `'pgboss:'`, or a whole connection\n * string, whichever the caller has.\n *\n * @throws {UnregisteredEventsScheme} when the scheme is a broker this package\n * implements but nothing registered its driver.\n * @throws {UnsupportedEventTransport} when no broker here has that scheme.\n */\nexport function eventsDriverFor(\n\tscheme: string,\n\trole: 'publisher' | 'subscriber' | 'connection' = 'connection',\n): EventsDriver {\n\tconst name = schemeOf(scheme);\n\tconst driver = drivers().get(name);\n\tif (driver) return driver;\n\n\tif (BUILT_IN[name]) {\n\t\tthrow new UnregisteredEventsScheme(name, registeredEventsSchemes());\n\t}\n\tthrow new UnsupportedEventTransport(name, role);\n}\n\n/** `pgboss` from `pgboss`, `pgboss:` or `pgboss://…`. */\nfunction schemeOf(value: string): string {\n\tconst separator = value.indexOf(':');\n\treturn separator === -1 ? value : value.slice(0, separator);\n}\n\n/**\n * A connection string for a broker whose driver nothing registered.\n *\n * The broker exists — this is not a typo'd scheme — but the process was never\n * told about it. Usually a script building its own publisher, or a build that\n * registered the drivers for a different target than the one that composed\n * the connection string.\n */\nexport class UnregisteredEventsScheme extends Error {\n\t/** The subpath that exports the missing driver. */\n\treadonly subpath: string;\n\t/** The driver's export name. */\n\treadonly driver: string;\n\n\tconstructor(\n\t\t/** The scheme with no driver, without the colon — `'pgboss'`. */\n\t\treadonly scheme: string,\n\t\t/** What is registered, so the caller can see what was chosen instead. */\n\t\treadonly registered: readonly string[],\n\t) {\n\t\tconst { subpath, driver } = BUILT_IN[scheme] ?? {\n\t\t\tsubpath: `@geekmidas/events/${scheme}`,\n\t\t\tdriver: `${scheme}EventsDriver`,\n\t\t};\n\t\tsuper(\n\t\t\t`No events driver is registered for '${scheme}://'. ` +\n\t\t\t\t(registered.length\n\t\t\t\t\t? `Registered: ${registered.join(', ')}. `\n\t\t\t\t\t: 'Nothing is registered. ') +\n\t\t\t\t`Register it once where the process starts: ` +\n\t\t\t\t`import { registerEventsDriver } from '@geekmidas/events'; ` +\n\t\t\t\t`import { ${driver} } from '${subpath}'; ` +\n\t\t\t\t`registerEventsDriver(${driver});`,\n\t\t);\n\t\tthis.name = 'UnregisteredEventsScheme';\n\t\tthis.subpath = subpath;\n\t\tthis.driver = driver;\n\t}\n}\n"],"mappings":";;;;;;AA6EA,MAAM,WACL;EAC6B,UAAA;EAC3B,SAAS;EACT,QAAQ;CACT;EAC6B,WAAA;EAC5B,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC0B,QAAA;EACzB,SAAS;EACT,QAAQ;CACT;EAC+B,aAAA;EAC9B,SAAS;EACT,QAAQ;CACT;AACD;;;;;;AAOD,MAAM,WAAW,OAAO,IAAI,2BAA2B;AAEvD,SAAS,UAAqC;CAC7C,MAAM,SAAS;CACf,OAAO,8BAAc,IAAI,IAAI;CAC7B,OAAO,OAAO;AACf;;AAGA,SAAgB,qBAAqB,QAA4B;CAChE,QAAQ,CAAC,CAAC,IAAI,OAAO,QAAQ,MAAM;AACpC;;AAGA,SAAgB,0BAAoC;CACnD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;AACnC;;;;;;;;;AAUA,SAAgB,gBACf,QACA,OAAkD,cACnC;CACf,MAAM,OAAO,SAAS,MAAM;CAC5B,MAAM,SAAS,QAAQ,CAAC,CAAC,IAAI,IAAI;CACjC,IAAI,QAAQ,OAAO;CAEnB,IAAI,SAAS,OACZ,MAAM,IAAI,yBAAyB,MAAM,wBAAwB,CAAC;CAEnE,MAAM,IAAIA,kBAAAA,0BAA0B,MAAM,IAAI;AAC/C;;AAGA,SAAS,SAAS,OAAuB;CACxC,MAAM,YAAY,MAAM,QAAQ,GAAG;CACnC,OAAO,cAAc,KAAK,QAAQ,MAAM,MAAM,GAAG,SAAS;AAC3D;;;;;;;;;AAUA,IAAa,2BAAb,cAA8C,MAAM;CAQzC;CAEA;;CARV;;CAEA;CAEA,YAEC,QAEA,YACC;EACD,MAAM,EAAE,SAAS,WAAW,SAAS,WAAW;GAC/C,SAAS,qBAAqB;GAC9B,QAAQ,GAAG,OAAO;EACnB;EACA,MACC,uCAAuC,OAAO,WAC5C,WAAW,SACT,eAAe,WAAW,KAAK,IAAI,EAAE,MACrC,6BACH,iHAEY,OAAO,WAAW,QAAQ,0BACd,OAAO,GACjC;EAjBS,KAAA,SAAA;EAEA,KAAA,aAAA;EAgBT,KAAK,OAAO;EACZ,KAAK,UAAU;EACf,KAAK,SAAS;CACf;AACD"}
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("../rolldown-runtime-C0BPl7ul.cjs");
3
- require("../types-BcZjLxVV.cjs");
4
- const require_SQSSubscriber = require("../SQSSubscriber-DtRUaZB3.cjs");
3
+ const require_telemetry = require("../telemetry-DG3l807O.cjs");
4
+ const require_SQSSubscriber = require("../SQSSubscriber-COTqWvOk.cjs");
5
5
  const require_sns_snsUrl = require("./snsUrl.cjs");
6
6
  let _aws_sdk_client_sqs = require("@aws-sdk/client-sqs");
7
7
  let _aws_sdk_client_sns = require("@aws-sdk/client-sns");
@@ -87,19 +87,28 @@ var SNSPublisher = class SNSPublisher {
87
87
  async publish(messages) {
88
88
  if (messages.length === 0) return;
89
89
  if (!this.connection.isConnected()) await this.connection.connect();
90
- await Promise.all(messages.map((message) => this.publishMessage(message)));
90
+ const topicArn = this.connection.topicArn;
91
+ const destination = topicArn.split(":").pop() ?? topicArn;
92
+ await require_telemetry.publishTraced(messages, (message) => ({
93
+ system: "aws_sns",
94
+ destination,
95
+ type: message.type
96
+ }), (carriers) => Promise.all(messages.map((message, i) => this.publishMessage(message, carriers[i]))));
91
97
  }
92
- async publishMessage(message) {
98
+ async publishMessage(message, carrier) {
93
99
  const command = new _aws_sdk_client_sns.PublishCommand({
94
100
  TopicArn: this.connection.topicArn,
95
101
  Message: JSON.stringify({
96
102
  type: message.type,
97
103
  payload: message.payload
98
104
  }),
99
- MessageAttributes: { type: {
100
- DataType: "String",
101
- StringValue: message.type
102
- } }
105
+ MessageAttributes: {
106
+ type: {
107
+ DataType: "String",
108
+ StringValue: message.type
109
+ },
110
+ ...require_telemetry.carrierAsAttributes(carrier)
111
+ }
103
112
  });
104
113
  await this.connection.snsClient.send(command);
105
114
  }