@babelqueue/bullmq 1.0.1 → 1.1.0

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.
package/README.md CHANGED
@@ -48,6 +48,24 @@ unmapped URN throws unless you pass `onUnknownUrn`.
48
48
  > services. For raw cross-language queues, other SDKs read/write plain broker
49
49
  > queues directly.
50
50
 
51
+ ## OpenTelemetry tracing (ADR-0028)
52
+
53
+ Cross-hop **span** linkage rides on the out-of-band `HeaderCarrier` from
54
+ [`@babelqueue/core@^1.4.0`](https://www.npmjs.com/package/@babelqueue/core). Pass the carrier produced by
55
+ `@babelqueue/core/otel`'s `publish` to this adapter's `publish({ headers })`; it is carried on
56
+ BullMQ's native `telemetry.metadata` job-options slot (so the envelope — `job.data` — is never touched). On consume, the `processor` surfaces a delivered job's headers to the handler's third argument (and `headersOf(job)` reads them back),
57
+ so the core's `otel` `wrapHandler` starts the consumer span as a true **child** of the producer span.
58
+
59
+ ```ts
60
+ import { trace } from "@opentelemetry/api";
61
+ import { publish as tracedPublish } from "@babelqueue/core/otel";
62
+ import type { HeaderCarrier } from "@babelqueue/core";
63
+
64
+ const headers: HeaderCarrier = {};
65
+ await tracedPublish(trace.getTracer("orders"), urn, data,
66
+ () => adapterPublish(urn, data, { headers }), { headers });
67
+ ```
68
+
51
69
  ## License
52
70
 
53
71
  [MIT](../../LICENSE) © Muhammet Şafak · [babelqueue.com](https://babelqueue.com)
package/dist/index.cjs CHANGED
@@ -20,19 +20,60 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ decodeMetadata: () => decodeMetadata,
24
+ encodeMetadata: () => encodeMetadata,
25
+ headersOf: () => headersOf,
23
26
  processor: () => processor,
24
27
  publish: () => publish
25
28
  });
26
29
  module.exports = __toCommonJS(index_exports);
27
30
  var import_core = require("@babelqueue/core");
31
+
32
+ // src/headers.ts
33
+ function sanitizeHeaders(headers) {
34
+ const out = {};
35
+ if (!headers) return out;
36
+ for (const key of Object.keys(headers)) {
37
+ const value = headers[key];
38
+ if (key === "" || value == null || value === "") continue;
39
+ out[key] = value;
40
+ }
41
+ return out;
42
+ }
43
+ function encodeMetadata(headers) {
44
+ const clean = sanitizeHeaders(headers);
45
+ return Object.keys(clean).length === 0 ? void 0 : JSON.stringify(clean);
46
+ }
47
+ function decodeMetadata(metadata) {
48
+ if (!metadata) return {};
49
+ try {
50
+ const parsed = JSON.parse(metadata);
51
+ if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
52
+ return sanitizeHeaders(parsed);
53
+ } catch {
54
+ return {};
55
+ }
56
+ }
57
+
58
+ // src/index.ts
59
+ function headersOf(job) {
60
+ return decodeMetadata(job.opts?.telemetry?.metadata);
61
+ }
28
62
  async function publish(queue, urn, data, options = {}) {
29
63
  const envelope = import_core.EnvelopeCodec.make(urn, data, {
30
64
  queue: queue.name,
31
65
  traceId: options.traceId
32
66
  });
33
- await queue.add(urn, envelope, options.jobsOptions);
67
+ await queue.add(urn, envelope, withHeaders(options.jobsOptions, options.headers));
34
68
  return envelope.meta.id;
35
69
  }
70
+ function withHeaders(jobsOptions, headers) {
71
+ const metadata = encodeMetadata(headers);
72
+ if (metadata === void 0) return jobsOptions;
73
+ const telemetry = jobsOptions?.telemetry;
74
+ if (telemetry?.metadata != null) return jobsOptions;
75
+ return { ...jobsOptions, telemetry: { ...telemetry, metadata } };
76
+ }
36
77
  function processor(handlers, options = {}) {
37
78
  return async (job) => {
38
79
  const envelope = job.data;
@@ -49,11 +90,14 @@ function processor(handlers, options = {}) {
49
90
  }
50
91
  throw new import_core.UnknownUrnError(urn);
51
92
  }
52
- return handler(envelope, job);
93
+ return handler(envelope, job, headersOf(job));
53
94
  };
54
95
  }
55
96
  // Annotate the CommonJS export names for ESM import in node:
56
97
  0 && (module.exports = {
98
+ decodeMetadata,
99
+ encodeMetadata,
100
+ headersOf,
57
101
  processor,
58
102
  publish
59
103
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * BullMQ adapter for BabelQueue.\n *\n * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes\n * them by URN, so a BullMQ-based Node service speaks the same contract (envelope\n * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and\n * .NET SDKs.\n *\n * import { Queue, Worker } from \"bullmq\";\n * import { publish, processor } from \"@babelqueue/bullmq\";\n *\n * const queue = new Queue(\"orders\", { connection });\n * await publish(queue, \"urn:babel:orders:created\", { order_id: 1042 });\n *\n * new Worker(\"orders\", processor({\n * \"urn:babel:orders:created\": async (env) => { ... },\n * }), { connection });\n */\n\nimport {\n BabelQueueError,\n EnvelopeCodec,\n UnknownUrnError,\n type Envelope,\n type IncomingEnvelope,\n} from \"@babelqueue/core\";\nimport type { Job, JobsOptions, Queue } from \"bullmq\";\n\n/** A URN handler. Receives the validated envelope and the raw BullMQ job. */\nexport type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;\n\n/** A map of URN → handler. */\nexport type BabelHandlers = Record<string, BabelHandler>;\n\n/** Options for {@link publish}. */\nexport interface PublishOptions {\n /** Reuse an existing trace id (trace continuation). */\n traceId?: string;\n /** BullMQ job options (delay, attempts, backoff, …). */\n jobsOptions?: JobsOptions;\n}\n\n/**\n * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the\n * job name is the URN, the job data is the envelope). Returns the message id\n * (`meta.id`).\n */\nexport async function publish(\n queue: Queue,\n urn: string,\n data: Record<string, unknown>,\n options: PublishOptions = {},\n): Promise<string> {\n const envelope = EnvelopeCodec.make(urn, data, {\n queue: queue.name,\n traceId: options.traceId,\n });\n await queue.add(urn, envelope, options.jobsOptions);\n return envelope.meta.id;\n}\n\n/** Options for {@link processor}. */\nexport interface ProcessorOptions {\n /** Called instead of throwing when a job's URN has no handler. */\n onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;\n}\n\n/**\n * Build a BullMQ processor that decodes each job's envelope, validates it, and\n * routes it to the handler registered for its URN. A non-conformant envelope\n * throws (so BullMQ retries / fails the job per its options); an unmapped URN\n * throws unless `onUnknownUrn` is given.\n *\n * new Worker(\"orders\", processor(handlers), { connection });\n */\nexport function processor(\n handlers: BabelHandlers,\n options: ProcessorOptions = {},\n): (job: Job) => Promise<unknown> {\n return async (job: Job): Promise<unknown> => {\n const envelope = job.data as IncomingEnvelope;\n\n if (!EnvelopeCodec.accepts(envelope)) {\n throw new BabelQueueError(\n `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? \"?\"}.`,\n );\n }\n\n const urn = EnvelopeCodec.urn(envelope);\n const handler = handlers[urn];\n if (!handler) {\n if (options.onUnknownUrn) {\n return options.onUnknownUrn(envelope, job);\n }\n throw new UnknownUrnError(urn);\n }\n\n return handler(envelope, job);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA,kBAMO;AAsBP,eAAsB,QACpB,OACA,KACA,MACA,UAA0B,CAAC,GACV;AACjB,QAAM,WAAW,0BAAc,KAAK,KAAK,MAAM;AAAA,IAC7C,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,MAAM,IAAI,KAAK,UAAU,QAAQ,WAAW;AAClD,SAAO,SAAS,KAAK;AACvB;AAgBO,SAAS,UACd,UACA,UAA4B,CAAC,GACG;AAChC,SAAO,OAAO,QAA+B;AAC3C,UAAM,WAAW,IAAI;AAErB,QAAI,CAAC,0BAAc,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,wDAAwD,IAAI,MAAM,GAAG;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,MAAM,0BAAc,IAAI,QAAQ;AACtC,UAAM,UAAU,SAAS,GAAG;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAI,QAAQ,cAAc;AACxB,eAAO,QAAQ,aAAa,UAAU,GAAG;AAAA,MAC3C;AACA,YAAM,IAAI,4BAAgB,GAAG;AAAA,IAC/B;AAEA,WAAO,QAAQ,UAAU,GAAG;AAAA,EAC9B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/headers.ts"],"sourcesContent":["/**\n * BullMQ adapter for BabelQueue.\n *\n * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes\n * them by URN, so a BullMQ-based Node service speaks the same contract (envelope\n * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and\n * .NET SDKs.\n *\n * import { Queue, Worker } from \"bullmq\";\n * import { publish, processor } from \"@babelqueue/bullmq\";\n *\n * const queue = new Queue(\"orders\", { connection });\n * await publish(queue, \"urn:babel:orders:created\", { order_id: 1042 });\n *\n * new Worker(\"orders\", processor({\n * \"urn:babel:orders:created\": async (env) => { ... },\n * }), { connection });\n */\n\nimport {\n BabelQueueError,\n EnvelopeCodec,\n UnknownUrnError,\n type Envelope,\n type HeaderCarrier,\n type IncomingEnvelope,\n} from \"@babelqueue/core\";\nimport type { Job, JobsOptions, Queue } from \"bullmq\";\n\nimport { decodeMetadata, encodeMetadata } from \"./headers.js\";\n\nexport { decodeMetadata, encodeMetadata } from \"./headers.js\";\n\n/**\n * The out-of-band {@link HeaderCarrier} carried by a job, read from BullMQ's native\n * `telemetry.metadata` slot (`job.opts.telemetry.metadata`). Empty for a job published without\n * headers. Pass it to `@babelqueue/core/otel`'s `wrapHandler` to link the consumer span as a child\n * of the producer span (ADR-0028).\n */\nexport function headersOf(job: Job): HeaderCarrier {\n return decodeMetadata(job.opts?.telemetry?.metadata);\n}\n\n/**\n * A URN handler. Receives the validated envelope, the raw BullMQ job, and the out-of-band\n * {@link HeaderCarrier} carried in the job's `telemetry.metadata` (empty when there are none).\n */\nexport type BabelHandler = (envelope: Envelope, job: Job, headers: HeaderCarrier) => unknown | Promise<unknown>;\n\n/** A map of URN → handler. */\nexport type BabelHandlers = Record<string, BabelHandler>;\n\n/** Options for {@link publish}. */\nexport interface PublishOptions {\n /** Reuse an existing trace id (trace continuation). */\n traceId?: string;\n /** BullMQ job options (delay, attempts, backoff, …). */\n jobsOptions?: JobsOptions;\n /**\n * Out-of-band transport headers carried in BullMQ's native `telemetry.metadata` slot (ADR-0028) —\n * e.g. a W3C `traceparent` written by `@babelqueue/core/otel`'s `publish`. The canonical envelope\n * (`job.data`) stays byte-identical (GR-1); an empty/omitted carrier leaves the job options\n * unchanged. An explicit `jobsOptions.telemetry.metadata` wins (it is not clobbered).\n */\n headers?: HeaderCarrier;\n}\n\n/**\n * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the\n * job name is the URN, the job data is the envelope). Returns the message id\n * (`meta.id`).\n *\n * When `options.headers` carries any out-of-band header (e.g. a `traceparent`) it is serialized\n * into the job's `telemetry.metadata` so a consumer can read it back via {@link headersOf} — the\n * envelope itself is never touched.\n */\nexport async function publish(\n queue: Queue,\n urn: string,\n data: Record<string, unknown>,\n options: PublishOptions = {},\n): Promise<string> {\n const envelope = EnvelopeCodec.make(urn, data, {\n queue: queue.name,\n traceId: options.traceId,\n });\n await queue.add(urn, envelope, withHeaders(options.jobsOptions, options.headers));\n return envelope.meta.id;\n}\n\n/**\n * Merge an out-of-band header carrier into a job's `telemetry.metadata` without clobbering an\n * explicit one the caller already set. Returns the original options unchanged when there is nothing\n * to carry, so a header-less publish stays byte-identical.\n */\nfunction withHeaders(jobsOptions: JobsOptions | undefined, headers: HeaderCarrier | undefined): JobsOptions | undefined {\n const metadata = encodeMetadata(headers);\n if (metadata === undefined) return jobsOptions;\n const telemetry = jobsOptions?.telemetry;\n if (telemetry?.metadata != null) return jobsOptions; // an explicit metadata wins (merge-not-clobber)\n return { ...jobsOptions, telemetry: { ...telemetry, metadata } };\n}\n\n/** Options for {@link processor}. */\nexport interface ProcessorOptions {\n /** Called instead of throwing when a job's URN has no handler. */\n onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;\n}\n\n/**\n * Build a BullMQ processor that decodes each job's envelope, validates it, and\n * routes it to the handler registered for its URN. A non-conformant envelope\n * throws (so BullMQ retries / fails the job per its options); an unmapped URN\n * throws unless `onUnknownUrn` is given.\n *\n * new Worker(\"orders\", processor(handlers), { connection });\n */\nexport function processor(\n handlers: BabelHandlers,\n options: ProcessorOptions = {},\n): (job: Job) => Promise<unknown> {\n return async (job: Job): Promise<unknown> => {\n const envelope = job.data as IncomingEnvelope;\n\n if (!EnvelopeCodec.accepts(envelope)) {\n throw new BabelQueueError(\n `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? \"?\"}.`,\n );\n }\n\n const urn = EnvelopeCodec.urn(envelope);\n const handler = handlers[urn];\n if (!handler) {\n if (options.onUnknownUrn) {\n return options.onUnknownUrn(envelope, job);\n }\n throw new UnknownUrnError(urn);\n }\n\n return handler(envelope, job, headersOf(job));\n };\n}\n","/**\n * Pure, dependency-free helpers for the out-of-band transport-header seam (ADR-0028) — the Node\n * adapter mirror of Go's `sanitizeHeaders` and PHP's `Support\\Headers`. They carry an injected\n * {@link HeaderCarrier} (e.g. a W3C `traceparent`) beside the frozen envelope (GR-1), never inside it.\n *\n * BullMQ has no AMQP-style header table; its native context-propagation slot is\n * `JobsOptions.telemetry.metadata` (a string, stored compactly as `tm` in Redis), so the carrier is\n * serialized to JSON there — leaving `job.data` (the canonical envelope) byte-identical.\n */\n\nimport type { HeaderCarrier } from \"@babelqueue/core\";\n\n/**\n * Copy `headers`, dropping blank keys and blank values. Returns an empty object when nothing\n * survives. A nullish input yields an empty object.\n */\nexport function sanitizeHeaders(headers: HeaderCarrier | null | undefined): HeaderCarrier {\n const out: HeaderCarrier = {};\n if (!headers) return out;\n for (const key of Object.keys(headers)) {\n const value = headers[key];\n if (key === \"\" || value == null || value === \"\") continue;\n out[key] = value;\n }\n return out;\n}\n\n/**\n * Serialize a header carrier for BullMQ's `telemetry.metadata` slot, or `undefined` when there is\n * nothing to carry (so a header-less publish leaves `telemetry` unset and the job byte-identical).\n */\nexport function encodeMetadata(headers: HeaderCarrier | null | undefined): string | undefined {\n const clean = sanitizeHeaders(headers);\n return Object.keys(clean).length === 0 ? undefined : JSON.stringify(clean);\n}\n\n/**\n * Read a header carrier back from a BullMQ `telemetry.metadata` string. Returns an empty object for\n * a missing or unparseable value, so a job produced without headers (or by a non-babelqueue\n * producer) consumes with no headers and no error.\n */\nexport function decodeMetadata(metadata: string | undefined | null): HeaderCarrier {\n if (!metadata) return {};\n try {\n const parsed = JSON.parse(metadata) as unknown;\n if (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) return {};\n return sanitizeHeaders(parsed as HeaderCarrier);\n } catch {\n return {};\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA,kBAOO;;;ACVA,SAAS,gBAAgB,SAA0D;AACxF,QAAM,MAAqB,CAAC;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,aAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,QAAQ,MAAM,SAAS,QAAQ,UAAU,GAAI;AACjD,QAAI,GAAG,IAAI;AAAA,EACb;AACA,SAAO;AACT;AAMO,SAAS,eAAe,SAA+D;AAC5F,QAAM,QAAQ,gBAAgB,OAAO;AACrC,SAAO,OAAO,KAAK,KAAK,EAAE,WAAW,IAAI,SAAY,KAAK,UAAU,KAAK;AAC3E;AAOO,SAAS,eAAe,UAAoD;AACjF,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,QAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACnF,WAAO,gBAAgB,MAAuB;AAAA,EAChD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;;;ADXO,SAAS,UAAU,KAAyB;AACjD,SAAO,eAAe,IAAI,MAAM,WAAW,QAAQ;AACrD;AAmCA,eAAsB,QACpB,OACA,KACA,MACA,UAA0B,CAAC,GACV;AACjB,QAAM,WAAW,0BAAc,KAAK,KAAK,MAAM;AAAA,IAC7C,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,MAAM,IAAI,KAAK,UAAU,YAAY,QAAQ,aAAa,QAAQ,OAAO,CAAC;AAChF,SAAO,SAAS,KAAK;AACvB;AAOA,SAAS,YAAY,aAAsC,SAA6D;AACtH,QAAM,WAAW,eAAe,OAAO;AACvC,MAAI,aAAa,OAAW,QAAO;AACnC,QAAM,YAAY,aAAa;AAC/B,MAAI,WAAW,YAAY,KAAM,QAAO;AACxC,SAAO,EAAE,GAAG,aAAa,WAAW,EAAE,GAAG,WAAW,SAAS,EAAE;AACjE;AAgBO,SAAS,UACd,UACA,UAA4B,CAAC,GACG;AAChC,SAAO,OAAO,QAA+B;AAC3C,UAAM,WAAW,IAAI;AAErB,QAAI,CAAC,0BAAc,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,wDAAwD,IAAI,MAAM,GAAG;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,MAAM,0BAAc,IAAI,QAAQ;AACtC,UAAM,UAAU,SAAS,GAAG;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAI,QAAQ,cAAc;AACxB,eAAO,QAAQ,aAAa,UAAU,GAAG;AAAA,MAC3C;AACA,YAAM,IAAI,4BAAgB,GAAG;AAAA,IAC/B;AAEA,WAAO,QAAQ,UAAU,KAAK,UAAU,GAAG,CAAC;AAAA,EAC9C;AACF;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,28 @@
1
- import { Envelope, IncomingEnvelope } from '@babelqueue/core';
1
+ import { HeaderCarrier, Envelope, IncomingEnvelope } from '@babelqueue/core';
2
2
  import { Job, JobsOptions, Queue } from 'bullmq';
3
3
 
4
+ /**
5
+ * Pure, dependency-free helpers for the out-of-band transport-header seam (ADR-0028) — the Node
6
+ * adapter mirror of Go's `sanitizeHeaders` and PHP's `Support\Headers`. They carry an injected
7
+ * {@link HeaderCarrier} (e.g. a W3C `traceparent`) beside the frozen envelope (GR-1), never inside it.
8
+ *
9
+ * BullMQ has no AMQP-style header table; its native context-propagation slot is
10
+ * `JobsOptions.telemetry.metadata` (a string, stored compactly as `tm` in Redis), so the carrier is
11
+ * serialized to JSON there — leaving `job.data` (the canonical envelope) byte-identical.
12
+ */
13
+
14
+ /**
15
+ * Serialize a header carrier for BullMQ's `telemetry.metadata` slot, or `undefined` when there is
16
+ * nothing to carry (so a header-less publish leaves `telemetry` unset and the job byte-identical).
17
+ */
18
+ declare function encodeMetadata(headers: HeaderCarrier | null | undefined): string | undefined;
19
+ /**
20
+ * Read a header carrier back from a BullMQ `telemetry.metadata` string. Returns an empty object for
21
+ * a missing or unparseable value, so a job produced without headers (or by a non-babelqueue
22
+ * producer) consumes with no headers and no error.
23
+ */
24
+ declare function decodeMetadata(metadata: string | undefined | null): HeaderCarrier;
25
+
4
26
  /**
5
27
  * BullMQ adapter for BabelQueue.
6
28
  *
@@ -20,8 +42,18 @@ import { Job, JobsOptions, Queue } from 'bullmq';
20
42
  * }), { connection });
21
43
  */
22
44
 
23
- /** A URN handler. Receives the validated envelope and the raw BullMQ job. */
24
- type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;
45
+ /**
46
+ * The out-of-band {@link HeaderCarrier} carried by a job, read from BullMQ's native
47
+ * `telemetry.metadata` slot (`job.opts.telemetry.metadata`). Empty for a job published without
48
+ * headers. Pass it to `@babelqueue/core/otel`'s `wrapHandler` to link the consumer span as a child
49
+ * of the producer span (ADR-0028).
50
+ */
51
+ declare function headersOf(job: Job): HeaderCarrier;
52
+ /**
53
+ * A URN handler. Receives the validated envelope, the raw BullMQ job, and the out-of-band
54
+ * {@link HeaderCarrier} carried in the job's `telemetry.metadata` (empty when there are none).
55
+ */
56
+ type BabelHandler = (envelope: Envelope, job: Job, headers: HeaderCarrier) => unknown | Promise<unknown>;
25
57
  /** A map of URN → handler. */
26
58
  type BabelHandlers = Record<string, BabelHandler>;
27
59
  /** Options for {@link publish}. */
@@ -30,11 +62,22 @@ interface PublishOptions {
30
62
  traceId?: string;
31
63
  /** BullMQ job options (delay, attempts, backoff, …). */
32
64
  jobsOptions?: JobsOptions;
65
+ /**
66
+ * Out-of-band transport headers carried in BullMQ's native `telemetry.metadata` slot (ADR-0028) —
67
+ * e.g. a W3C `traceparent` written by `@babelqueue/core/otel`'s `publish`. The canonical envelope
68
+ * (`job.data`) stays byte-identical (GR-1); an empty/omitted carrier leaves the job options
69
+ * unchanged. An explicit `jobsOptions.telemetry.metadata` wins (it is not clobbered).
70
+ */
71
+ headers?: HeaderCarrier;
33
72
  }
34
73
  /**
35
74
  * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the
36
75
  * job name is the URN, the job data is the envelope). Returns the message id
37
76
  * (`meta.id`).
77
+ *
78
+ * When `options.headers` carries any out-of-band header (e.g. a `traceparent`) it is serialized
79
+ * into the job's `telemetry.metadata` so a consumer can read it back via {@link headersOf} — the
80
+ * envelope itself is never touched.
38
81
  */
39
82
  declare function publish(queue: Queue, urn: string, data: Record<string, unknown>, options?: PublishOptions): Promise<string>;
40
83
  /** Options for {@link processor}. */
@@ -52,4 +95,4 @@ interface ProcessorOptions {
52
95
  */
53
96
  declare function processor(handlers: BabelHandlers, options?: ProcessorOptions): (job: Job) => Promise<unknown>;
54
97
 
55
- export { type BabelHandler, type BabelHandlers, type ProcessorOptions, type PublishOptions, processor, publish };
98
+ export { type BabelHandler, type BabelHandlers, type ProcessorOptions, type PublishOptions, decodeMetadata, encodeMetadata, headersOf, processor, publish };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,28 @@
1
- import { Envelope, IncomingEnvelope } from '@babelqueue/core';
1
+ import { HeaderCarrier, Envelope, IncomingEnvelope } from '@babelqueue/core';
2
2
  import { Job, JobsOptions, Queue } from 'bullmq';
3
3
 
4
+ /**
5
+ * Pure, dependency-free helpers for the out-of-band transport-header seam (ADR-0028) — the Node
6
+ * adapter mirror of Go's `sanitizeHeaders` and PHP's `Support\Headers`. They carry an injected
7
+ * {@link HeaderCarrier} (e.g. a W3C `traceparent`) beside the frozen envelope (GR-1), never inside it.
8
+ *
9
+ * BullMQ has no AMQP-style header table; its native context-propagation slot is
10
+ * `JobsOptions.telemetry.metadata` (a string, stored compactly as `tm` in Redis), so the carrier is
11
+ * serialized to JSON there — leaving `job.data` (the canonical envelope) byte-identical.
12
+ */
13
+
14
+ /**
15
+ * Serialize a header carrier for BullMQ's `telemetry.metadata` slot, or `undefined` when there is
16
+ * nothing to carry (so a header-less publish leaves `telemetry` unset and the job byte-identical).
17
+ */
18
+ declare function encodeMetadata(headers: HeaderCarrier | null | undefined): string | undefined;
19
+ /**
20
+ * Read a header carrier back from a BullMQ `telemetry.metadata` string. Returns an empty object for
21
+ * a missing or unparseable value, so a job produced without headers (or by a non-babelqueue
22
+ * producer) consumes with no headers and no error.
23
+ */
24
+ declare function decodeMetadata(metadata: string | undefined | null): HeaderCarrier;
25
+
4
26
  /**
5
27
  * BullMQ adapter for BabelQueue.
6
28
  *
@@ -20,8 +42,18 @@ import { Job, JobsOptions, Queue } from 'bullmq';
20
42
  * }), { connection });
21
43
  */
22
44
 
23
- /** A URN handler. Receives the validated envelope and the raw BullMQ job. */
24
- type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;
45
+ /**
46
+ * The out-of-band {@link HeaderCarrier} carried by a job, read from BullMQ's native
47
+ * `telemetry.metadata` slot (`job.opts.telemetry.metadata`). Empty for a job published without
48
+ * headers. Pass it to `@babelqueue/core/otel`'s `wrapHandler` to link the consumer span as a child
49
+ * of the producer span (ADR-0028).
50
+ */
51
+ declare function headersOf(job: Job): HeaderCarrier;
52
+ /**
53
+ * A URN handler. Receives the validated envelope, the raw BullMQ job, and the out-of-band
54
+ * {@link HeaderCarrier} carried in the job's `telemetry.metadata` (empty when there are none).
55
+ */
56
+ type BabelHandler = (envelope: Envelope, job: Job, headers: HeaderCarrier) => unknown | Promise<unknown>;
25
57
  /** A map of URN → handler. */
26
58
  type BabelHandlers = Record<string, BabelHandler>;
27
59
  /** Options for {@link publish}. */
@@ -30,11 +62,22 @@ interface PublishOptions {
30
62
  traceId?: string;
31
63
  /** BullMQ job options (delay, attempts, backoff, …). */
32
64
  jobsOptions?: JobsOptions;
65
+ /**
66
+ * Out-of-band transport headers carried in BullMQ's native `telemetry.metadata` slot (ADR-0028) —
67
+ * e.g. a W3C `traceparent` written by `@babelqueue/core/otel`'s `publish`. The canonical envelope
68
+ * (`job.data`) stays byte-identical (GR-1); an empty/omitted carrier leaves the job options
69
+ * unchanged. An explicit `jobsOptions.telemetry.metadata` wins (it is not clobbered).
70
+ */
71
+ headers?: HeaderCarrier;
33
72
  }
34
73
  /**
35
74
  * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the
36
75
  * job name is the URN, the job data is the envelope). Returns the message id
37
76
  * (`meta.id`).
77
+ *
78
+ * When `options.headers` carries any out-of-band header (e.g. a `traceparent`) it is serialized
79
+ * into the job's `telemetry.metadata` so a consumer can read it back via {@link headersOf} — the
80
+ * envelope itself is never touched.
38
81
  */
39
82
  declare function publish(queue: Queue, urn: string, data: Record<string, unknown>, options?: PublishOptions): Promise<string>;
40
83
  /** Options for {@link processor}. */
@@ -52,4 +95,4 @@ interface ProcessorOptions {
52
95
  */
53
96
  declare function processor(handlers: BabelHandlers, options?: ProcessorOptions): (job: Job) => Promise<unknown>;
54
97
 
55
- export { type BabelHandler, type BabelHandlers, type ProcessorOptions, type PublishOptions, processor, publish };
98
+ export { type BabelHandler, type BabelHandlers, type ProcessorOptions, type PublishOptions, decodeMetadata, encodeMetadata, headersOf, processor, publish };
package/dist/index.js CHANGED
@@ -4,14 +4,52 @@ import {
4
4
  EnvelopeCodec,
5
5
  UnknownUrnError
6
6
  } from "@babelqueue/core";
7
+
8
+ // src/headers.ts
9
+ function sanitizeHeaders(headers) {
10
+ const out = {};
11
+ if (!headers) return out;
12
+ for (const key of Object.keys(headers)) {
13
+ const value = headers[key];
14
+ if (key === "" || value == null || value === "") continue;
15
+ out[key] = value;
16
+ }
17
+ return out;
18
+ }
19
+ function encodeMetadata(headers) {
20
+ const clean = sanitizeHeaders(headers);
21
+ return Object.keys(clean).length === 0 ? void 0 : JSON.stringify(clean);
22
+ }
23
+ function decodeMetadata(metadata) {
24
+ if (!metadata) return {};
25
+ try {
26
+ const parsed = JSON.parse(metadata);
27
+ if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
28
+ return sanitizeHeaders(parsed);
29
+ } catch {
30
+ return {};
31
+ }
32
+ }
33
+
34
+ // src/index.ts
35
+ function headersOf(job) {
36
+ return decodeMetadata(job.opts?.telemetry?.metadata);
37
+ }
7
38
  async function publish(queue, urn, data, options = {}) {
8
39
  const envelope = EnvelopeCodec.make(urn, data, {
9
40
  queue: queue.name,
10
41
  traceId: options.traceId
11
42
  });
12
- await queue.add(urn, envelope, options.jobsOptions);
43
+ await queue.add(urn, envelope, withHeaders(options.jobsOptions, options.headers));
13
44
  return envelope.meta.id;
14
45
  }
46
+ function withHeaders(jobsOptions, headers) {
47
+ const metadata = encodeMetadata(headers);
48
+ if (metadata === void 0) return jobsOptions;
49
+ const telemetry = jobsOptions?.telemetry;
50
+ if (telemetry?.metadata != null) return jobsOptions;
51
+ return { ...jobsOptions, telemetry: { ...telemetry, metadata } };
52
+ }
15
53
  function processor(handlers, options = {}) {
16
54
  return async (job) => {
17
55
  const envelope = job.data;
@@ -28,10 +66,13 @@ function processor(handlers, options = {}) {
28
66
  }
29
67
  throw new UnknownUrnError(urn);
30
68
  }
31
- return handler(envelope, job);
69
+ return handler(envelope, job, headersOf(job));
32
70
  };
33
71
  }
34
72
  export {
73
+ decodeMetadata,
74
+ encodeMetadata,
75
+ headersOf,
35
76
  processor,
36
77
  publish
37
78
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * BullMQ adapter for BabelQueue.\n *\n * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes\n * them by URN, so a BullMQ-based Node service speaks the same contract (envelope\n * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and\n * .NET SDKs.\n *\n * import { Queue, Worker } from \"bullmq\";\n * import { publish, processor } from \"@babelqueue/bullmq\";\n *\n * const queue = new Queue(\"orders\", { connection });\n * await publish(queue, \"urn:babel:orders:created\", { order_id: 1042 });\n *\n * new Worker(\"orders\", processor({\n * \"urn:babel:orders:created\": async (env) => { ... },\n * }), { connection });\n */\n\nimport {\n BabelQueueError,\n EnvelopeCodec,\n UnknownUrnError,\n type Envelope,\n type IncomingEnvelope,\n} from \"@babelqueue/core\";\nimport type { Job, JobsOptions, Queue } from \"bullmq\";\n\n/** A URN handler. Receives the validated envelope and the raw BullMQ job. */\nexport type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;\n\n/** A map of URN → handler. */\nexport type BabelHandlers = Record<string, BabelHandler>;\n\n/** Options for {@link publish}. */\nexport interface PublishOptions {\n /** Reuse an existing trace id (trace continuation). */\n traceId?: string;\n /** BullMQ job options (delay, attempts, backoff, …). */\n jobsOptions?: JobsOptions;\n}\n\n/**\n * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the\n * job name is the URN, the job data is the envelope). Returns the message id\n * (`meta.id`).\n */\nexport async function publish(\n queue: Queue,\n urn: string,\n data: Record<string, unknown>,\n options: PublishOptions = {},\n): Promise<string> {\n const envelope = EnvelopeCodec.make(urn, data, {\n queue: queue.name,\n traceId: options.traceId,\n });\n await queue.add(urn, envelope, options.jobsOptions);\n return envelope.meta.id;\n}\n\n/** Options for {@link processor}. */\nexport interface ProcessorOptions {\n /** Called instead of throwing when a job's URN has no handler. */\n onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;\n}\n\n/**\n * Build a BullMQ processor that decodes each job's envelope, validates it, and\n * routes it to the handler registered for its URN. A non-conformant envelope\n * throws (so BullMQ retries / fails the job per its options); an unmapped URN\n * throws unless `onUnknownUrn` is given.\n *\n * new Worker(\"orders\", processor(handlers), { connection });\n */\nexport function processor(\n handlers: BabelHandlers,\n options: ProcessorOptions = {},\n): (job: Job) => Promise<unknown> {\n return async (job: Job): Promise<unknown> => {\n const envelope = job.data as IncomingEnvelope;\n\n if (!EnvelopeCodec.accepts(envelope)) {\n throw new BabelQueueError(\n `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? \"?\"}.`,\n );\n }\n\n const urn = EnvelopeCodec.urn(envelope);\n const handler = handlers[urn];\n if (!handler) {\n if (options.onUnknownUrn) {\n return options.onUnknownUrn(envelope, job);\n }\n throw new UnknownUrnError(urn);\n }\n\n return handler(envelope, job);\n };\n}\n"],"mappings":";AAmBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAsBP,eAAsB,QACpB,OACA,KACA,MACA,UAA0B,CAAC,GACV;AACjB,QAAM,WAAW,cAAc,KAAK,KAAK,MAAM;AAAA,IAC7C,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,MAAM,IAAI,KAAK,UAAU,QAAQ,WAAW;AAClD,SAAO,SAAS,KAAK;AACvB;AAgBO,SAAS,UACd,UACA,UAA4B,CAAC,GACG;AAChC,SAAO,OAAO,QAA+B;AAC3C,UAAM,WAAW,IAAI;AAErB,QAAI,CAAC,cAAc,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,wDAAwD,IAAI,MAAM,GAAG;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,MAAM,cAAc,IAAI,QAAQ;AACtC,UAAM,UAAU,SAAS,GAAG;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAI,QAAQ,cAAc;AACxB,eAAO,QAAQ,aAAa,UAAU,GAAG;AAAA,MAC3C;AACA,YAAM,IAAI,gBAAgB,GAAG;AAAA,IAC/B;AAEA,WAAO,QAAQ,UAAU,GAAG;AAAA,EAC9B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/headers.ts"],"sourcesContent":["/**\n * BullMQ adapter for BabelQueue.\n *\n * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes\n * them by URN, so a BullMQ-based Node service speaks the same contract (envelope\n * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and\n * .NET SDKs.\n *\n * import { Queue, Worker } from \"bullmq\";\n * import { publish, processor } from \"@babelqueue/bullmq\";\n *\n * const queue = new Queue(\"orders\", { connection });\n * await publish(queue, \"urn:babel:orders:created\", { order_id: 1042 });\n *\n * new Worker(\"orders\", processor({\n * \"urn:babel:orders:created\": async (env) => { ... },\n * }), { connection });\n */\n\nimport {\n BabelQueueError,\n EnvelopeCodec,\n UnknownUrnError,\n type Envelope,\n type HeaderCarrier,\n type IncomingEnvelope,\n} from \"@babelqueue/core\";\nimport type { Job, JobsOptions, Queue } from \"bullmq\";\n\nimport { decodeMetadata, encodeMetadata } from \"./headers.js\";\n\nexport { decodeMetadata, encodeMetadata } from \"./headers.js\";\n\n/**\n * The out-of-band {@link HeaderCarrier} carried by a job, read from BullMQ's native\n * `telemetry.metadata` slot (`job.opts.telemetry.metadata`). Empty for a job published without\n * headers. Pass it to `@babelqueue/core/otel`'s `wrapHandler` to link the consumer span as a child\n * of the producer span (ADR-0028).\n */\nexport function headersOf(job: Job): HeaderCarrier {\n return decodeMetadata(job.opts?.telemetry?.metadata);\n}\n\n/**\n * A URN handler. Receives the validated envelope, the raw BullMQ job, and the out-of-band\n * {@link HeaderCarrier} carried in the job's `telemetry.metadata` (empty when there are none).\n */\nexport type BabelHandler = (envelope: Envelope, job: Job, headers: HeaderCarrier) => unknown | Promise<unknown>;\n\n/** A map of URN → handler. */\nexport type BabelHandlers = Record<string, BabelHandler>;\n\n/** Options for {@link publish}. */\nexport interface PublishOptions {\n /** Reuse an existing trace id (trace continuation). */\n traceId?: string;\n /** BullMQ job options (delay, attempts, backoff, …). */\n jobsOptions?: JobsOptions;\n /**\n * Out-of-band transport headers carried in BullMQ's native `telemetry.metadata` slot (ADR-0028) —\n * e.g. a W3C `traceparent` written by `@babelqueue/core/otel`'s `publish`. The canonical envelope\n * (`job.data`) stays byte-identical (GR-1); an empty/omitted carrier leaves the job options\n * unchanged. An explicit `jobsOptions.telemetry.metadata` wins (it is not clobbered).\n */\n headers?: HeaderCarrier;\n}\n\n/**\n * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the\n * job name is the URN, the job data is the envelope). Returns the message id\n * (`meta.id`).\n *\n * When `options.headers` carries any out-of-band header (e.g. a `traceparent`) it is serialized\n * into the job's `telemetry.metadata` so a consumer can read it back via {@link headersOf} — the\n * envelope itself is never touched.\n */\nexport async function publish(\n queue: Queue,\n urn: string,\n data: Record<string, unknown>,\n options: PublishOptions = {},\n): Promise<string> {\n const envelope = EnvelopeCodec.make(urn, data, {\n queue: queue.name,\n traceId: options.traceId,\n });\n await queue.add(urn, envelope, withHeaders(options.jobsOptions, options.headers));\n return envelope.meta.id;\n}\n\n/**\n * Merge an out-of-band header carrier into a job's `telemetry.metadata` without clobbering an\n * explicit one the caller already set. Returns the original options unchanged when there is nothing\n * to carry, so a header-less publish stays byte-identical.\n */\nfunction withHeaders(jobsOptions: JobsOptions | undefined, headers: HeaderCarrier | undefined): JobsOptions | undefined {\n const metadata = encodeMetadata(headers);\n if (metadata === undefined) return jobsOptions;\n const telemetry = jobsOptions?.telemetry;\n if (telemetry?.metadata != null) return jobsOptions; // an explicit metadata wins (merge-not-clobber)\n return { ...jobsOptions, telemetry: { ...telemetry, metadata } };\n}\n\n/** Options for {@link processor}. */\nexport interface ProcessorOptions {\n /** Called instead of throwing when a job's URN has no handler. */\n onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;\n}\n\n/**\n * Build a BullMQ processor that decodes each job's envelope, validates it, and\n * routes it to the handler registered for its URN. A non-conformant envelope\n * throws (so BullMQ retries / fails the job per its options); an unmapped URN\n * throws unless `onUnknownUrn` is given.\n *\n * new Worker(\"orders\", processor(handlers), { connection });\n */\nexport function processor(\n handlers: BabelHandlers,\n options: ProcessorOptions = {},\n): (job: Job) => Promise<unknown> {\n return async (job: Job): Promise<unknown> => {\n const envelope = job.data as IncomingEnvelope;\n\n if (!EnvelopeCodec.accepts(envelope)) {\n throw new BabelQueueError(\n `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? \"?\"}.`,\n );\n }\n\n const urn = EnvelopeCodec.urn(envelope);\n const handler = handlers[urn];\n if (!handler) {\n if (options.onUnknownUrn) {\n return options.onUnknownUrn(envelope, job);\n }\n throw new UnknownUrnError(urn);\n }\n\n return handler(envelope, job, headersOf(job));\n };\n}\n","/**\n * Pure, dependency-free helpers for the out-of-band transport-header seam (ADR-0028) — the Node\n * adapter mirror of Go's `sanitizeHeaders` and PHP's `Support\\Headers`. They carry an injected\n * {@link HeaderCarrier} (e.g. a W3C `traceparent`) beside the frozen envelope (GR-1), never inside it.\n *\n * BullMQ has no AMQP-style header table; its native context-propagation slot is\n * `JobsOptions.telemetry.metadata` (a string, stored compactly as `tm` in Redis), so the carrier is\n * serialized to JSON there — leaving `job.data` (the canonical envelope) byte-identical.\n */\n\nimport type { HeaderCarrier } from \"@babelqueue/core\";\n\n/**\n * Copy `headers`, dropping blank keys and blank values. Returns an empty object when nothing\n * survives. A nullish input yields an empty object.\n */\nexport function sanitizeHeaders(headers: HeaderCarrier | null | undefined): HeaderCarrier {\n const out: HeaderCarrier = {};\n if (!headers) return out;\n for (const key of Object.keys(headers)) {\n const value = headers[key];\n if (key === \"\" || value == null || value === \"\") continue;\n out[key] = value;\n }\n return out;\n}\n\n/**\n * Serialize a header carrier for BullMQ's `telemetry.metadata` slot, or `undefined` when there is\n * nothing to carry (so a header-less publish leaves `telemetry` unset and the job byte-identical).\n */\nexport function encodeMetadata(headers: HeaderCarrier | null | undefined): string | undefined {\n const clean = sanitizeHeaders(headers);\n return Object.keys(clean).length === 0 ? undefined : JSON.stringify(clean);\n}\n\n/**\n * Read a header carrier back from a BullMQ `telemetry.metadata` string. Returns an empty object for\n * a missing or unparseable value, so a job produced without headers (or by a non-babelqueue\n * producer) consumes with no headers and no error.\n */\nexport function decodeMetadata(metadata: string | undefined | null): HeaderCarrier {\n if (!metadata) return {};\n try {\n const parsed = JSON.parse(metadata) as unknown;\n if (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) return {};\n return sanitizeHeaders(parsed as HeaderCarrier);\n } catch {\n return {};\n }\n}\n"],"mappings":";AAmBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;;;ACVA,SAAS,gBAAgB,SAA0D;AACxF,QAAM,MAAqB,CAAC;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,aAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,QAAQ,MAAM,SAAS,QAAQ,UAAU,GAAI;AACjD,QAAI,GAAG,IAAI;AAAA,EACb;AACA,SAAO;AACT;AAMO,SAAS,eAAe,SAA+D;AAC5F,QAAM,QAAQ,gBAAgB,OAAO;AACrC,SAAO,OAAO,KAAK,KAAK,EAAE,WAAW,IAAI,SAAY,KAAK,UAAU,KAAK;AAC3E;AAOO,SAAS,eAAe,UAAoD;AACjF,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,QAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACnF,WAAO,gBAAgB,MAAuB;AAAA,EAChD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;;;ADXO,SAAS,UAAU,KAAyB;AACjD,SAAO,eAAe,IAAI,MAAM,WAAW,QAAQ;AACrD;AAmCA,eAAsB,QACpB,OACA,KACA,MACA,UAA0B,CAAC,GACV;AACjB,QAAM,WAAW,cAAc,KAAK,KAAK,MAAM;AAAA,IAC7C,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,MAAM,IAAI,KAAK,UAAU,YAAY,QAAQ,aAAa,QAAQ,OAAO,CAAC;AAChF,SAAO,SAAS,KAAK;AACvB;AAOA,SAAS,YAAY,aAAsC,SAA6D;AACtH,QAAM,WAAW,eAAe,OAAO;AACvC,MAAI,aAAa,OAAW,QAAO;AACnC,QAAM,YAAY,aAAa;AAC/B,MAAI,WAAW,YAAY,KAAM,QAAO;AACxC,SAAO,EAAE,GAAG,aAAa,WAAW,EAAE,GAAG,WAAW,SAAS,EAAE;AACjE;AAgBO,SAAS,UACd,UACA,UAA4B,CAAC,GACG;AAChC,SAAO,OAAO,QAA+B;AAC3C,UAAM,WAAW,IAAI;AAErB,QAAI,CAAC,cAAc,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,wDAAwD,IAAI,MAAM,GAAG;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,MAAM,cAAc,IAAI,QAAQ;AACtC,UAAM,UAAU,SAAS,GAAG;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAI,QAAQ,cAAc;AACxB,eAAO,QAAQ,aAAa,UAAU,GAAG;AAAA,MAC3C;AACA,YAAM,IAAI,gBAAgB,GAAG;AAAA,IAC/B;AAEA,WAAO,QAAQ,UAAU,KAAK,UAAU,GAAG,CAAC;AAAA,EAC9C;AACF;","names":[]}
package/package.json CHANGED
@@ -1,8 +1,15 @@
1
1
  {
2
2
  "name": "@babelqueue/bullmq",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "BullMQ adapter for BabelQueue — canonical-envelope jobs and a URN-routed processor.",
5
- "keywords": ["babelqueue", "bullmq", "queue", "polyglot", "redis", "messaging"],
5
+ "keywords": [
6
+ "babelqueue",
7
+ "bullmq",
8
+ "queue",
9
+ "polyglot",
10
+ "redis",
11
+ "messaging"
12
+ ],
6
13
  "homepage": "https://babelqueue.com",
7
14
  "bugs": {
8
15
  "url": "https://github.com/BabelQueue/babelqueue-node-adapters/issues"
@@ -30,7 +37,9 @@
30
37
  "main": "./dist/index.cjs",
31
38
  "module": "./dist/index.js",
32
39
  "types": "./dist/index.d.ts",
33
- "files": ["dist"],
40
+ "files": [
41
+ "dist"
42
+ ],
34
43
  "sideEffects": false,
35
44
  "engines": {
36
45
  "node": ">=18"
@@ -41,7 +50,7 @@
41
50
  "test": "node --import tsx --test test/*.test.ts"
42
51
  },
43
52
  "dependencies": {
44
- "@babelqueue/core": "^1.0.0"
53
+ "@babelqueue/core": "^1.4.0"
45
54
  },
46
55
  "peerDependencies": {
47
56
  "bullmq": "^5.0.0"