@amqp-contract/worker 0.13.0 → 0.14.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/dist/index.cjs CHANGED
@@ -1,4 +1,5 @@
1
1
  let _amqp_contract_core = require("@amqp-contract/core");
2
+ let _amqp_contract_contract = require("@amqp-contract/contract");
2
3
  let _swan_io_boxed = require("@swan-io/boxed");
3
4
  let node_zlib = require("node:zlib");
4
5
  let node_util = require("node:util");
@@ -374,7 +375,8 @@ var TypedAmqpWorker = class TypedAmqpWorker {
374
375
  * TypeScript guarantees consumer and handler exist for valid consumer names.
375
376
  */
376
377
  consume(consumerName) {
377
- const consumer = this.contract.consumers[consumerName];
378
+ const consumerEntry = this.contract.consumers[consumerName];
379
+ const consumer = (0, _amqp_contract_contract.extractConsumer)(consumerEntry);
378
380
  const handler = this.actualHandlers[consumerName];
379
381
  return this.consumeSingle(consumerName, consumer, handler);
380
382
  }
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Logger, TechnicalError, TelemetryProvider } from "@amqp-contract/core";
2
2
  import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
3
- import { ConsumerDefinition, ContractDefinition, InferConsumerNames, MessageDefinition } from "@amqp-contract/contract";
3
+ import { ConsumerDefinition, ConsumerEntry, ContractDefinitionInput, InferConsumerNames, MessageDefinition } from "@amqp-contract/contract";
4
4
  import { Future, Result } from "@swan-io/boxed";
5
5
  import { ConsumeMessage } from "amqplib";
6
6
  import { StandardSchemaV1 } from "@standard-schema/spec";
@@ -165,31 +165,39 @@ declare function nonRetryable(message: string, cause?: unknown): NonRetryableErr
165
165
  */
166
166
  type InferSchemaInput<TSchema extends StandardSchemaV1> = TSchema extends StandardSchemaV1<infer TInput> ? TInput : never;
167
167
  /**
168
- * Infer consumer message payload input type
168
+ * Extract the ConsumerDefinition from any consumer entry type.
169
+ * Handles ConsumerDefinition, EventConsumerResult, and CommandConsumerConfig.
169
170
  */
170
- type ConsumerInferPayloadInput<TConsumer extends ConsumerDefinition> = InferSchemaInput<TConsumer["message"]["payload"]>;
171
+ type ExtractConsumerDefinition<T extends ConsumerEntry> = T extends ConsumerDefinition ? T : T extends {
172
+ consumer: ConsumerDefinition;
173
+ } ? T["consumer"] : never;
174
+ /**
175
+ * Infer consumer message payload input type.
176
+ * Works with any consumer entry type by first extracting the ConsumerDefinition.
177
+ */
178
+ type ConsumerInferPayloadInput<TConsumer extends ConsumerEntry> = ExtractConsumerDefinition<TConsumer> extends ConsumerDefinition ? InferSchemaInput<ExtractConsumerDefinition<TConsumer>["message"]["payload"]> : never;
171
179
  /**
172
180
  * Infer consumer message headers input type
173
181
  * Returns undefined if no headers schema is defined
174
182
  */
175
- type ConsumerInferHeadersInput<TConsumer extends ConsumerDefinition> = TConsumer["message"] extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaInput<THeaders> : undefined : undefined;
183
+ type ConsumerInferHeadersInput<TConsumer extends ConsumerEntry> = ExtractConsumerDefinition<TConsumer> extends ConsumerDefinition ? ExtractConsumerDefinition<TConsumer>["message"] extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaInput<THeaders> : undefined : undefined : undefined;
176
184
  /**
177
185
  * Infer all consumers from contract
178
186
  */
179
- type InferConsumers<TContract extends ContractDefinition> = NonNullable<TContract["consumers"]>;
187
+ type InferConsumers<TContract extends ContractDefinitionInput> = NonNullable<TContract["consumers"]>;
180
188
  /**
181
- * Get specific consumer definition from contract
189
+ * Get specific consumer entry from contract
182
190
  */
183
- type InferConsumer<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
191
+ type InferConsumer<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
184
192
  /**
185
193
  * Infer the payload type for a specific consumer
186
194
  */
187
- type WorkerInferConsumerPayload<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferPayloadInput<InferConsumer<TContract, TName>>;
195
+ type WorkerInferConsumerPayload<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = ConsumerInferPayloadInput<InferConsumer<TContract, TName>>;
188
196
  /**
189
197
  * Infer the headers type for a specific consumer
190
198
  * Returns undefined if no headers schema is defined
191
199
  */
192
- type WorkerInferConsumerHeaders<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferHeadersInput<InferConsumer<TContract, TName>>;
200
+ type WorkerInferConsumerHeaders<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = ConsumerInferHeadersInput<InferConsumer<TContract, TName>>;
193
201
  /**
194
202
  * A consumed message containing parsed payload and headers.
195
203
  *
@@ -220,7 +228,7 @@ type WorkerConsumedMessage<TPayload, THeaders$1 = undefined> = {
220
228
  * Infer the full consumed message type for a specific consumer.
221
229
  * Includes both payload and headers (if defined).
222
230
  */
223
- type WorkerInferConsumedMessage<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
231
+ type WorkerInferConsumedMessage<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
224
232
  /**
225
233
  * Consumer handler type for a specific consumer.
226
234
  * Returns a `Future<Result<void, HandlerError>>` for explicit error handling.
@@ -245,7 +253,7 @@ type WorkerInferConsumedMessage<TContract extends ContractDefinition, TName exte
245
253
  * };
246
254
  * ```
247
255
  */
248
- type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<void, HandlerError>>;
256
+ type WorkerInferConsumerHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<void, HandlerError>>;
249
257
  /**
250
258
  * Handler entry for a consumer - either a function or a tuple of [handler, options].
251
259
  *
@@ -256,7 +264,7 @@ type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName exte
256
264
  * Note: Retry configuration is now defined at the queue level in the contract,
257
265
  * not at the handler level. See `QueueDefinition.retry` for configuration options.
258
266
  */
259
- type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName> | readonly [WorkerInferConsumerHandler<TContract, TName>, {
267
+ type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName> | readonly [WorkerInferConsumerHandler<TContract, TName>, {
260
268
  prefetch?: number;
261
269
  }];
262
270
  /**
@@ -273,19 +281,19 @@ type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinition, TName
273
281
  * };
274
282
  * ```
275
283
  */
276
- type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandlerEntry<TContract, K> };
284
+ type WorkerInferConsumerHandlers<TContract extends ContractDefinitionInput> = { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandlerEntry<TContract, K> };
277
285
  /**
278
286
  * @deprecated Use `WorkerInferConsumerHandler` instead. Will be removed in next major version.
279
287
  */
280
- type WorkerInferSafeConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName>;
288
+ type WorkerInferSafeConsumerHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName>;
281
289
  /**
282
290
  * @deprecated Use `WorkerInferConsumerHandlerEntry` instead. Will be removed in next major version.
283
291
  */
284
- type WorkerInferSafeConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandlerEntry<TContract, TName>;
292
+ type WorkerInferSafeConsumerHandlerEntry<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandlerEntry<TContract, TName>;
285
293
  /**
286
294
  * @deprecated Use `WorkerInferConsumerHandlers` instead. Will be removed in next major version.
287
295
  */
288
- type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinition> = WorkerInferConsumerHandlers<TContract>;
296
+ type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinitionInput> = WorkerInferConsumerHandlers<TContract>;
289
297
  //#endregion
290
298
  //#region src/worker.d.ts
291
299
  /**
@@ -323,7 +331,7 @@ type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinition> = Wor
323
331
  * Note: Retry configuration is defined at the queue level in the contract,
324
332
  * not at the handler level. See `QueueDefinition.retry` for configuration options.
325
333
  */
326
- type CreateWorkerOptions<TContract extends ContractDefinition> = {
334
+ type CreateWorkerOptions<TContract extends ContractDefinitionInput> = {
327
335
  /** The AMQP contract definition specifying consumers and their message schemas */
328
336
  contract: TContract;
329
337
  /**
@@ -385,7 +393,7 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
385
393
  * await worker.close().resultToPromise();
386
394
  * ```
387
395
  */
388
- declare class TypedAmqpWorker<TContract extends ContractDefinition> {
396
+ declare class TypedAmqpWorker<TContract extends ContractDefinitionInput> {
389
397
  private readonly contract;
390
398
  private readonly amqpClient;
391
399
  private readonly logger?;
@@ -422,7 +430,7 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
422
430
  * }).resultToPromise();
423
431
  * ```
424
432
  */
425
- static create<TContract extends ContractDefinition>({
433
+ static create<TContract extends ContractDefinitionInput>({
426
434
  contract,
427
435
  handlers,
428
436
  urls,
@@ -599,8 +607,8 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
599
607
  * );
600
608
  * ```
601
609
  */
602
- declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>): WorkerInferConsumerHandlerEntry<TContract, TName>;
603
- declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>, options: {
610
+ declare function defineHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>): WorkerInferConsumerHandlerEntry<TContract, TName>;
611
+ declare function defineHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>, options: {
604
612
  prefetch?: number;
605
613
  }): WorkerInferConsumerHandlerEntry<TContract, TName>;
606
614
  /**
@@ -632,7 +640,7 @@ declare function defineHandler<TContract extends ContractDefinition, TName exten
632
640
  * });
633
641
  * ```
634
642
  */
635
- declare function defineHandlers<TContract extends ContractDefinition>(contract: TContract, handlers: WorkerInferConsumerHandlers<TContract>): WorkerInferConsumerHandlers<TContract>;
643
+ declare function defineHandlers<TContract extends ContractDefinitionInput>(contract: TContract, handlers: WorkerInferConsumerHandlers<TContract>): WorkerInferConsumerHandlers<TContract>;
636
644
  //#endregion
637
645
  export { type CreateWorkerOptions, type HandlerError, MessageValidationError, NonRetryableError, RetryableError, TypedAmqpWorker, type WorkerConsumedMessage, type WorkerInferConsumedMessage, type WorkerInferConsumerHandler, type WorkerInferConsumerHandlerEntry, type WorkerInferConsumerHandlers, type WorkerInferConsumerHeaders, type WorkerInferSafeConsumerHandler, type WorkerInferSafeConsumerHandlerEntry, type WorkerInferSafeConsumerHandlers, defineHandler, defineHandlers, isHandlerError, isNonRetryableError, isRetryableError, nonRetryable, retryable };
638
646
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Logger, TechnicalError, TelemetryProvider } from "@amqp-contract/core";
2
+ import { ConsumerDefinition, ConsumerEntry, ContractDefinitionInput, InferConsumerNames, MessageDefinition } from "@amqp-contract/contract";
2
3
  import { Future, Result } from "@swan-io/boxed";
3
4
  import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
4
- import { ConsumerDefinition, ContractDefinition, InferConsumerNames, MessageDefinition } from "@amqp-contract/contract";
5
5
  import { ConsumeMessage } from "amqplib";
6
6
  import { StandardSchemaV1 } from "@standard-schema/spec";
7
7
 
@@ -165,31 +165,39 @@ declare function nonRetryable(message: string, cause?: unknown): NonRetryableErr
165
165
  */
166
166
  type InferSchemaInput<TSchema extends StandardSchemaV1> = TSchema extends StandardSchemaV1<infer TInput> ? TInput : never;
167
167
  /**
168
- * Infer consumer message payload input type
168
+ * Extract the ConsumerDefinition from any consumer entry type.
169
+ * Handles ConsumerDefinition, EventConsumerResult, and CommandConsumerConfig.
169
170
  */
170
- type ConsumerInferPayloadInput<TConsumer extends ConsumerDefinition> = InferSchemaInput<TConsumer["message"]["payload"]>;
171
+ type ExtractConsumerDefinition<T extends ConsumerEntry> = T extends ConsumerDefinition ? T : T extends {
172
+ consumer: ConsumerDefinition;
173
+ } ? T["consumer"] : never;
174
+ /**
175
+ * Infer consumer message payload input type.
176
+ * Works with any consumer entry type by first extracting the ConsumerDefinition.
177
+ */
178
+ type ConsumerInferPayloadInput<TConsumer extends ConsumerEntry> = ExtractConsumerDefinition<TConsumer> extends ConsumerDefinition ? InferSchemaInput<ExtractConsumerDefinition<TConsumer>["message"]["payload"]> : never;
171
179
  /**
172
180
  * Infer consumer message headers input type
173
181
  * Returns undefined if no headers schema is defined
174
182
  */
175
- type ConsumerInferHeadersInput<TConsumer extends ConsumerDefinition> = TConsumer["message"] extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaInput<THeaders> : undefined : undefined;
183
+ type ConsumerInferHeadersInput<TConsumer extends ConsumerEntry> = ExtractConsumerDefinition<TConsumer> extends ConsumerDefinition ? ExtractConsumerDefinition<TConsumer>["message"] extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaInput<THeaders> : undefined : undefined : undefined;
176
184
  /**
177
185
  * Infer all consumers from contract
178
186
  */
179
- type InferConsumers<TContract extends ContractDefinition> = NonNullable<TContract["consumers"]>;
187
+ type InferConsumers<TContract extends ContractDefinitionInput> = NonNullable<TContract["consumers"]>;
180
188
  /**
181
- * Get specific consumer definition from contract
189
+ * Get specific consumer entry from contract
182
190
  */
183
- type InferConsumer<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
191
+ type InferConsumer<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
184
192
  /**
185
193
  * Infer the payload type for a specific consumer
186
194
  */
187
- type WorkerInferConsumerPayload<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferPayloadInput<InferConsumer<TContract, TName>>;
195
+ type WorkerInferConsumerPayload<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = ConsumerInferPayloadInput<InferConsumer<TContract, TName>>;
188
196
  /**
189
197
  * Infer the headers type for a specific consumer
190
198
  * Returns undefined if no headers schema is defined
191
199
  */
192
- type WorkerInferConsumerHeaders<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferHeadersInput<InferConsumer<TContract, TName>>;
200
+ type WorkerInferConsumerHeaders<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = ConsumerInferHeadersInput<InferConsumer<TContract, TName>>;
193
201
  /**
194
202
  * A consumed message containing parsed payload and headers.
195
203
  *
@@ -220,7 +228,7 @@ type WorkerConsumedMessage<TPayload, THeaders$1 = undefined> = {
220
228
  * Infer the full consumed message type for a specific consumer.
221
229
  * Includes both payload and headers (if defined).
222
230
  */
223
- type WorkerInferConsumedMessage<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
231
+ type WorkerInferConsumedMessage<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
224
232
  /**
225
233
  * Consumer handler type for a specific consumer.
226
234
  * Returns a `Future<Result<void, HandlerError>>` for explicit error handling.
@@ -245,7 +253,7 @@ type WorkerInferConsumedMessage<TContract extends ContractDefinition, TName exte
245
253
  * };
246
254
  * ```
247
255
  */
248
- type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<void, HandlerError>>;
256
+ type WorkerInferConsumerHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<void, HandlerError>>;
249
257
  /**
250
258
  * Handler entry for a consumer - either a function or a tuple of [handler, options].
251
259
  *
@@ -256,7 +264,7 @@ type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName exte
256
264
  * Note: Retry configuration is now defined at the queue level in the contract,
257
265
  * not at the handler level. See `QueueDefinition.retry` for configuration options.
258
266
  */
259
- type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName> | readonly [WorkerInferConsumerHandler<TContract, TName>, {
267
+ type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName> | readonly [WorkerInferConsumerHandler<TContract, TName>, {
260
268
  prefetch?: number;
261
269
  }];
262
270
  /**
@@ -273,19 +281,19 @@ type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinition, TName
273
281
  * };
274
282
  * ```
275
283
  */
276
- type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandlerEntry<TContract, K> };
284
+ type WorkerInferConsumerHandlers<TContract extends ContractDefinitionInput> = { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandlerEntry<TContract, K> };
277
285
  /**
278
286
  * @deprecated Use `WorkerInferConsumerHandler` instead. Will be removed in next major version.
279
287
  */
280
- type WorkerInferSafeConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName>;
288
+ type WorkerInferSafeConsumerHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName>;
281
289
  /**
282
290
  * @deprecated Use `WorkerInferConsumerHandlerEntry` instead. Will be removed in next major version.
283
291
  */
284
- type WorkerInferSafeConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandlerEntry<TContract, TName>;
292
+ type WorkerInferSafeConsumerHandlerEntry<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandlerEntry<TContract, TName>;
285
293
  /**
286
294
  * @deprecated Use `WorkerInferConsumerHandlers` instead. Will be removed in next major version.
287
295
  */
288
- type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinition> = WorkerInferConsumerHandlers<TContract>;
296
+ type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinitionInput> = WorkerInferConsumerHandlers<TContract>;
289
297
  //#endregion
290
298
  //#region src/worker.d.ts
291
299
  /**
@@ -323,7 +331,7 @@ type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinition> = Wor
323
331
  * Note: Retry configuration is defined at the queue level in the contract,
324
332
  * not at the handler level. See `QueueDefinition.retry` for configuration options.
325
333
  */
326
- type CreateWorkerOptions<TContract extends ContractDefinition> = {
334
+ type CreateWorkerOptions<TContract extends ContractDefinitionInput> = {
327
335
  /** The AMQP contract definition specifying consumers and their message schemas */
328
336
  contract: TContract;
329
337
  /**
@@ -385,7 +393,7 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
385
393
  * await worker.close().resultToPromise();
386
394
  * ```
387
395
  */
388
- declare class TypedAmqpWorker<TContract extends ContractDefinition> {
396
+ declare class TypedAmqpWorker<TContract extends ContractDefinitionInput> {
389
397
  private readonly contract;
390
398
  private readonly amqpClient;
391
399
  private readonly logger?;
@@ -422,7 +430,7 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
422
430
  * }).resultToPromise();
423
431
  * ```
424
432
  */
425
- static create<TContract extends ContractDefinition>({
433
+ static create<TContract extends ContractDefinitionInput>({
426
434
  contract,
427
435
  handlers,
428
436
  urls,
@@ -599,8 +607,8 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
599
607
  * );
600
608
  * ```
601
609
  */
602
- declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>): WorkerInferConsumerHandlerEntry<TContract, TName>;
603
- declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>, options: {
610
+ declare function defineHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>): WorkerInferConsumerHandlerEntry<TContract, TName>;
611
+ declare function defineHandler<TContract extends ContractDefinitionInput, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>, options: {
604
612
  prefetch?: number;
605
613
  }): WorkerInferConsumerHandlerEntry<TContract, TName>;
606
614
  /**
@@ -632,7 +640,7 @@ declare function defineHandler<TContract extends ContractDefinition, TName exten
632
640
  * });
633
641
  * ```
634
642
  */
635
- declare function defineHandlers<TContract extends ContractDefinition>(contract: TContract, handlers: WorkerInferConsumerHandlers<TContract>): WorkerInferConsumerHandlers<TContract>;
643
+ declare function defineHandlers<TContract extends ContractDefinitionInput>(contract: TContract, handlers: WorkerInferConsumerHandlers<TContract>): WorkerInferConsumerHandlers<TContract>;
636
644
  //#endregion
637
645
  export { type CreateWorkerOptions, type HandlerError, MessageValidationError, NonRetryableError, RetryableError, TypedAmqpWorker, type WorkerConsumedMessage, type WorkerInferConsumedMessage, type WorkerInferConsumerHandler, type WorkerInferConsumerHandlerEntry, type WorkerInferConsumerHandlers, type WorkerInferConsumerHeaders, type WorkerInferSafeConsumerHandler, type WorkerInferSafeConsumerHandlerEntry, type WorkerInferSafeConsumerHandlers, defineHandler, defineHandlers, isHandlerError, isNonRetryableError, isRetryableError, nonRetryable, retryable };
638
646
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AmqpClient, TechnicalError, defaultTelemetryProvider, endSpanError, endSpanSuccess, recordConsumeMetric, startConsumeSpan } from "@amqp-contract/core";
2
+ import { extractConsumer } from "@amqp-contract/contract";
2
3
  import { Future, Result } from "@swan-io/boxed";
3
4
  import { gunzip, inflate } from "node:zlib";
4
5
  import { promisify } from "node:util";
@@ -374,7 +375,8 @@ var TypedAmqpWorker = class TypedAmqpWorker {
374
375
  * TypeScript guarantees consumer and handler exist for valid consumer names.
375
376
  */
376
377
  consume(consumerName) {
377
- const consumer = this.contract.consumers[consumerName];
378
+ const consumerEntry = this.contract.consumers[consumerName];
379
+ const consumer = extractConsumer(consumerEntry);
378
380
  const handler = this.actualHandlers[consumerName];
379
381
  return this.consumeSingle(consumerName, consumer, handler);
380
382
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/decompression.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":["/**\n * Error thrown when message validation fails\n */\nexport class MessageValidationError extends Error {\n constructor(\n public readonly consumerName: string,\n public readonly issues: unknown,\n ) {\n super(`Message validation failed for consumer \"${consumerName}\"`);\n this.name = \"MessageValidationError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Retryable errors - transient failures that may succeed on retry\n * Examples: network timeouts, rate limiting, temporary service unavailability\n *\n * Use this error type when the operation might succeed if retried.\n * The worker will apply exponential backoff and retry the message.\n */\nexport class RetryableError extends Error {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"RetryableError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Non-retryable errors - permanent failures that should not be retried\n * Examples: invalid data, business rule violations, permanent external failures\n *\n * Use this error type when retrying would not help - the message will be\n * immediately sent to the dead letter queue (DLQ) if configured.\n */\nexport class NonRetryableError extends Error {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"NonRetryableError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Union type representing all handler errors.\n * Use this type when defining handlers that explicitly signal error outcomes.\n */\nexport type HandlerError = RetryableError | NonRetryableError;\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Type guard to check if an error is a RetryableError.\n *\n * Use this to check error types in catch blocks or error handlers.\n *\n * @param error - The error to check\n * @returns True if the error is a RetryableError\n *\n * @example\n * ```typescript\n * import { isRetryableError } from '@amqp-contract/worker';\n *\n * try {\n * await processMessage();\n * } catch (error) {\n * if (isRetryableError(error)) {\n * console.log('Will retry:', error.message);\n * } else {\n * console.log('Permanent failure:', error);\n * }\n * }\n * ```\n */\nexport function isRetryableError(error: unknown): error is RetryableError {\n return error instanceof RetryableError;\n}\n\n/**\n * Type guard to check if an error is a NonRetryableError.\n *\n * Use this to check error types in catch blocks or error handlers.\n *\n * @param error - The error to check\n * @returns True if the error is a NonRetryableError\n *\n * @example\n * ```typescript\n * import { isNonRetryableError } from '@amqp-contract/worker';\n *\n * try {\n * await processMessage();\n * } catch (error) {\n * if (isNonRetryableError(error)) {\n * console.log('Will not retry:', error.message);\n * }\n * }\n * ```\n */\nexport function isNonRetryableError(error: unknown): error is NonRetryableError {\n return error instanceof NonRetryableError;\n}\n\n/**\n * Type guard to check if an error is any HandlerError (RetryableError or NonRetryableError).\n *\n * @param error - The error to check\n * @returns True if the error is a HandlerError\n *\n * @example\n * ```typescript\n * import { isHandlerError } from '@amqp-contract/worker';\n *\n * function handleError(error: unknown) {\n * if (isHandlerError(error)) {\n * // error is RetryableError | NonRetryableError\n * console.log('Handler error:', error.name, error.message);\n * }\n * }\n * ```\n */\nexport function isHandlerError(error: unknown): error is HandlerError {\n return isRetryableError(error) || isNonRetryableError(error);\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a RetryableError with less verbosity.\n *\n * This is a shorthand factory function for creating RetryableError instances.\n * Use it for cleaner error creation in handlers.\n *\n * @param message - Error message describing the failure\n * @param cause - Optional underlying error that caused this failure\n * @returns A new RetryableError instance\n *\n * @example\n * ```typescript\n * import { retryable } from '@amqp-contract/worker';\n * import { Future, Result } from '@swan-io/boxed';\n *\n * const handler = ({ payload }) =>\n * Future.fromPromise(processPayment(payload))\n * .mapOk(() => undefined)\n * .mapError((e) => retryable('Payment service unavailable', e));\n *\n * // Equivalent to:\n * // .mapError((e) => new RetryableError('Payment service unavailable', e));\n * ```\n */\nexport function retryable(message: string, cause?: unknown): RetryableError {\n return new RetryableError(message, cause);\n}\n\n/**\n * Create a NonRetryableError with less verbosity.\n *\n * This is a shorthand factory function for creating NonRetryableError instances.\n * Use it for cleaner error creation in handlers.\n *\n * @param message - Error message describing the failure\n * @param cause - Optional underlying error that caused this failure\n * @returns A new NonRetryableError instance\n *\n * @example\n * ```typescript\n * import { nonRetryable } from '@amqp-contract/worker';\n * import { Future, Result } from '@swan-io/boxed';\n *\n * const handler = ({ payload }) => {\n * if (!isValidPayload(payload)) {\n * return Future.value(Result.Error(nonRetryable('Invalid payload format')));\n * }\n * return Future.value(Result.Ok(undefined));\n * };\n *\n * // Equivalent to:\n * // return Future.value(Result.Error(new NonRetryableError('Invalid payload format')));\n * ```\n */\nexport function nonRetryable(message: string, cause?: unknown): NonRetryableError {\n return new NonRetryableError(message, cause);\n}\n","import { Future, Result } from \"@swan-io/boxed\";\nimport { gunzip, inflate } from \"node:zlib\";\nimport { TechnicalError } from \"@amqp-contract/core\";\nimport { promisify } from \"node:util\";\n\nconst gunzipAsync = promisify(gunzip);\nconst inflateAsync = promisify(inflate);\n\n/**\n * Supported content encodings for message decompression.\n */\nconst SUPPORTED_ENCODINGS = [\"gzip\", \"deflate\"] as const;\n\n/**\n * Type for supported content encodings.\n */\ntype SupportedEncoding = (typeof SUPPORTED_ENCODINGS)[number];\n\n/**\n * Type guard to check if a string is a supported encoding.\n */\nfunction isSupportedEncoding(encoding: string): encoding is SupportedEncoding {\n return SUPPORTED_ENCODINGS.includes(encoding.toLowerCase() as SupportedEncoding);\n}\n\n/**\n * Decompress a buffer based on the content-encoding header.\n *\n * @param buffer - The buffer to decompress\n * @param contentEncoding - The content-encoding header value (e.g., 'gzip', 'deflate')\n * @returns A Future with the decompressed buffer or a TechnicalError\n *\n * @internal\n */\nexport function decompressBuffer(\n buffer: Buffer,\n contentEncoding: string | undefined,\n): Future<Result<Buffer, TechnicalError>> {\n if (!contentEncoding) {\n return Future.value(Result.Ok(buffer));\n }\n\n const normalizedEncoding = contentEncoding.toLowerCase();\n\n if (!isSupportedEncoding(normalizedEncoding)) {\n return Future.value(\n Result.Error(\n new TechnicalError(\n `Unsupported content-encoding: \"${contentEncoding}\". ` +\n `Supported encodings are: ${SUPPORTED_ENCODINGS.join(\", \")}. ` +\n `Please check your publisher configuration.`,\n ),\n ),\n );\n }\n\n switch (normalizedEncoding) {\n case \"gzip\":\n return Future.fromPromise(gunzipAsync(buffer)).mapError(\n (error) => new TechnicalError(\"Failed to decompress gzip\", error),\n );\n case \"deflate\":\n return Future.fromPromise(inflateAsync(buffer)).mapError(\n (error) => new TechnicalError(\"Failed to decompress deflate\", error),\n );\n }\n}\n","import {\n AmqpClient,\n type Logger,\n TechnicalError,\n type TelemetryProvider,\n defaultTelemetryProvider,\n endSpanError,\n endSpanSuccess,\n recordConsumeMetric,\n startConsumeSpan,\n} from \"@amqp-contract/core\";\nimport type { AmqpConnectionManagerOptions, ConnectionUrl } from \"amqp-connection-manager\";\nimport type { Channel, ConsumeMessage } from \"amqplib\";\nimport type {\n ConsumerDefinition,\n ContractDefinition,\n InferConsumerNames,\n ResolvedRetryOptions,\n ResolvedTtlBackoffRetryOptions,\n} from \"@amqp-contract/contract\";\nimport { Future, Result } from \"@swan-io/boxed\";\nimport { MessageValidationError, NonRetryableError } from \"./errors.js\";\nimport type {\n WorkerInferConsumedMessage,\n WorkerInferConsumerHandler,\n WorkerInferConsumerHandlers,\n} from \"./types.js\";\nimport type { HandlerError } from \"./errors.js\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { decompressBuffer } from \"./decompression.js\";\n\n/**\n * Internal type for consumer options extracted from handler tuples.\n * Not exported - options are specified inline in the handler tuple types.\n *\n * Note: Retry configuration is now defined at the queue level in the contract,\n * not at the handler level. See `QueueDefinition.retry` for configuration options.\n */\ntype ConsumerOptions = {\n /** Number of messages to prefetch */\n prefetch?: number;\n};\n\n/**\n * Retry configuration from the contract with all values resolved.\n * This is a discriminated union on `mode` - TTL-backoff has the config fields,\n * quorum-native does not.\n */\ntype ResolvedRetryConfig = ResolvedRetryOptions;\n\n/**\n * Type guard to check if a handler entry is a tuple format [handler, options].\n */\nfunction isHandlerTuple(entry: unknown): entry is [unknown, ConsumerOptions] {\n return Array.isArray(entry) && entry.length === 2;\n}\n\n/**\n * Options for creating a type-safe AMQP worker.\n *\n * @typeParam TContract - The contract definition type\n *\n * @example\n * ```typescript\n * const options: CreateWorkerOptions<typeof contract> = {\n * contract: myContract,\n * handlers: {\n * // Simple handler\n * processOrder: ({ payload }) => {\n * console.log('Processing order:', payload.orderId);\n * return Future.value(Result.Ok(undefined));\n * },\n * // Handler with prefetch configuration\n * processPayment: [\n * ({ payload }) => {\n * console.log('Processing payment:', payload.paymentId);\n * return Future.value(Result.Ok(undefined));\n * },\n * { prefetch: 10 }\n * ]\n * },\n * urls: ['amqp://localhost'],\n * connectionOptions: {\n * heartbeatIntervalInSeconds: 30\n * },\n * logger: myLogger\n * };\n * ```\n *\n * Note: Retry configuration is defined at the queue level in the contract,\n * not at the handler level. See `QueueDefinition.retry` for configuration options.\n */\nexport type CreateWorkerOptions<TContract extends ContractDefinition> = {\n /** The AMQP contract definition specifying consumers and their message schemas */\n contract: TContract;\n /**\n * Handlers for each consumer defined in the contract.\n * Handlers must return `Future<Result<void, HandlerError>>` for explicit error handling.\n * Use defineHandler() to create handlers.\n */\n handlers: WorkerInferConsumerHandlers<TContract>;\n /** AMQP broker URL(s). Multiple URLs provide failover support */\n urls: ConnectionUrl[];\n /** Optional connection configuration (heartbeat, reconnect settings, etc.) */\n connectionOptions?: AmqpConnectionManagerOptions | undefined;\n /** Optional logger for logging message consumption and errors */\n logger?: Logger | undefined;\n /**\n * Optional telemetry provider for tracing and metrics.\n * If not provided, uses the default provider which attempts to load OpenTelemetry.\n * OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed.\n */\n telemetry?: TelemetryProvider | undefined;\n};\n\n/**\n * Type-safe AMQP worker for consuming messages from RabbitMQ.\n *\n * This class provides automatic message validation, connection management,\n * and error handling for consuming messages based on a contract definition.\n *\n * @typeParam TContract - The contract definition type\n *\n * @example\n * ```typescript\n * import { TypedAmqpWorker } from '@amqp-contract/worker';\n * import { z } from 'zod';\n *\n * const contract = defineContract({\n * queues: {\n * orderProcessing: defineQueue('order-processing', { durable: true })\n * },\n * consumers: {\n * processOrder: defineConsumer('order-processing', z.object({\n * orderId: z.string(),\n * amount: z.number()\n * }))\n * }\n * });\n *\n * const worker = await TypedAmqpWorker.create({\n * contract,\n * handlers: {\n * processOrder: async (message) => {\n * console.log('Processing order', message.orderId);\n * // Process the order...\n * }\n * },\n * urls: ['amqp://localhost']\n * }).resultToPromise();\n *\n * // Close when done\n * await worker.close().resultToPromise();\n * ```\n */\nexport class TypedAmqpWorker<TContract extends ContractDefinition> {\n /**\n * Internal handler storage - handlers returning `Future<Result>`.\n */\n private readonly actualHandlers: Partial<\n Record<\n InferConsumerNames<TContract>,\n WorkerInferConsumerHandler<TContract, InferConsumerNames<TContract>>\n >\n >;\n private readonly consumerOptions: Partial<Record<InferConsumerNames<TContract>, ConsumerOptions>>;\n private readonly consumerTags: Set<string> = new Set();\n private readonly telemetry: TelemetryProvider;\n\n private constructor(\n private readonly contract: TContract,\n private readonly amqpClient: AmqpClient,\n handlers: WorkerInferConsumerHandlers<TContract>,\n private readonly logger?: Logger,\n telemetry?: TelemetryProvider,\n ) {\n this.telemetry = telemetry ?? defaultTelemetryProvider;\n\n // Extract handlers and options from the handlers object\n this.actualHandlers = {};\n this.consumerOptions = {};\n\n // Cast handlers to a generic record for iteration\n const handlersRecord = handlers as Record<string, unknown>;\n\n for (const consumerName of Object.keys(handlersRecord)) {\n const handlerEntry = handlersRecord[consumerName];\n const typedConsumerName = consumerName as InferConsumerNames<TContract>;\n\n if (isHandlerTuple(handlerEntry)) {\n // Tuple format: [handler, options]\n const [handler, options] = handlerEntry;\n this.actualHandlers[typedConsumerName] = handler as WorkerInferConsumerHandler<\n TContract,\n InferConsumerNames<TContract>\n >;\n this.consumerOptions[typedConsumerName] = options;\n } else {\n // Direct function format\n this.actualHandlers[typedConsumerName] = handlerEntry as WorkerInferConsumerHandler<\n TContract,\n InferConsumerNames<TContract>\n >;\n }\n }\n }\n\n /**\n * Create a type-safe AMQP worker from a contract.\n *\n * Connection management (including automatic reconnection) is handled internally\n * by amqp-connection-manager via the {@link AmqpClient}. The worker will set up\n * consumers for all contract-defined handlers asynchronously in the background\n * once the underlying connection and channels are ready.\n *\n * Connections are automatically shared across clients and workers with the same\n * URLs and connection options, following RabbitMQ best practices.\n *\n * @param options - Configuration options for the worker\n * @returns A Future that resolves to a Result containing the worker or an error\n *\n * @example\n * ```typescript\n * const worker = await TypedAmqpWorker.create({\n * contract: myContract,\n * handlers: {\n * processOrder: async ({ payload }) => console.log('Order:', payload.orderId)\n * },\n * urls: ['amqp://localhost']\n * }).resultToPromise();\n * ```\n */\n static create<TContract extends ContractDefinition>({\n contract,\n handlers,\n urls,\n connectionOptions,\n logger,\n telemetry,\n }: CreateWorkerOptions<TContract>): Future<Result<TypedAmqpWorker<TContract>, TechnicalError>> {\n const worker = new TypedAmqpWorker(\n contract,\n new AmqpClient(contract, {\n urls,\n connectionOptions,\n }),\n handlers,\n logger,\n telemetry,\n );\n\n // Note: Wait queues are now created by the core package in setupAmqpTopology\n // when the queue's retry mode is \"ttl-backoff\"\n return worker\n .waitForConnectionReady()\n .flatMapOk(() => worker.consumeAll())\n .mapOk(() => worker);\n }\n\n /**\n * Close the AMQP channel and connection.\n *\n * This gracefully closes the connection to the AMQP broker,\n * stopping all message consumption and cleaning up resources.\n *\n * @returns A Future that resolves to a Result indicating success or failure\n *\n * @example\n * ```typescript\n * const closeResult = await worker.close().resultToPromise();\n * if (closeResult.isOk()) {\n * console.log('Worker closed successfully');\n * }\n * ```\n */\n close(): Future<Result<void, TechnicalError>> {\n return Future.all(\n Array.from(this.consumerTags).map((consumerTag) =>\n this.amqpClient.cancel(consumerTag).mapErrorToResult((error) => {\n this.logger?.warn(\"Failed to cancel consumer during close\", { consumerTag, error });\n return Result.Ok(undefined);\n }),\n ),\n )\n .map(Result.all)\n .tapOk(() => {\n // Clear consumer tags after successful cancellation\n this.consumerTags.clear();\n })\n .flatMapOk(() => this.amqpClient.close())\n .mapOk(() => undefined);\n }\n\n /**\n * Get the retry configuration for a consumer's queue.\n * Defaults are applied in the contract's defineQueue, so we just return the config.\n */\n private getRetryConfigForConsumer(consumer: ConsumerDefinition): ResolvedRetryConfig {\n return consumer.queue.retry;\n }\n\n /**\n * Start consuming messages for all consumers.\n * TypeScript guarantees consumers exist (handlers require matching consumers).\n */\n private consumeAll(): Future<Result<void, TechnicalError>> {\n const consumers = this.contract.consumers!;\n const consumerNames = Object.keys(consumers) as InferConsumerNames<TContract>[];\n\n // Calculate max prefetch (AMQP 0.9.1 prefetch is per-channel)\n const maxPrefetch = consumerNames.reduce((max, name) => {\n const prefetch = this.consumerOptions[name]?.prefetch;\n return prefetch ? Math.max(max, prefetch) : max;\n }, 0);\n\n if (maxPrefetch > 0) {\n this.amqpClient.addSetup(async (channel: Channel) => {\n await channel.prefetch(maxPrefetch);\n });\n }\n\n return Future.all(consumerNames.map((name) => this.consume(name)))\n .map(Result.all)\n .mapOk(() => undefined);\n }\n\n private waitForConnectionReady(): Future<Result<void, TechnicalError>> {\n return this.amqpClient.waitForConnect();\n }\n\n /**\n * Start consuming messages for a specific consumer.\n * TypeScript guarantees consumer and handler exist for valid consumer names.\n */\n private consume<TName extends InferConsumerNames<TContract>>(\n consumerName: TName,\n ): Future<Result<void, TechnicalError>> {\n // Non-null assertions safe: TypeScript guarantees these exist for valid TName\n const consumer = this.contract.consumers![consumerName as string]!;\n const handler = this.actualHandlers[consumerName]!;\n\n return this.consumeSingle(\n consumerName,\n consumer,\n handler as Parameters<typeof this.consumeSingle<TName>>[2],\n );\n }\n\n /**\n * Validate data against a Standard Schema and handle errors.\n */\n private validateSchema(\n schema: StandardSchemaV1,\n data: unknown,\n context: { consumerName: string; queueName: string; field: string },\n msg: ConsumeMessage,\n ): Future<Result<unknown, TechnicalError>> {\n const rawValidation = schema[\"~standard\"].validate(data);\n const validationPromise =\n rawValidation instanceof Promise ? rawValidation : Promise.resolve(rawValidation);\n\n return Future.fromPromise(validationPromise)\n .mapError((error) => new TechnicalError(`Error validating ${context.field}`, error))\n .mapOkToResult((result) => {\n if (result.issues) {\n return Result.Error(\n new TechnicalError(\n `${context.field} validation failed`,\n new MessageValidationError(context.consumerName, result.issues),\n ),\n );\n }\n return Result.Ok(result.value);\n })\n .tapError((error) => {\n this.logger?.error(`${context.field} validation failed`, {\n consumerName: context.consumerName,\n queueName: context.queueName,\n error,\n });\n this.amqpClient.nack(msg, false, false);\n });\n }\n\n /**\n * Parse and validate a message from AMQP.\n * @returns Ok with validated message (payload + headers), or Error (message already nacked)\n */\n private parseAndValidateMessage<TName extends InferConsumerNames<TContract>>(\n msg: ConsumeMessage,\n consumer: ConsumerDefinition,\n consumerName: TName,\n ): Future<Result<WorkerInferConsumedMessage<TContract, TName>, TechnicalError>> {\n const context = {\n consumerName: String(consumerName),\n queueName: consumer.queue.name,\n };\n\n const nackAndError = (message: string, error?: unknown): TechnicalError => {\n this.logger?.error(message, { ...context, error });\n this.amqpClient.nack(msg, false, false);\n return new TechnicalError(message, error);\n };\n\n // Decompress → Parse JSON → Validate payload\n const parsePayload = decompressBuffer(msg.content, msg.properties.contentEncoding)\n .tapError((error) => {\n this.logger?.error(\"Failed to decompress message\", { ...context, error });\n this.amqpClient.nack(msg, false, false);\n })\n .mapOkToResult((buffer) =>\n Result.fromExecution(() => JSON.parse(buffer.toString()) as unknown).mapError((error) =>\n nackAndError(\"Failed to parse JSON\", error),\n ),\n )\n .flatMapOk((parsed) =>\n this.validateSchema(\n consumer.message.payload as StandardSchemaV1,\n parsed,\n { ...context, field: \"payload\" },\n msg,\n ),\n );\n\n // Validate headers (if schema defined)\n const parseHeaders = consumer.message.headers\n ? this.validateSchema(\n consumer.message.headers as StandardSchemaV1,\n msg.properties.headers ?? {},\n { ...context, field: \"headers\" },\n msg,\n )\n : Future.value(Result.Ok<unknown, TechnicalError>(undefined));\n\n return Future.allFromDict({ payload: parsePayload, headers: parseHeaders }).map(\n Result.allFromDict,\n ) as Future<Result<WorkerInferConsumedMessage<TContract, TName>, TechnicalError>>;\n }\n\n /**\n * Consume messages one at a time\n */\n private consumeSingle<TName extends InferConsumerNames<TContract>>(\n consumerName: TName,\n consumer: ConsumerDefinition,\n handler: (\n message: WorkerInferConsumedMessage<TContract, TName>,\n rawMessage: ConsumeMessage,\n ) => Future<Result<void, HandlerError>>,\n ): Future<Result<void, TechnicalError>> {\n const queueName = consumer.queue.name;\n\n // Start consuming\n return this.amqpClient\n .consume(queueName, async (msg) => {\n // Handle null messages (consumer cancellation)\n if (msg === null) {\n this.logger?.warn(\"Consumer cancelled by server\", {\n consumerName: String(consumerName),\n queueName,\n });\n return;\n }\n\n const startTime = Date.now();\n const span = startConsumeSpan(this.telemetry, queueName, String(consumerName), {\n \"messaging.rabbitmq.message.delivery_tag\": msg.fields.deliveryTag,\n });\n\n // Parse and validate message\n await this.parseAndValidateMessage(msg, consumer, consumerName)\n .flatMapOk((validatedMessage) =>\n handler(validatedMessage, msg)\n .flatMapOk(() => {\n this.logger?.info(\"Message consumed successfully\", {\n consumerName: String(consumerName),\n queueName,\n });\n // Acknowledge message on success\n this.amqpClient.ack(msg);\n\n // Record telemetry success\n const durationMs = Date.now() - startTime;\n endSpanSuccess(span);\n recordConsumeMetric(\n this.telemetry,\n queueName,\n String(consumerName),\n true,\n durationMs,\n );\n\n return Future.value(Result.Ok<void, HandlerError>(undefined));\n })\n .flatMapError((handlerError: HandlerError) => {\n // Handler returned an error\n this.logger?.error(\"Error processing message\", {\n consumerName: String(consumerName),\n queueName,\n errorType: handlerError.name,\n error: handlerError.message,\n });\n\n // Record telemetry failure\n const durationMs = Date.now() - startTime;\n endSpanError(span, handlerError);\n recordConsumeMetric(\n this.telemetry,\n queueName,\n String(consumerName),\n false,\n durationMs,\n );\n\n // Handle the error using retry mechanism\n return this.handleError(handlerError, msg, String(consumerName), consumer);\n }),\n )\n .tapError(() => {\n // Record telemetry failure for validation errors\n // Note: The actual validation error is logged in parseAndValidateMessage,\n // here we just record that validation failed for telemetry purposes\n const durationMs = Date.now() - startTime;\n endSpanError(span, new Error(\"Message validation failed\"));\n recordConsumeMetric(this.telemetry, queueName, String(consumerName), false, durationMs);\n })\n .toPromise();\n })\n .tapOk((consumerTag) => {\n // Store consumer tag for later cancellation\n this.consumerTags.add(consumerTag);\n })\n .mapError(\n (error) =>\n new TechnicalError(`Failed to start consuming for \"${String(consumerName)}\"`, error),\n )\n .mapOk(() => undefined);\n }\n\n /**\n * Handle error in message processing with retry logic.\n *\n * Flow depends on retry mode:\n *\n * **quorum-native mode:**\n * 1. If NonRetryableError -> send directly to DLQ (no retry)\n * 2. Otherwise -> nack with requeue=true (RabbitMQ handles delivery count)\n *\n * **ttl-backoff mode:**\n * 1. If NonRetryableError -> send directly to DLQ (no retry)\n * 2. If max retries exceeded -> send to DLQ\n * 3. Otherwise -> publish to wait queue with TTL for retry\n *\n * **Legacy mode (no retry config):**\n * 1. nack with requeue=true (immediate requeue)\n */\n private handleError(\n error: Error,\n msg: ConsumeMessage,\n consumerName: string,\n consumer: ConsumerDefinition,\n ): Future<Result<void, TechnicalError>> {\n // NonRetryableError -> send directly to DLQ without retrying\n if (error instanceof NonRetryableError) {\n this.logger?.error(\"Non-retryable error, sending to DLQ immediately\", {\n consumerName,\n errorType: error.name,\n error: error.message,\n });\n this.sendToDLQ(msg, consumer);\n return Future.value(Result.Ok(undefined));\n }\n\n // Get retry config from the queue definition in the contract\n const config = this.getRetryConfigForConsumer(consumer);\n\n // Quorum-native mode: let RabbitMQ handle retry via x-delivery-count\n if (config.mode === \"quorum-native\") {\n return this.handleErrorQuorumNative(error, msg, consumerName, consumer);\n }\n\n // TTL-backoff mode: use wait queue with exponential backoff\n return this.handleErrorTtlBackoff(error, msg, consumerName, consumer, config);\n }\n\n /**\n * Handle error using quorum queue's native delivery limit feature.\n *\n * Simply requeues the message with nack(requeue=true). RabbitMQ automatically:\n * - Increments x-delivery-count header\n * - Dead-letters the message when count exceeds x-delivery-limit\n *\n * This is simpler than TTL-based retry but provides immediate retries only.\n */\n private handleErrorQuorumNative(\n error: Error,\n msg: ConsumeMessage,\n consumerName: string,\n consumer: ConsumerDefinition,\n ): Future<Result<void, TechnicalError>> {\n const queue = consumer.queue;\n const queueName = queue.name;\n // x-delivery-count is incremented on each delivery attempt\n // When x-delivery-count equals x-delivery-limit, message is dead-lettered on next attempt\n const deliveryCount = (msg.properties.headers?.[\"x-delivery-count\"] as number) ?? 0;\n // This function is only called for quorum-native mode, which requires quorum queues\n const deliveryLimit = queue.type === \"quorum\" ? queue.deliveryLimit : undefined;\n\n // After this requeue, RabbitMQ will increment deliveryCount\n // Message is dead-lettered when deliveryCount reaches deliveryLimit\n // So if deliveryCount == deliveryLimit - 1, the next failure will dead-letter the message\n const attemptsBeforeDeadLetter =\n deliveryLimit !== undefined ? Math.max(0, deliveryLimit - deliveryCount - 1) : \"unknown\";\n\n // Log warning if this is the last attempt before dead-lettering\n if (deliveryLimit !== undefined && deliveryCount >= deliveryLimit - 1) {\n this.logger?.warn(\"Message at final delivery attempt (quorum-native mode)\", {\n consumerName,\n queueName,\n deliveryCount,\n deliveryLimit,\n willDeadLetterOnNextFailure: deliveryCount === deliveryLimit - 1,\n alreadyExceededLimit: deliveryCount >= deliveryLimit,\n error: error.message,\n });\n } else {\n this.logger?.warn(\"Retrying message (quorum-native mode)\", {\n consumerName,\n queueName,\n deliveryCount,\n deliveryLimit,\n attemptsBeforeDeadLetter,\n error: error.message,\n });\n }\n\n // Requeue the message - RabbitMQ tracks delivery count and handles dead-lettering\n this.amqpClient.nack(msg, false, true);\n return Future.value(Result.Ok(undefined));\n }\n\n /**\n * Handle error using TTL + wait queue pattern for exponential backoff.\n */\n private handleErrorTtlBackoff(\n error: Error,\n msg: ConsumeMessage,\n consumerName: string,\n consumer: ConsumerDefinition,\n config: ResolvedTtlBackoffRetryOptions,\n ): Future<Result<void, TechnicalError>> {\n // Get retry count from headers\n const retryCount = (msg.properties.headers?.[\"x-retry-count\"] as number) ?? 0;\n\n // Max retries exceeded -> DLQ\n if (retryCount >= config.maxRetries) {\n this.logger?.error(\"Max retries exceeded, sending to DLQ\", {\n consumerName,\n retryCount,\n maxRetries: config.maxRetries,\n error: error.message,\n });\n this.sendToDLQ(msg, consumer);\n return Future.value(Result.Ok(undefined));\n }\n\n // Retry with exponential backoff\n const delayMs = this.calculateRetryDelay(retryCount, config);\n this.logger?.warn(\"Retrying message (ttl-backoff mode)\", {\n consumerName,\n retryCount: retryCount + 1,\n delayMs,\n error: error.message,\n });\n\n return this.publishForRetry(msg, consumer, retryCount + 1, delayMs, error);\n }\n\n /**\n * Calculate retry delay with exponential backoff and optional jitter.\n */\n private calculateRetryDelay(retryCount: number, config: ResolvedTtlBackoffRetryOptions): number {\n const { initialDelayMs, maxDelayMs, backoffMultiplier, jitter } = config;\n\n let delay = Math.min(initialDelayMs * Math.pow(backoffMultiplier, retryCount), maxDelayMs);\n\n if (jitter) {\n // Add jitter: random value between 50% and 100% of calculated delay\n delay = delay * (0.5 + Math.random() * 0.5);\n }\n\n return Math.floor(delay);\n }\n\n /**\n * Parse message content for republishing.\n * Prevents double JSON serialization by converting Buffer to object when possible.\n */\n private parseMessageContentForRetry(msg: ConsumeMessage, queueName: string): Buffer | unknown {\n let content: Buffer | unknown = msg.content;\n\n // If message is not compressed (no contentEncoding), parse it to get the original object\n if (!msg.properties.contentEncoding) {\n try {\n content = JSON.parse(msg.content.toString());\n } catch (err) {\n this.logger?.warn(\"Failed to parse message for retry, using original buffer\", {\n queueName,\n error: err,\n });\n }\n }\n\n return content;\n }\n\n /**\n * Publish message to wait queue for retry after TTL expires.\n *\n * ┌─────────────────────────────────────────────────────────────────┐\n * │ Retry Flow (Native RabbitMQ TTL + DLX Pattern) │\n * ├─────────────────────────────────────────────────────────────────┤\n * │ │\n * │ 1. Handler throws any Error │\n * │ ↓ │\n * │ 2. Worker publishes to DLX with routing key: {queue}-wait │\n * │ ↓ │\n * │ 3. DLX routes to wait queue: {queue}-wait │\n * │ (with expiration: calculated backoff delay) │\n * │ ↓ │\n * │ 4. Message waits in queue until TTL expires │\n * │ ↓ │\n * │ 5. Expired message dead-lettered to DLX │\n * │ (with routing key: {queue}) │\n * │ ↓ │\n * │ 6. DLX routes back to main queue → RETRY │\n * │ ↓ │\n * │ 7. If retries exhausted: nack without requeue → DLQ │\n * │ │\n * └─────────────────────────────────────────────────────────────────┘\n */\n private publishForRetry(\n msg: ConsumeMessage,\n consumer: ConsumerDefinition,\n newRetryCount: number,\n delayMs: number,\n error: Error,\n ): Future<Result<void, TechnicalError>> {\n const queueName = consumer.queue.name;\n const deadLetter = consumer.queue.deadLetter;\n\n if (!deadLetter) {\n this.logger?.warn(\n \"Cannot retry: queue does not have DLX configured, falling back to nack with requeue\",\n {\n queueName,\n },\n );\n this.amqpClient.nack(msg, false, true);\n return Future.value(Result.Ok(undefined));\n }\n\n const dlxName = deadLetter.exchange.name;\n const waitRoutingKey = `${queueName}-wait`;\n\n // Acknowledge original message\n this.amqpClient.ack(msg);\n\n const content = this.parseMessageContentForRetry(msg, queueName);\n\n // Publish to DLX with wait routing key\n return this.amqpClient\n .publish(dlxName, waitRoutingKey, content, {\n ...msg.properties,\n expiration: delayMs.toString(), // Per-message TTL\n headers: {\n ...msg.properties.headers,\n \"x-retry-count\": newRetryCount,\n \"x-last-error\": error.message,\n \"x-first-failure-timestamp\":\n msg.properties.headers?.[\"x-first-failure-timestamp\"] ?? Date.now(),\n },\n })\n .mapOkToResult((published) => {\n if (!published) {\n this.logger?.error(\"Failed to publish message for retry (write buffer full)\", {\n queueName,\n waitRoutingKey,\n retryCount: newRetryCount,\n });\n return Result.Error(\n new TechnicalError(\"Failed to publish message for retry (write buffer full)\"),\n );\n }\n\n this.logger?.info(\"Message published for retry\", {\n queueName,\n waitRoutingKey,\n retryCount: newRetryCount,\n delayMs,\n });\n return Result.Ok(undefined);\n });\n }\n\n /**\n * Send message to dead letter queue.\n * Nacks the message without requeue, relying on DLX configuration.\n */\n private sendToDLQ(msg: ConsumeMessage, consumer: ConsumerDefinition): void {\n const queueName = consumer.queue.name;\n const hasDeadLetter = consumer.queue.deadLetter !== undefined;\n\n if (!hasDeadLetter) {\n this.logger?.warn(\"Queue does not have DLX configured - message will be lost on nack\", {\n queueName,\n });\n }\n\n this.logger?.info(\"Sending message to DLQ\", {\n queueName,\n deliveryTag: msg.fields.deliveryTag,\n });\n\n // Nack without requeue - relies on DLX configuration\n this.amqpClient.nack(msg, false, false);\n }\n}\n","import type { ContractDefinition, InferConsumerNames } from \"@amqp-contract/contract\";\nimport type {\n WorkerInferConsumerHandler,\n WorkerInferConsumerHandlerEntry,\n WorkerInferConsumerHandlers,\n} from \"./types.js\";\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Validate that a consumer exists in the contract\n */\nfunction validateConsumerExists<TContract extends ContractDefinition>(\n contract: TContract,\n consumerName: string,\n): void {\n const consumers = contract.consumers;\n\n if (!consumers || !(consumerName in consumers)) {\n const availableConsumers = consumers ? Object.keys(consumers) : [];\n const available = availableConsumers.length > 0 ? availableConsumers.join(\", \") : \"none\";\n throw new Error(\n `Consumer \"${consumerName}\" not found in contract. Available consumers: ${available}`,\n );\n }\n}\n\n/**\n * Validate that all handlers reference valid consumers\n */\nfunction validateHandlers<TContract extends ContractDefinition>(\n contract: TContract,\n handlers: Record<string, unknown>,\n): void {\n const consumers = contract.consumers;\n const availableConsumers = Object.keys(consumers ?? {});\n const availableConsumerNames =\n availableConsumers.length > 0 ? availableConsumers.join(\", \") : \"none\";\n\n for (const handlerName of Object.keys(handlers)) {\n if (!consumers || !(handlerName in consumers)) {\n throw new Error(\n `Consumer \"${handlerName}\" not found in contract. Available consumers: ${availableConsumerNames}`,\n );\n }\n }\n}\n\n// =============================================================================\n// Handler Definitions\n// =============================================================================\n\n/**\n * Define a type-safe handler for a specific consumer in a contract.\n *\n * **Recommended:** This function creates handlers that return `Future<Result<void, HandlerError>>`,\n * providing explicit error handling and better control over retry behavior.\n *\n * Supports two patterns:\n * 1. Simple handler: just the function\n * 2. Handler with options: [handler, { prefetch: 10 }]\n *\n * @template TContract - The contract definition type\n * @template TName - The consumer name from the contract\n * @param contract - The contract definition containing the consumer\n * @param consumerName - The name of the consumer from the contract\n * @param handler - The handler function that returns `Future<Result<void, HandlerError>>`\n * @param options - Optional consumer options (prefetch)\n * @returns A type-safe handler that can be used with TypedAmqpWorker\n *\n * @example\n * ```typescript\n * import { defineHandler, RetryableError, NonRetryableError } from '@amqp-contract/worker';\n * import { Future, Result } from '@swan-io/boxed';\n * import { orderContract } from './contract';\n *\n * // Simple handler with explicit error handling using mapError\n * const processOrderHandler = defineHandler(\n * orderContract,\n * 'processOrder',\n * ({ payload }) =>\n * Future.fromPromise(processPayment(payload))\n * .mapOk(() => undefined)\n * .mapError((error) => new RetryableError('Payment failed', error))\n * );\n *\n * // Handler with validation (non-retryable error)\n * const validateOrderHandler = defineHandler(\n * orderContract,\n * 'validateOrder',\n * ({ payload }) => {\n * if (payload.amount < 1) {\n * // Won't be retried - goes directly to DLQ\n * return Future.value(Result.Error(new NonRetryableError('Invalid order amount')));\n * }\n * return Future.value(Result.Ok(undefined));\n * }\n * );\n * ```\n */\nexport function defineHandler<\n TContract extends ContractDefinition,\n TName extends InferConsumerNames<TContract>,\n>(\n contract: TContract,\n consumerName: TName,\n handler: WorkerInferConsumerHandler<TContract, TName>,\n): WorkerInferConsumerHandlerEntry<TContract, TName>;\nexport function defineHandler<\n TContract extends ContractDefinition,\n TName extends InferConsumerNames<TContract>,\n>(\n contract: TContract,\n consumerName: TName,\n handler: WorkerInferConsumerHandler<TContract, TName>,\n options: { prefetch?: number },\n): WorkerInferConsumerHandlerEntry<TContract, TName>;\nexport function defineHandler<\n TContract extends ContractDefinition,\n TName extends InferConsumerNames<TContract>,\n>(\n contract: TContract,\n consumerName: TName,\n handler: WorkerInferConsumerHandler<TContract, TName>,\n options?: { prefetch?: number },\n): WorkerInferConsumerHandlerEntry<TContract, TName> {\n validateConsumerExists(contract, String(consumerName));\n\n if (options) {\n return [handler, options];\n }\n return handler;\n}\n\n/**\n * Define multiple type-safe handlers for consumers in a contract.\n *\n * **Recommended:** This function creates handlers that return `Future<Result<void, HandlerError>>`,\n * providing explicit error handling and better control over retry behavior.\n *\n * @template TContract - The contract definition type\n * @param contract - The contract definition containing the consumers\n * @param handlers - An object with handler functions for each consumer\n * @returns A type-safe handlers object that can be used with TypedAmqpWorker\n *\n * @example\n * ```typescript\n * import { defineHandlers, RetryableError } from '@amqp-contract/worker';\n * import { Future } from '@swan-io/boxed';\n * import { orderContract } from './contract';\n *\n * const handlers = defineHandlers(orderContract, {\n * processOrder: ({ payload }) =>\n * Future.fromPromise(processPayment(payload))\n * .mapOk(() => undefined)\n * .mapError((error) => new RetryableError('Payment failed', error)),\n * notifyOrder: ({ payload }) =>\n * Future.fromPromise(sendNotification(payload))\n * .mapOk(() => undefined)\n * .mapError((error) => new RetryableError('Notification failed', error)),\n * });\n * ```\n */\nexport function defineHandlers<TContract extends ContractDefinition>(\n contract: TContract,\n handlers: WorkerInferConsumerHandlers<TContract>,\n): WorkerInferConsumerHandlers<TContract> {\n validateHandlers(contract, handlers as unknown as Record<string, unknown>);\n return handlers;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/decompression.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":["/**\n * Error thrown when message validation fails\n */\nexport class MessageValidationError extends Error {\n constructor(\n public readonly consumerName: string,\n public readonly issues: unknown,\n ) {\n super(`Message validation failed for consumer \"${consumerName}\"`);\n this.name = \"MessageValidationError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Retryable errors - transient failures that may succeed on retry\n * Examples: network timeouts, rate limiting, temporary service unavailability\n *\n * Use this error type when the operation might succeed if retried.\n * The worker will apply exponential backoff and retry the message.\n */\nexport class RetryableError extends Error {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"RetryableError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Non-retryable errors - permanent failures that should not be retried\n * Examples: invalid data, business rule violations, permanent external failures\n *\n * Use this error type when retrying would not help - the message will be\n * immediately sent to the dead letter queue (DLQ) if configured.\n */\nexport class NonRetryableError extends Error {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"NonRetryableError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Union type representing all handler errors.\n * Use this type when defining handlers that explicitly signal error outcomes.\n */\nexport type HandlerError = RetryableError | NonRetryableError;\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Type guard to check if an error is a RetryableError.\n *\n * Use this to check error types in catch blocks or error handlers.\n *\n * @param error - The error to check\n * @returns True if the error is a RetryableError\n *\n * @example\n * ```typescript\n * import { isRetryableError } from '@amqp-contract/worker';\n *\n * try {\n * await processMessage();\n * } catch (error) {\n * if (isRetryableError(error)) {\n * console.log('Will retry:', error.message);\n * } else {\n * console.log('Permanent failure:', error);\n * }\n * }\n * ```\n */\nexport function isRetryableError(error: unknown): error is RetryableError {\n return error instanceof RetryableError;\n}\n\n/**\n * Type guard to check if an error is a NonRetryableError.\n *\n * Use this to check error types in catch blocks or error handlers.\n *\n * @param error - The error to check\n * @returns True if the error is a NonRetryableError\n *\n * @example\n * ```typescript\n * import { isNonRetryableError } from '@amqp-contract/worker';\n *\n * try {\n * await processMessage();\n * } catch (error) {\n * if (isNonRetryableError(error)) {\n * console.log('Will not retry:', error.message);\n * }\n * }\n * ```\n */\nexport function isNonRetryableError(error: unknown): error is NonRetryableError {\n return error instanceof NonRetryableError;\n}\n\n/**\n * Type guard to check if an error is any HandlerError (RetryableError or NonRetryableError).\n *\n * @param error - The error to check\n * @returns True if the error is a HandlerError\n *\n * @example\n * ```typescript\n * import { isHandlerError } from '@amqp-contract/worker';\n *\n * function handleError(error: unknown) {\n * if (isHandlerError(error)) {\n * // error is RetryableError | NonRetryableError\n * console.log('Handler error:', error.name, error.message);\n * }\n * }\n * ```\n */\nexport function isHandlerError(error: unknown): error is HandlerError {\n return isRetryableError(error) || isNonRetryableError(error);\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a RetryableError with less verbosity.\n *\n * This is a shorthand factory function for creating RetryableError instances.\n * Use it for cleaner error creation in handlers.\n *\n * @param message - Error message describing the failure\n * @param cause - Optional underlying error that caused this failure\n * @returns A new RetryableError instance\n *\n * @example\n * ```typescript\n * import { retryable } from '@amqp-contract/worker';\n * import { Future, Result } from '@swan-io/boxed';\n *\n * const handler = ({ payload }) =>\n * Future.fromPromise(processPayment(payload))\n * .mapOk(() => undefined)\n * .mapError((e) => retryable('Payment service unavailable', e));\n *\n * // Equivalent to:\n * // .mapError((e) => new RetryableError('Payment service unavailable', e));\n * ```\n */\nexport function retryable(message: string, cause?: unknown): RetryableError {\n return new RetryableError(message, cause);\n}\n\n/**\n * Create a NonRetryableError with less verbosity.\n *\n * This is a shorthand factory function for creating NonRetryableError instances.\n * Use it for cleaner error creation in handlers.\n *\n * @param message - Error message describing the failure\n * @param cause - Optional underlying error that caused this failure\n * @returns A new NonRetryableError instance\n *\n * @example\n * ```typescript\n * import { nonRetryable } from '@amqp-contract/worker';\n * import { Future, Result } from '@swan-io/boxed';\n *\n * const handler = ({ payload }) => {\n * if (!isValidPayload(payload)) {\n * return Future.value(Result.Error(nonRetryable('Invalid payload format')));\n * }\n * return Future.value(Result.Ok(undefined));\n * };\n *\n * // Equivalent to:\n * // return Future.value(Result.Error(new NonRetryableError('Invalid payload format')));\n * ```\n */\nexport function nonRetryable(message: string, cause?: unknown): NonRetryableError {\n return new NonRetryableError(message, cause);\n}\n","import { Future, Result } from \"@swan-io/boxed\";\nimport { gunzip, inflate } from \"node:zlib\";\nimport { TechnicalError } from \"@amqp-contract/core\";\nimport { promisify } from \"node:util\";\n\nconst gunzipAsync = promisify(gunzip);\nconst inflateAsync = promisify(inflate);\n\n/**\n * Supported content encodings for message decompression.\n */\nconst SUPPORTED_ENCODINGS = [\"gzip\", \"deflate\"] as const;\n\n/**\n * Type for supported content encodings.\n */\ntype SupportedEncoding = (typeof SUPPORTED_ENCODINGS)[number];\n\n/**\n * Type guard to check if a string is a supported encoding.\n */\nfunction isSupportedEncoding(encoding: string): encoding is SupportedEncoding {\n return SUPPORTED_ENCODINGS.includes(encoding.toLowerCase() as SupportedEncoding);\n}\n\n/**\n * Decompress a buffer based on the content-encoding header.\n *\n * @param buffer - The buffer to decompress\n * @param contentEncoding - The content-encoding header value (e.g., 'gzip', 'deflate')\n * @returns A Future with the decompressed buffer or a TechnicalError\n *\n * @internal\n */\nexport function decompressBuffer(\n buffer: Buffer,\n contentEncoding: string | undefined,\n): Future<Result<Buffer, TechnicalError>> {\n if (!contentEncoding) {\n return Future.value(Result.Ok(buffer));\n }\n\n const normalizedEncoding = contentEncoding.toLowerCase();\n\n if (!isSupportedEncoding(normalizedEncoding)) {\n return Future.value(\n Result.Error(\n new TechnicalError(\n `Unsupported content-encoding: \"${contentEncoding}\". ` +\n `Supported encodings are: ${SUPPORTED_ENCODINGS.join(\", \")}. ` +\n `Please check your publisher configuration.`,\n ),\n ),\n );\n }\n\n switch (normalizedEncoding) {\n case \"gzip\":\n return Future.fromPromise(gunzipAsync(buffer)).mapError(\n (error) => new TechnicalError(\"Failed to decompress gzip\", error),\n );\n case \"deflate\":\n return Future.fromPromise(inflateAsync(buffer)).mapError(\n (error) => new TechnicalError(\"Failed to decompress deflate\", error),\n );\n }\n}\n","import {\n AmqpClient,\n type Logger,\n TechnicalError,\n type TelemetryProvider,\n defaultTelemetryProvider,\n endSpanError,\n endSpanSuccess,\n recordConsumeMetric,\n startConsumeSpan,\n} from \"@amqp-contract/core\";\nimport type { AmqpConnectionManagerOptions, ConnectionUrl } from \"amqp-connection-manager\";\nimport type { Channel, ConsumeMessage } from \"amqplib\";\nimport {\n type ConsumerDefinition,\n type ContractDefinitionInput,\n type InferConsumerNames,\n type ResolvedRetryOptions,\n type ResolvedTtlBackoffRetryOptions,\n extractConsumer,\n} from \"@amqp-contract/contract\";\nimport { Future, Result } from \"@swan-io/boxed\";\nimport { MessageValidationError, NonRetryableError } from \"./errors.js\";\nimport type {\n WorkerInferConsumedMessage,\n WorkerInferConsumerHandler,\n WorkerInferConsumerHandlers,\n} from \"./types.js\";\nimport type { HandlerError } from \"./errors.js\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { decompressBuffer } from \"./decompression.js\";\n\n/**\n * Internal type for consumer options extracted from handler tuples.\n * Not exported - options are specified inline in the handler tuple types.\n *\n * Note: Retry configuration is now defined at the queue level in the contract,\n * not at the handler level. See `QueueDefinition.retry` for configuration options.\n */\ntype ConsumerOptions = {\n /** Number of messages to prefetch */\n prefetch?: number;\n};\n\n/**\n * Retry configuration from the contract with all values resolved.\n * This is a discriminated union on `mode` - TTL-backoff has the config fields,\n * quorum-native does not.\n */\ntype ResolvedRetryConfig = ResolvedRetryOptions;\n\n/**\n * Type guard to check if a handler entry is a tuple format [handler, options].\n */\nfunction isHandlerTuple(entry: unknown): entry is [unknown, ConsumerOptions] {\n return Array.isArray(entry) && entry.length === 2;\n}\n\n/**\n * Options for creating a type-safe AMQP worker.\n *\n * @typeParam TContract - The contract definition type\n *\n * @example\n * ```typescript\n * const options: CreateWorkerOptions<typeof contract> = {\n * contract: myContract,\n * handlers: {\n * // Simple handler\n * processOrder: ({ payload }) => {\n * console.log('Processing order:', payload.orderId);\n * return Future.value(Result.Ok(undefined));\n * },\n * // Handler with prefetch configuration\n * processPayment: [\n * ({ payload }) => {\n * console.log('Processing payment:', payload.paymentId);\n * return Future.value(Result.Ok(undefined));\n * },\n * { prefetch: 10 }\n * ]\n * },\n * urls: ['amqp://localhost'],\n * connectionOptions: {\n * heartbeatIntervalInSeconds: 30\n * },\n * logger: myLogger\n * };\n * ```\n *\n * Note: Retry configuration is defined at the queue level in the contract,\n * not at the handler level. See `QueueDefinition.retry` for configuration options.\n */\nexport type CreateWorkerOptions<TContract extends ContractDefinitionInput> = {\n /** The AMQP contract definition specifying consumers and their message schemas */\n contract: TContract;\n /**\n * Handlers for each consumer defined in the contract.\n * Handlers must return `Future<Result<void, HandlerError>>` for explicit error handling.\n * Use defineHandler() to create handlers.\n */\n handlers: WorkerInferConsumerHandlers<TContract>;\n /** AMQP broker URL(s). Multiple URLs provide failover support */\n urls: ConnectionUrl[];\n /** Optional connection configuration (heartbeat, reconnect settings, etc.) */\n connectionOptions?: AmqpConnectionManagerOptions | undefined;\n /** Optional logger for logging message consumption and errors */\n logger?: Logger | undefined;\n /**\n * Optional telemetry provider for tracing and metrics.\n * If not provided, uses the default provider which attempts to load OpenTelemetry.\n * OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed.\n */\n telemetry?: TelemetryProvider | undefined;\n};\n\n/**\n * Type-safe AMQP worker for consuming messages from RabbitMQ.\n *\n * This class provides automatic message validation, connection management,\n * and error handling for consuming messages based on a contract definition.\n *\n * @typeParam TContract - The contract definition type\n *\n * @example\n * ```typescript\n * import { TypedAmqpWorker } from '@amqp-contract/worker';\n * import { z } from 'zod';\n *\n * const contract = defineContract({\n * queues: {\n * orderProcessing: defineQueue('order-processing', { durable: true })\n * },\n * consumers: {\n * processOrder: defineConsumer('order-processing', z.object({\n * orderId: z.string(),\n * amount: z.number()\n * }))\n * }\n * });\n *\n * const worker = await TypedAmqpWorker.create({\n * contract,\n * handlers: {\n * processOrder: async (message) => {\n * console.log('Processing order', message.orderId);\n * // Process the order...\n * }\n * },\n * urls: ['amqp://localhost']\n * }).resultToPromise();\n *\n * // Close when done\n * await worker.close().resultToPromise();\n * ```\n */\nexport class TypedAmqpWorker<TContract extends ContractDefinitionInput> {\n /**\n * Internal handler storage - handlers returning `Future<Result>`.\n */\n private readonly actualHandlers: Partial<\n Record<\n InferConsumerNames<TContract>,\n WorkerInferConsumerHandler<TContract, InferConsumerNames<TContract>>\n >\n >;\n private readonly consumerOptions: Partial<Record<InferConsumerNames<TContract>, ConsumerOptions>>;\n private readonly consumerTags: Set<string> = new Set();\n private readonly telemetry: TelemetryProvider;\n\n private constructor(\n private readonly contract: TContract,\n private readonly amqpClient: AmqpClient,\n handlers: WorkerInferConsumerHandlers<TContract>,\n private readonly logger?: Logger,\n telemetry?: TelemetryProvider,\n ) {\n this.telemetry = telemetry ?? defaultTelemetryProvider;\n\n // Extract handlers and options from the handlers object\n this.actualHandlers = {};\n this.consumerOptions = {};\n\n // Cast handlers to a generic record for iteration\n const handlersRecord = handlers as Record<string, unknown>;\n\n for (const consumerName of Object.keys(handlersRecord)) {\n const handlerEntry = handlersRecord[consumerName];\n const typedConsumerName = consumerName as InferConsumerNames<TContract>;\n\n if (isHandlerTuple(handlerEntry)) {\n // Tuple format: [handler, options]\n const [handler, options] = handlerEntry;\n this.actualHandlers[typedConsumerName] = handler as WorkerInferConsumerHandler<\n TContract,\n InferConsumerNames<TContract>\n >;\n this.consumerOptions[typedConsumerName] = options;\n } else {\n // Direct function format\n this.actualHandlers[typedConsumerName] = handlerEntry as WorkerInferConsumerHandler<\n TContract,\n InferConsumerNames<TContract>\n >;\n }\n }\n }\n\n /**\n * Create a type-safe AMQP worker from a contract.\n *\n * Connection management (including automatic reconnection) is handled internally\n * by amqp-connection-manager via the {@link AmqpClient}. The worker will set up\n * consumers for all contract-defined handlers asynchronously in the background\n * once the underlying connection and channels are ready.\n *\n * Connections are automatically shared across clients and workers with the same\n * URLs and connection options, following RabbitMQ best practices.\n *\n * @param options - Configuration options for the worker\n * @returns A Future that resolves to a Result containing the worker or an error\n *\n * @example\n * ```typescript\n * const worker = await TypedAmqpWorker.create({\n * contract: myContract,\n * handlers: {\n * processOrder: async ({ payload }) => console.log('Order:', payload.orderId)\n * },\n * urls: ['amqp://localhost']\n * }).resultToPromise();\n * ```\n */\n static create<TContract extends ContractDefinitionInput>({\n contract,\n handlers,\n urls,\n connectionOptions,\n logger,\n telemetry,\n }: CreateWorkerOptions<TContract>): Future<Result<TypedAmqpWorker<TContract>, TechnicalError>> {\n const worker = new TypedAmqpWorker(\n contract,\n new AmqpClient(contract, {\n urls,\n connectionOptions,\n }),\n handlers,\n logger,\n telemetry,\n );\n\n // Note: Wait queues are now created by the core package in setupAmqpTopology\n // when the queue's retry mode is \"ttl-backoff\"\n return worker\n .waitForConnectionReady()\n .flatMapOk(() => worker.consumeAll())\n .mapOk(() => worker);\n }\n\n /**\n * Close the AMQP channel and connection.\n *\n * This gracefully closes the connection to the AMQP broker,\n * stopping all message consumption and cleaning up resources.\n *\n * @returns A Future that resolves to a Result indicating success or failure\n *\n * @example\n * ```typescript\n * const closeResult = await worker.close().resultToPromise();\n * if (closeResult.isOk()) {\n * console.log('Worker closed successfully');\n * }\n * ```\n */\n close(): Future<Result<void, TechnicalError>> {\n return Future.all(\n Array.from(this.consumerTags).map((consumerTag) =>\n this.amqpClient.cancel(consumerTag).mapErrorToResult((error) => {\n this.logger?.warn(\"Failed to cancel consumer during close\", { consumerTag, error });\n return Result.Ok(undefined);\n }),\n ),\n )\n .map(Result.all)\n .tapOk(() => {\n // Clear consumer tags after successful cancellation\n this.consumerTags.clear();\n })\n .flatMapOk(() => this.amqpClient.close())\n .mapOk(() => undefined);\n }\n\n /**\n * Get the retry configuration for a consumer's queue.\n * Defaults are applied in the contract's defineQueue, so we just return the config.\n */\n private getRetryConfigForConsumer(consumer: ConsumerDefinition): ResolvedRetryConfig {\n return consumer.queue.retry;\n }\n\n /**\n * Start consuming messages for all consumers.\n * TypeScript guarantees consumers exist (handlers require matching consumers).\n */\n private consumeAll(): Future<Result<void, TechnicalError>> {\n const consumers = this.contract.consumers!;\n const consumerNames = Object.keys(consumers) as InferConsumerNames<TContract>[];\n\n // Calculate max prefetch (AMQP 0.9.1 prefetch is per-channel)\n const maxPrefetch = consumerNames.reduce((max, name) => {\n const prefetch = this.consumerOptions[name]?.prefetch;\n return prefetch ? Math.max(max, prefetch) : max;\n }, 0);\n\n if (maxPrefetch > 0) {\n this.amqpClient.addSetup(async (channel: Channel) => {\n await channel.prefetch(maxPrefetch);\n });\n }\n\n return Future.all(consumerNames.map((name) => this.consume(name)))\n .map(Result.all)\n .mapOk(() => undefined);\n }\n\n private waitForConnectionReady(): Future<Result<void, TechnicalError>> {\n return this.amqpClient.waitForConnect();\n }\n\n /**\n * Start consuming messages for a specific consumer.\n * TypeScript guarantees consumer and handler exist for valid consumer names.\n */\n private consume<TName extends InferConsumerNames<TContract>>(\n consumerName: TName,\n ): Future<Result<void, TechnicalError>> {\n // Non-null assertions safe: TypeScript guarantees these exist for valid TName\n const consumerEntry = this.contract.consumers![consumerName as string]!;\n const consumer = extractConsumer(consumerEntry);\n const handler = this.actualHandlers[consumerName]!;\n\n return this.consumeSingle(\n consumerName,\n consumer,\n handler as Parameters<typeof this.consumeSingle<TName>>[2],\n );\n }\n\n /**\n * Validate data against a Standard Schema and handle errors.\n */\n private validateSchema(\n schema: StandardSchemaV1,\n data: unknown,\n context: { consumerName: string; queueName: string; field: string },\n msg: ConsumeMessage,\n ): Future<Result<unknown, TechnicalError>> {\n const rawValidation = schema[\"~standard\"].validate(data);\n const validationPromise =\n rawValidation instanceof Promise ? rawValidation : Promise.resolve(rawValidation);\n\n return Future.fromPromise(validationPromise)\n .mapError((error) => new TechnicalError(`Error validating ${context.field}`, error))\n .mapOkToResult((result) => {\n if (result.issues) {\n return Result.Error(\n new TechnicalError(\n `${context.field} validation failed`,\n new MessageValidationError(context.consumerName, result.issues),\n ),\n );\n }\n return Result.Ok(result.value);\n })\n .tapError((error) => {\n this.logger?.error(`${context.field} validation failed`, {\n consumerName: context.consumerName,\n queueName: context.queueName,\n error,\n });\n this.amqpClient.nack(msg, false, false);\n });\n }\n\n /**\n * Parse and validate a message from AMQP.\n * @returns Ok with validated message (payload + headers), or Error (message already nacked)\n */\n private parseAndValidateMessage<TName extends InferConsumerNames<TContract>>(\n msg: ConsumeMessage,\n consumer: ConsumerDefinition,\n consumerName: TName,\n ): Future<Result<WorkerInferConsumedMessage<TContract, TName>, TechnicalError>> {\n const context = {\n consumerName: String(consumerName),\n queueName: consumer.queue.name,\n };\n\n const nackAndError = (message: string, error?: unknown): TechnicalError => {\n this.logger?.error(message, { ...context, error });\n this.amqpClient.nack(msg, false, false);\n return new TechnicalError(message, error);\n };\n\n // Decompress → Parse JSON → Validate payload\n const parsePayload = decompressBuffer(msg.content, msg.properties.contentEncoding)\n .tapError((error) => {\n this.logger?.error(\"Failed to decompress message\", { ...context, error });\n this.amqpClient.nack(msg, false, false);\n })\n .mapOkToResult((buffer) =>\n Result.fromExecution(() => JSON.parse(buffer.toString()) as unknown).mapError((error) =>\n nackAndError(\"Failed to parse JSON\", error),\n ),\n )\n .flatMapOk((parsed) =>\n this.validateSchema(\n consumer.message.payload as StandardSchemaV1,\n parsed,\n { ...context, field: \"payload\" },\n msg,\n ),\n );\n\n // Validate headers (if schema defined)\n const parseHeaders = consumer.message.headers\n ? this.validateSchema(\n consumer.message.headers as StandardSchemaV1,\n msg.properties.headers ?? {},\n { ...context, field: \"headers\" },\n msg,\n )\n : Future.value(Result.Ok<unknown, TechnicalError>(undefined));\n\n return Future.allFromDict({ payload: parsePayload, headers: parseHeaders }).map(\n Result.allFromDict,\n ) as Future<Result<WorkerInferConsumedMessage<TContract, TName>, TechnicalError>>;\n }\n\n /**\n * Consume messages one at a time\n */\n private consumeSingle<TName extends InferConsumerNames<TContract>>(\n consumerName: TName,\n consumer: ConsumerDefinition,\n handler: (\n message: WorkerInferConsumedMessage<TContract, TName>,\n rawMessage: ConsumeMessage,\n ) => Future<Result<void, HandlerError>>,\n ): Future<Result<void, TechnicalError>> {\n const queueName = consumer.queue.name;\n\n // Start consuming\n return this.amqpClient\n .consume(queueName, async (msg) => {\n // Handle null messages (consumer cancellation)\n if (msg === null) {\n this.logger?.warn(\"Consumer cancelled by server\", {\n consumerName: String(consumerName),\n queueName,\n });\n return;\n }\n\n const startTime = Date.now();\n const span = startConsumeSpan(this.telemetry, queueName, String(consumerName), {\n \"messaging.rabbitmq.message.delivery_tag\": msg.fields.deliveryTag,\n });\n\n // Parse and validate message\n await this.parseAndValidateMessage(msg, consumer, consumerName)\n .flatMapOk((validatedMessage) =>\n handler(validatedMessage, msg)\n .flatMapOk(() => {\n this.logger?.info(\"Message consumed successfully\", {\n consumerName: String(consumerName),\n queueName,\n });\n // Acknowledge message on success\n this.amqpClient.ack(msg);\n\n // Record telemetry success\n const durationMs = Date.now() - startTime;\n endSpanSuccess(span);\n recordConsumeMetric(\n this.telemetry,\n queueName,\n String(consumerName),\n true,\n durationMs,\n );\n\n return Future.value(Result.Ok<void, HandlerError>(undefined));\n })\n .flatMapError((handlerError: HandlerError) => {\n // Handler returned an error\n this.logger?.error(\"Error processing message\", {\n consumerName: String(consumerName),\n queueName,\n errorType: handlerError.name,\n error: handlerError.message,\n });\n\n // Record telemetry failure\n const durationMs = Date.now() - startTime;\n endSpanError(span, handlerError);\n recordConsumeMetric(\n this.telemetry,\n queueName,\n String(consumerName),\n false,\n durationMs,\n );\n\n // Handle the error using retry mechanism\n return this.handleError(handlerError, msg, String(consumerName), consumer);\n }),\n )\n .tapError(() => {\n // Record telemetry failure for validation errors\n // Note: The actual validation error is logged in parseAndValidateMessage,\n // here we just record that validation failed for telemetry purposes\n const durationMs = Date.now() - startTime;\n endSpanError(span, new Error(\"Message validation failed\"));\n recordConsumeMetric(this.telemetry, queueName, String(consumerName), false, durationMs);\n })\n .toPromise();\n })\n .tapOk((consumerTag) => {\n // Store consumer tag for later cancellation\n this.consumerTags.add(consumerTag);\n })\n .mapError(\n (error) =>\n new TechnicalError(`Failed to start consuming for \"${String(consumerName)}\"`, error),\n )\n .mapOk(() => undefined);\n }\n\n /**\n * Handle error in message processing with retry logic.\n *\n * Flow depends on retry mode:\n *\n * **quorum-native mode:**\n * 1. If NonRetryableError -> send directly to DLQ (no retry)\n * 2. Otherwise -> nack with requeue=true (RabbitMQ handles delivery count)\n *\n * **ttl-backoff mode:**\n * 1. If NonRetryableError -> send directly to DLQ (no retry)\n * 2. If max retries exceeded -> send to DLQ\n * 3. Otherwise -> publish to wait queue with TTL for retry\n *\n * **Legacy mode (no retry config):**\n * 1. nack with requeue=true (immediate requeue)\n */\n private handleError(\n error: Error,\n msg: ConsumeMessage,\n consumerName: string,\n consumer: ConsumerDefinition,\n ): Future<Result<void, TechnicalError>> {\n // NonRetryableError -> send directly to DLQ without retrying\n if (error instanceof NonRetryableError) {\n this.logger?.error(\"Non-retryable error, sending to DLQ immediately\", {\n consumerName,\n errorType: error.name,\n error: error.message,\n });\n this.sendToDLQ(msg, consumer);\n return Future.value(Result.Ok(undefined));\n }\n\n // Get retry config from the queue definition in the contract\n const config = this.getRetryConfigForConsumer(consumer);\n\n // Quorum-native mode: let RabbitMQ handle retry via x-delivery-count\n if (config.mode === \"quorum-native\") {\n return this.handleErrorQuorumNative(error, msg, consumerName, consumer);\n }\n\n // TTL-backoff mode: use wait queue with exponential backoff\n return this.handleErrorTtlBackoff(error, msg, consumerName, consumer, config);\n }\n\n /**\n * Handle error using quorum queue's native delivery limit feature.\n *\n * Simply requeues the message with nack(requeue=true). RabbitMQ automatically:\n * - Increments x-delivery-count header\n * - Dead-letters the message when count exceeds x-delivery-limit\n *\n * This is simpler than TTL-based retry but provides immediate retries only.\n */\n private handleErrorQuorumNative(\n error: Error,\n msg: ConsumeMessage,\n consumerName: string,\n consumer: ConsumerDefinition,\n ): Future<Result<void, TechnicalError>> {\n const queue = consumer.queue;\n const queueName = queue.name;\n // x-delivery-count is incremented on each delivery attempt\n // When x-delivery-count equals x-delivery-limit, message is dead-lettered on next attempt\n const deliveryCount = (msg.properties.headers?.[\"x-delivery-count\"] as number) ?? 0;\n // This function is only called for quorum-native mode, which requires quorum queues\n const deliveryLimit = queue.type === \"quorum\" ? queue.deliveryLimit : undefined;\n\n // After this requeue, RabbitMQ will increment deliveryCount\n // Message is dead-lettered when deliveryCount reaches deliveryLimit\n // So if deliveryCount == deliveryLimit - 1, the next failure will dead-letter the message\n const attemptsBeforeDeadLetter =\n deliveryLimit !== undefined ? Math.max(0, deliveryLimit - deliveryCount - 1) : \"unknown\";\n\n // Log warning if this is the last attempt before dead-lettering\n if (deliveryLimit !== undefined && deliveryCount >= deliveryLimit - 1) {\n this.logger?.warn(\"Message at final delivery attempt (quorum-native mode)\", {\n consumerName,\n queueName,\n deliveryCount,\n deliveryLimit,\n willDeadLetterOnNextFailure: deliveryCount === deliveryLimit - 1,\n alreadyExceededLimit: deliveryCount >= deliveryLimit,\n error: error.message,\n });\n } else {\n this.logger?.warn(\"Retrying message (quorum-native mode)\", {\n consumerName,\n queueName,\n deliveryCount,\n deliveryLimit,\n attemptsBeforeDeadLetter,\n error: error.message,\n });\n }\n\n // Requeue the message - RabbitMQ tracks delivery count and handles dead-lettering\n this.amqpClient.nack(msg, false, true);\n return Future.value(Result.Ok(undefined));\n }\n\n /**\n * Handle error using TTL + wait queue pattern for exponential backoff.\n */\n private handleErrorTtlBackoff(\n error: Error,\n msg: ConsumeMessage,\n consumerName: string,\n consumer: ConsumerDefinition,\n config: ResolvedTtlBackoffRetryOptions,\n ): Future<Result<void, TechnicalError>> {\n // Get retry count from headers\n const retryCount = (msg.properties.headers?.[\"x-retry-count\"] as number) ?? 0;\n\n // Max retries exceeded -> DLQ\n if (retryCount >= config.maxRetries) {\n this.logger?.error(\"Max retries exceeded, sending to DLQ\", {\n consumerName,\n retryCount,\n maxRetries: config.maxRetries,\n error: error.message,\n });\n this.sendToDLQ(msg, consumer);\n return Future.value(Result.Ok(undefined));\n }\n\n // Retry with exponential backoff\n const delayMs = this.calculateRetryDelay(retryCount, config);\n this.logger?.warn(\"Retrying message (ttl-backoff mode)\", {\n consumerName,\n retryCount: retryCount + 1,\n delayMs,\n error: error.message,\n });\n\n return this.publishForRetry(msg, consumer, retryCount + 1, delayMs, error);\n }\n\n /**\n * Calculate retry delay with exponential backoff and optional jitter.\n */\n private calculateRetryDelay(retryCount: number, config: ResolvedTtlBackoffRetryOptions): number {\n const { initialDelayMs, maxDelayMs, backoffMultiplier, jitter } = config;\n\n let delay = Math.min(initialDelayMs * Math.pow(backoffMultiplier, retryCount), maxDelayMs);\n\n if (jitter) {\n // Add jitter: random value between 50% and 100% of calculated delay\n delay = delay * (0.5 + Math.random() * 0.5);\n }\n\n return Math.floor(delay);\n }\n\n /**\n * Parse message content for republishing.\n * Prevents double JSON serialization by converting Buffer to object when possible.\n */\n private parseMessageContentForRetry(msg: ConsumeMessage, queueName: string): Buffer | unknown {\n let content: Buffer | unknown = msg.content;\n\n // If message is not compressed (no contentEncoding), parse it to get the original object\n if (!msg.properties.contentEncoding) {\n try {\n content = JSON.parse(msg.content.toString());\n } catch (err) {\n this.logger?.warn(\"Failed to parse message for retry, using original buffer\", {\n queueName,\n error: err,\n });\n }\n }\n\n return content;\n }\n\n /**\n * Publish message to wait queue for retry after TTL expires.\n *\n * ┌─────────────────────────────────────────────────────────────────┐\n * │ Retry Flow (Native RabbitMQ TTL + DLX Pattern) │\n * ├─────────────────────────────────────────────────────────────────┤\n * │ │\n * │ 1. Handler throws any Error │\n * │ ↓ │\n * │ 2. Worker publishes to DLX with routing key: {queue}-wait │\n * │ ↓ │\n * │ 3. DLX routes to wait queue: {queue}-wait │\n * │ (with expiration: calculated backoff delay) │\n * │ ↓ │\n * │ 4. Message waits in queue until TTL expires │\n * │ ↓ │\n * │ 5. Expired message dead-lettered to DLX │\n * │ (with routing key: {queue}) │\n * │ ↓ │\n * │ 6. DLX routes back to main queue → RETRY │\n * │ ↓ │\n * │ 7. If retries exhausted: nack without requeue → DLQ │\n * │ │\n * └─────────────────────────────────────────────────────────────────┘\n */\n private publishForRetry(\n msg: ConsumeMessage,\n consumer: ConsumerDefinition,\n newRetryCount: number,\n delayMs: number,\n error: Error,\n ): Future<Result<void, TechnicalError>> {\n const queueName = consumer.queue.name;\n const deadLetter = consumer.queue.deadLetter;\n\n if (!deadLetter) {\n this.logger?.warn(\n \"Cannot retry: queue does not have DLX configured, falling back to nack with requeue\",\n {\n queueName,\n },\n );\n this.amqpClient.nack(msg, false, true);\n return Future.value(Result.Ok(undefined));\n }\n\n const dlxName = deadLetter.exchange.name;\n const waitRoutingKey = `${queueName}-wait`;\n\n // Acknowledge original message\n this.amqpClient.ack(msg);\n\n const content = this.parseMessageContentForRetry(msg, queueName);\n\n // Publish to DLX with wait routing key\n return this.amqpClient\n .publish(dlxName, waitRoutingKey, content, {\n ...msg.properties,\n expiration: delayMs.toString(), // Per-message TTL\n headers: {\n ...msg.properties.headers,\n \"x-retry-count\": newRetryCount,\n \"x-last-error\": error.message,\n \"x-first-failure-timestamp\":\n msg.properties.headers?.[\"x-first-failure-timestamp\"] ?? Date.now(),\n },\n })\n .mapOkToResult((published) => {\n if (!published) {\n this.logger?.error(\"Failed to publish message for retry (write buffer full)\", {\n queueName,\n waitRoutingKey,\n retryCount: newRetryCount,\n });\n return Result.Error(\n new TechnicalError(\"Failed to publish message for retry (write buffer full)\"),\n );\n }\n\n this.logger?.info(\"Message published for retry\", {\n queueName,\n waitRoutingKey,\n retryCount: newRetryCount,\n delayMs,\n });\n return Result.Ok(undefined);\n });\n }\n\n /**\n * Send message to dead letter queue.\n * Nacks the message without requeue, relying on DLX configuration.\n */\n private sendToDLQ(msg: ConsumeMessage, consumer: ConsumerDefinition): void {\n const queueName = consumer.queue.name;\n const hasDeadLetter = consumer.queue.deadLetter !== undefined;\n\n if (!hasDeadLetter) {\n this.logger?.warn(\"Queue does not have DLX configured - message will be lost on nack\", {\n queueName,\n });\n }\n\n this.logger?.info(\"Sending message to DLQ\", {\n queueName,\n deliveryTag: msg.fields.deliveryTag,\n });\n\n // Nack without requeue - relies on DLX configuration\n this.amqpClient.nack(msg, false, false);\n }\n}\n","import type { ContractDefinitionInput, InferConsumerNames } from \"@amqp-contract/contract\";\nimport type {\n WorkerInferConsumerHandler,\n WorkerInferConsumerHandlerEntry,\n WorkerInferConsumerHandlers,\n} from \"./types.js\";\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Validate that a consumer exists in the contract\n */\nfunction validateConsumerExists<TContract extends ContractDefinitionInput>(\n contract: TContract,\n consumerName: string,\n): void {\n const consumers = contract.consumers;\n\n if (!consumers || !(consumerName in consumers)) {\n const availableConsumers = consumers ? Object.keys(consumers) : [];\n const available = availableConsumers.length > 0 ? availableConsumers.join(\", \") : \"none\";\n throw new Error(\n `Consumer \"${consumerName}\" not found in contract. Available consumers: ${available}`,\n );\n }\n}\n\n/**\n * Validate that all handlers reference valid consumers\n */\nfunction validateHandlers<TContract extends ContractDefinitionInput>(\n contract: TContract,\n handlers: Record<string, unknown>,\n): void {\n const consumers = contract.consumers;\n const availableConsumers = Object.keys(consumers ?? {});\n const availableConsumerNames =\n availableConsumers.length > 0 ? availableConsumers.join(\", \") : \"none\";\n\n for (const handlerName of Object.keys(handlers)) {\n if (!consumers || !(handlerName in consumers)) {\n throw new Error(\n `Consumer \"${handlerName}\" not found in contract. Available consumers: ${availableConsumerNames}`,\n );\n }\n }\n}\n\n// =============================================================================\n// Handler Definitions\n// =============================================================================\n\n/**\n * Define a type-safe handler for a specific consumer in a contract.\n *\n * **Recommended:** This function creates handlers that return `Future<Result<void, HandlerError>>`,\n * providing explicit error handling and better control over retry behavior.\n *\n * Supports two patterns:\n * 1. Simple handler: just the function\n * 2. Handler with options: [handler, { prefetch: 10 }]\n *\n * @template TContract - The contract definition type\n * @template TName - The consumer name from the contract\n * @param contract - The contract definition containing the consumer\n * @param consumerName - The name of the consumer from the contract\n * @param handler - The handler function that returns `Future<Result<void, HandlerError>>`\n * @param options - Optional consumer options (prefetch)\n * @returns A type-safe handler that can be used with TypedAmqpWorker\n *\n * @example\n * ```typescript\n * import { defineHandler, RetryableError, NonRetryableError } from '@amqp-contract/worker';\n * import { Future, Result } from '@swan-io/boxed';\n * import { orderContract } from './contract';\n *\n * // Simple handler with explicit error handling using mapError\n * const processOrderHandler = defineHandler(\n * orderContract,\n * 'processOrder',\n * ({ payload }) =>\n * Future.fromPromise(processPayment(payload))\n * .mapOk(() => undefined)\n * .mapError((error) => new RetryableError('Payment failed', error))\n * );\n *\n * // Handler with validation (non-retryable error)\n * const validateOrderHandler = defineHandler(\n * orderContract,\n * 'validateOrder',\n * ({ payload }) => {\n * if (payload.amount < 1) {\n * // Won't be retried - goes directly to DLQ\n * return Future.value(Result.Error(new NonRetryableError('Invalid order amount')));\n * }\n * return Future.value(Result.Ok(undefined));\n * }\n * );\n * ```\n */\nexport function defineHandler<\n TContract extends ContractDefinitionInput,\n TName extends InferConsumerNames<TContract>,\n>(\n contract: TContract,\n consumerName: TName,\n handler: WorkerInferConsumerHandler<TContract, TName>,\n): WorkerInferConsumerHandlerEntry<TContract, TName>;\nexport function defineHandler<\n TContract extends ContractDefinitionInput,\n TName extends InferConsumerNames<TContract>,\n>(\n contract: TContract,\n consumerName: TName,\n handler: WorkerInferConsumerHandler<TContract, TName>,\n options: { prefetch?: number },\n): WorkerInferConsumerHandlerEntry<TContract, TName>;\nexport function defineHandler<\n TContract extends ContractDefinitionInput,\n TName extends InferConsumerNames<TContract>,\n>(\n contract: TContract,\n consumerName: TName,\n handler: WorkerInferConsumerHandler<TContract, TName>,\n options?: { prefetch?: number },\n): WorkerInferConsumerHandlerEntry<TContract, TName> {\n validateConsumerExists(contract, String(consumerName));\n\n if (options) {\n return [handler, options];\n }\n return handler;\n}\n\n/**\n * Define multiple type-safe handlers for consumers in a contract.\n *\n * **Recommended:** This function creates handlers that return `Future<Result<void, HandlerError>>`,\n * providing explicit error handling and better control over retry behavior.\n *\n * @template TContract - The contract definition type\n * @param contract - The contract definition containing the consumers\n * @param handlers - An object with handler functions for each consumer\n * @returns A type-safe handlers object that can be used with TypedAmqpWorker\n *\n * @example\n * ```typescript\n * import { defineHandlers, RetryableError } from '@amqp-contract/worker';\n * import { Future } from '@swan-io/boxed';\n * import { orderContract } from './contract';\n *\n * const handlers = defineHandlers(orderContract, {\n * processOrder: ({ payload }) =>\n * Future.fromPromise(processPayment(payload))\n * .mapOk(() => undefined)\n * .mapError((error) => new RetryableError('Payment failed', error)),\n * notifyOrder: ({ payload }) =>\n * Future.fromPromise(sendNotification(payload))\n * .mapOk(() => undefined)\n * .mapError((error) => new RetryableError('Notification failed', error)),\n * });\n * ```\n */\nexport function defineHandlers<TContract extends ContractDefinitionInput>(\n contract: TContract,\n handlers: WorkerInferConsumerHandlers<TContract>,\n): WorkerInferConsumerHandlers<TContract> {\n validateHandlers(contract, handlers as unknown as Record<string, unknown>);\n return handlers;\n}\n"],"mappings":"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"}
package/docs/index.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ### MessageValidationError
10
10
 
11
- Defined in: [packages/worker/src/errors.ts:4](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L4)
11
+ Defined in: [packages/worker/src/errors.ts:4](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L4)
12
12
 
13
13
  Error thrown when message validation fails
14
14
 
@@ -24,7 +24,7 @@ Error thrown when message validation fails
24
24
  new MessageValidationError(consumerName, issues): MessageValidationError;
25
25
  ```
26
26
 
27
- Defined in: [packages/worker/src/errors.ts:5](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L5)
27
+ Defined in: [packages/worker/src/errors.ts:5](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L5)
28
28
 
29
29
  ###### Parameters
30
30
 
@@ -48,8 +48,8 @@ Error.constructor
48
48
  | Property | Modifier | Type | Description | Inherited from | Defined in |
49
49
  | ------ | ------ | ------ | ------ | ------ | ------ |
50
50
  | <a id="cause"></a> `cause?` | `public` | `unknown` | - | `Error.cause` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es2022.error.d.ts:26 |
51
- | <a id="consumername"></a> `consumerName` | `readonly` | `string` | - | - | [packages/worker/src/errors.ts:6](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L6) |
52
- | <a id="issues"></a> `issues` | `readonly` | `unknown` | - | - | [packages/worker/src/errors.ts:7](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L7) |
51
+ | <a id="consumername"></a> `consumerName` | `readonly` | `string` | - | - | [packages/worker/src/errors.ts:6](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L6) |
52
+ | <a id="issues"></a> `issues` | `readonly` | `unknown` | - | - | [packages/worker/src/errors.ts:7](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L7) |
53
53
  | <a id="message"></a> `message` | `public` | `string` | - | `Error.message` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1077 |
54
54
  | <a id="name"></a> `name` | `public` | `string` | - | `Error.name` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1076 |
55
55
  | <a id="stack"></a> `stack?` | `public` | `string` | - | `Error.stack` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1078 |
@@ -159,7 +159,7 @@ Error.prepareStackTrace
159
159
 
160
160
  ### NonRetryableError
161
161
 
162
- Defined in: [packages/worker/src/errors.ts:52](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L52)
162
+ Defined in: [packages/worker/src/errors.ts:52](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L52)
163
163
 
164
164
  Non-retryable errors - permanent failures that should not be retried
165
165
  Examples: invalid data, business rule violations, permanent external failures
@@ -179,7 +179,7 @@ immediately sent to the dead letter queue (DLQ) if configured.
179
179
  new NonRetryableError(message, cause?): NonRetryableError;
180
180
  ```
181
181
 
182
- Defined in: [packages/worker/src/errors.ts:53](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L53)
182
+ Defined in: [packages/worker/src/errors.ts:53](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L53)
183
183
 
184
184
  ###### Parameters
185
185
 
@@ -202,7 +202,7 @@ Error.constructor
202
202
 
203
203
  | Property | Modifier | Type | Description | Inherited from | Defined in |
204
204
  | ------ | ------ | ------ | ------ | ------ | ------ |
205
- | <a id="cause-1"></a> `cause?` | `readonly` | `unknown` | - | `Error.cause` | [packages/worker/src/errors.ts:55](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L55) |
205
+ | <a id="cause-1"></a> `cause?` | `readonly` | `unknown` | - | `Error.cause` | [packages/worker/src/errors.ts:55](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L55) |
206
206
  | <a id="message-1"></a> `message` | `public` | `string` | - | `Error.message` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1077 |
207
207
  | <a id="name-1"></a> `name` | `public` | `string` | - | `Error.name` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1076 |
208
208
  | <a id="stack-1"></a> `stack?` | `public` | `string` | - | `Error.stack` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1078 |
@@ -312,7 +312,7 @@ Error.prepareStackTrace
312
312
 
313
313
  ### RetryableError
314
314
 
315
- Defined in: [packages/worker/src/errors.ts:28](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L28)
315
+ Defined in: [packages/worker/src/errors.ts:28](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L28)
316
316
 
317
317
  Retryable errors - transient failures that may succeed on retry
318
318
  Examples: network timeouts, rate limiting, temporary service unavailability
@@ -332,7 +332,7 @@ The worker will apply exponential backoff and retry the message.
332
332
  new RetryableError(message, cause?): RetryableError;
333
333
  ```
334
334
 
335
- Defined in: [packages/worker/src/errors.ts:29](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L29)
335
+ Defined in: [packages/worker/src/errors.ts:29](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L29)
336
336
 
337
337
  ###### Parameters
338
338
 
@@ -355,7 +355,7 @@ Error.constructor
355
355
 
356
356
  | Property | Modifier | Type | Description | Inherited from | Defined in |
357
357
  | ------ | ------ | ------ | ------ | ------ | ------ |
358
- | <a id="cause-2"></a> `cause?` | `readonly` | `unknown` | - | `Error.cause` | [packages/worker/src/errors.ts:31](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L31) |
358
+ | <a id="cause-2"></a> `cause?` | `readonly` | `unknown` | - | `Error.cause` | [packages/worker/src/errors.ts:31](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L31) |
359
359
  | <a id="message-2"></a> `message` | `public` | `string` | - | `Error.message` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1077 |
360
360
  | <a id="name-2"></a> `name` | `public` | `string` | - | `Error.name` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1076 |
361
361
  | <a id="stack-2"></a> `stack?` | `public` | `string` | - | `Error.stack` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1078 |
@@ -465,7 +465,7 @@ Error.prepareStackTrace
465
465
 
466
466
  ### TypedAmqpWorker
467
467
 
468
- Defined in: [packages/worker/src/worker.ts:156](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L156)
468
+ Defined in: [packages/worker/src/worker.ts:157](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L157)
469
469
 
470
470
  Type-safe AMQP worker for consuming messages from RabbitMQ.
471
471
 
@@ -509,7 +509,7 @@ await worker.close().resultToPromise();
509
509
 
510
510
  | Type Parameter | Description |
511
511
  | ------ | ------ |
512
- | `TContract` *extends* `ContractDefinition` | The contract definition type |
512
+ | `TContract` *extends* `ContractDefinitionInput` | The contract definition type |
513
513
 
514
514
  #### Methods
515
515
 
@@ -519,7 +519,7 @@ await worker.close().resultToPromise();
519
519
  close(): Future<Result<void, TechnicalError>>;
520
520
  ```
521
521
 
522
- Defined in: [packages/worker/src/worker.ts:276](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L276)
522
+ Defined in: [packages/worker/src/worker.ts:277](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L277)
523
523
 
524
524
  Close the AMQP channel and connection.
525
525
 
@@ -547,7 +547,7 @@ if (closeResult.isOk()) {
547
547
  static create<TContract>(options): Future<Result<TypedAmqpWorker<TContract>, TechnicalError>>;
548
548
  ```
549
549
 
550
- Defined in: [packages/worker/src/worker.ts:233](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L233)
550
+ Defined in: [packages/worker/src/worker.ts:234](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L234)
551
551
 
552
552
  Create a type-safe AMQP worker from a contract.
553
553
 
@@ -563,7 +563,7 @@ URLs and connection options, following RabbitMQ best practices.
563
563
 
564
564
  | Type Parameter |
565
565
  | ------ |
566
- | `TContract` *extends* `ContractDefinition` |
566
+ | `TContract` *extends* `ContractDefinitionInput` |
567
567
 
568
568
  ###### Parameters
569
569
 
@@ -597,7 +597,7 @@ const worker = await TypedAmqpWorker.create({
597
597
  type CreateWorkerOptions<TContract> = object;
598
598
  ```
599
599
 
600
- Defined in: [packages/worker/src/worker.ts:93](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L93)
600
+ Defined in: [packages/worker/src/worker.ts:94](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L94)
601
601
 
602
602
  Options for creating a type-safe AMQP worker.
603
603
 
@@ -636,18 +636,18 @@ not at the handler level. See `QueueDefinition.retry` for configuration options.
636
636
 
637
637
  | Type Parameter | Description |
638
638
  | ------ | ------ |
639
- | `TContract` *extends* `ContractDefinition` | The contract definition type |
639
+ | `TContract` *extends* `ContractDefinitionInput` | The contract definition type |
640
640
 
641
641
  #### Properties
642
642
 
643
643
  | Property | Type | Description | Defined in |
644
644
  | ------ | ------ | ------ | ------ |
645
- | <a id="connectionoptions"></a> `connectionOptions?` | `AmqpConnectionManagerOptions` | Optional connection configuration (heartbeat, reconnect settings, etc.) | [packages/worker/src/worker.ts:105](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L105) |
646
- | <a id="contract"></a> `contract` | `TContract` | The AMQP contract definition specifying consumers and their message schemas | [packages/worker/src/worker.ts:95](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L95) |
647
- | <a id="handlers"></a> `handlers` | [`WorkerInferConsumerHandlers`](#workerinferconsumerhandlers)&lt;`TContract`&gt; | Handlers for each consumer defined in the contract. Handlers must return `Future<Result<void, HandlerError>>` for explicit error handling. Use defineHandler() to create handlers. | [packages/worker/src/worker.ts:101](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L101) |
648
- | <a id="logger"></a> `logger?` | `Logger` | Optional logger for logging message consumption and errors | [packages/worker/src/worker.ts:107](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L107) |
649
- | <a id="telemetry"></a> `telemetry?` | `TelemetryProvider` | Optional telemetry provider for tracing and metrics. If not provided, uses the default provider which attempts to load OpenTelemetry. OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed. | [packages/worker/src/worker.ts:113](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L113) |
650
- | <a id="urls"></a> `urls` | `ConnectionUrl`[] | AMQP broker URL(s). Multiple URLs provide failover support | [packages/worker/src/worker.ts:103](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/worker.ts#L103) |
645
+ | <a id="connectionoptions"></a> `connectionOptions?` | `AmqpConnectionManagerOptions` | Optional connection configuration (heartbeat, reconnect settings, etc.) | [packages/worker/src/worker.ts:106](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L106) |
646
+ | <a id="contract"></a> `contract` | `TContract` | The AMQP contract definition specifying consumers and their message schemas | [packages/worker/src/worker.ts:96](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L96) |
647
+ | <a id="handlers"></a> `handlers` | [`WorkerInferConsumerHandlers`](#workerinferconsumerhandlers)&lt;`TContract`&gt; | Handlers for each consumer defined in the contract. Handlers must return `Future<Result<void, HandlerError>>` for explicit error handling. Use defineHandler() to create handlers. | [packages/worker/src/worker.ts:102](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L102) |
648
+ | <a id="logger"></a> `logger?` | `Logger` | Optional logger for logging message consumption and errors | [packages/worker/src/worker.ts:108](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L108) |
649
+ | <a id="telemetry"></a> `telemetry?` | `TelemetryProvider` | Optional telemetry provider for tracing and metrics. If not provided, uses the default provider which attempts to load OpenTelemetry. OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed. | [packages/worker/src/worker.ts:114](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L114) |
650
+ | <a id="urls"></a> `urls` | `ConnectionUrl`[] | AMQP broker URL(s). Multiple URLs provide failover support | [packages/worker/src/worker.ts:104](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/worker.ts#L104) |
651
651
 
652
652
  ***
653
653
 
@@ -659,7 +659,7 @@ type HandlerError =
659
659
  | NonRetryableError;
660
660
  ```
661
661
 
662
- Defined in: [packages/worker/src/errors.ts:73](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L73)
662
+ Defined in: [packages/worker/src/errors.ts:73](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L73)
663
663
 
664
664
  Union type representing all handler errors.
665
665
  Use this type when defining handlers that explicitly signal error outcomes.
@@ -672,7 +672,7 @@ Use this type when defining handlers that explicitly signal error outcomes.
672
672
  type WorkerConsumedMessage<TPayload, THeaders> = object;
673
673
  ```
674
674
 
675
- Defined in: [packages/worker/src/types.ts:86](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L86)
675
+ Defined in: [packages/worker/src/types.ts:106](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L106)
676
676
 
677
677
  A consumed message containing parsed payload and headers.
678
678
 
@@ -702,8 +702,8 @@ const handler = defineHandler(contract, 'processOrder', (message, rawMessage) =>
702
702
 
703
703
  | Property | Type | Description | Defined in |
704
704
  | ------ | ------ | ------ | ------ |
705
- | <a id="headers"></a> `headers` | `THeaders` *extends* `undefined` ? `undefined` : `THeaders` | The validated message headers (present only when headers schema is defined) | [packages/worker/src/types.ts:90](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L90) |
706
- | <a id="payload"></a> `payload` | `TPayload` | The validated message payload | [packages/worker/src/types.ts:88](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L88) |
705
+ | <a id="headers"></a> `headers` | `THeaders` *extends* `undefined` ? `undefined` : `THeaders` | The validated message headers (present only when headers schema is defined) | [packages/worker/src/types.ts:110](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L110) |
706
+ | <a id="payload"></a> `payload` | `TPayload` | The validated message payload | [packages/worker/src/types.ts:108](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L108) |
707
707
 
708
708
  ***
709
709
 
@@ -713,7 +713,7 @@ const handler = defineHandler(contract, 'processOrder', (message, rawMessage) =>
713
713
  type WorkerInferConsumedMessage<TContract, TName> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
714
714
  ```
715
715
 
716
- Defined in: [packages/worker/src/types.ts:97](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L97)
716
+ Defined in: [packages/worker/src/types.ts:117](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L117)
717
717
 
718
718
  Infer the full consumed message type for a specific consumer.
719
719
  Includes both payload and headers (if defined).
@@ -722,7 +722,7 @@ Includes both payload and headers (if defined).
722
722
 
723
723
  | Type Parameter |
724
724
  | ------ |
725
- | `TContract` *extends* `ContractDefinition` |
725
+ | `TContract` *extends* `ContractDefinitionInput` |
726
726
  | `TName` *extends* `InferConsumerNames`&lt;`TContract`&gt; |
727
727
 
728
728
  ***
@@ -733,7 +733,7 @@ Includes both payload and headers (if defined).
733
733
  type WorkerInferConsumerHandler<TContract, TName> = (message, rawMessage) => Future<Result<void, HandlerError>>;
734
734
  ```
735
735
 
736
- Defined in: [packages/worker/src/types.ts:136](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L136)
736
+ Defined in: [packages/worker/src/types.ts:156](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L156)
737
737
 
738
738
  Consumer handler type for a specific consumer.
739
739
  Returns a `Future<Result<void, HandlerError>>` for explicit error handling.
@@ -749,7 +749,7 @@ types from a contract definition at compile time.
749
749
 
750
750
  | Type Parameter |
751
751
  | ------ |
752
- | `TContract` *extends* `ContractDefinition` |
752
+ | `TContract` *extends* `ContractDefinitionInput` |
753
753
  | `TName` *extends* `InferConsumerNames`&lt;`TContract`&gt; |
754
754
 
755
755
  #### Parameters
@@ -786,7 +786,7 @@ type WorkerInferConsumerHandlerEntry<TContract, TName> =
786
786
  }];
787
787
  ```
788
788
 
789
- Defined in: [packages/worker/src/types.ts:154](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L154)
789
+ Defined in: [packages/worker/src/types.ts:174](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L174)
790
790
 
791
791
  Handler entry for a consumer - either a function or a tuple of [handler, options].
792
792
 
@@ -801,7 +801,7 @@ not at the handler level. See `QueueDefinition.retry` for configuration options.
801
801
 
802
802
  | Type Parameter |
803
803
  | ------ |
804
- | `TContract` *extends* `ContractDefinition` |
804
+ | `TContract` *extends* `ContractDefinitionInput` |
805
805
  | `TName` *extends* `InferConsumerNames`&lt;`TContract`&gt; |
806
806
 
807
807
  ***
@@ -812,7 +812,7 @@ not at the handler level. See `QueueDefinition.retry` for configuration options.
812
812
  type WorkerInferConsumerHandlers<TContract> = { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandlerEntry<TContract, K> };
813
813
  ```
814
814
 
815
- Defined in: [packages/worker/src/types.ts:175](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L175)
815
+ Defined in: [packages/worker/src/types.ts:195](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L195)
816
816
 
817
817
  Consumer handlers for a contract.
818
818
  All handlers return `Future<Result<void, HandlerError>>` for explicit error control.
@@ -821,7 +821,7 @@ All handlers return `Future<Result<void, HandlerError>>` for explicit error cont
821
821
 
822
822
  | Type Parameter |
823
823
  | ------ |
824
- | `TContract` *extends* `ContractDefinition` |
824
+ | `TContract` *extends* `ContractDefinitionInput` |
825
825
 
826
826
  #### Example
827
827
 
@@ -842,7 +842,7 @@ const handlers: WorkerInferConsumerHandlers<typeof contract> = {
842
842
  type WorkerInferConsumerHeaders<TContract, TName> = ConsumerInferHeadersInput<InferConsumer<TContract, TName>>;
843
843
  ```
844
844
 
845
- Defined in: [packages/worker/src/types.ts:61](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L61)
845
+ Defined in: [packages/worker/src/types.ts:81](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L81)
846
846
 
847
847
  Infer the headers type for a specific consumer
848
848
  Returns undefined if no headers schema is defined
@@ -851,7 +851,7 @@ Returns undefined if no headers schema is defined
851
851
 
852
852
  | Type Parameter |
853
853
  | ------ |
854
- | `TContract` *extends* `ContractDefinition` |
854
+ | `TContract` *extends* `ContractDefinitionInput` |
855
855
  | `TName` *extends* `InferConsumerNames`&lt;`TContract`&gt; |
856
856
 
857
857
  ***
@@ -862,13 +862,13 @@ Returns undefined if no headers schema is defined
862
862
  type WorkerInferSafeConsumerHandler<TContract, TName> = WorkerInferConsumerHandler<TContract, TName>;
863
863
  ```
864
864
 
865
- Defined in: [packages/worker/src/types.ts:187](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L187)
865
+ Defined in: [packages/worker/src/types.ts:207](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L207)
866
866
 
867
867
  #### Type Parameters
868
868
 
869
869
  | Type Parameter |
870
870
  | ------ |
871
- | `TContract` *extends* `ContractDefinition` |
871
+ | `TContract` *extends* `ContractDefinitionInput` |
872
872
  | `TName` *extends* `InferConsumerNames`&lt;`TContract`&gt; |
873
873
 
874
874
  #### Deprecated
@@ -883,13 +883,13 @@ Use `WorkerInferConsumerHandler` instead. Will be removed in next major version.
883
883
  type WorkerInferSafeConsumerHandlerEntry<TContract, TName> = WorkerInferConsumerHandlerEntry<TContract, TName>;
884
884
  ```
885
885
 
886
- Defined in: [packages/worker/src/types.ts:195](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L195)
886
+ Defined in: [packages/worker/src/types.ts:215](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L215)
887
887
 
888
888
  #### Type Parameters
889
889
 
890
890
  | Type Parameter |
891
891
  | ------ |
892
- | `TContract` *extends* `ContractDefinition` |
892
+ | `TContract` *extends* `ContractDefinitionInput` |
893
893
  | `TName` *extends* `InferConsumerNames`&lt;`TContract`&gt; |
894
894
 
895
895
  #### Deprecated
@@ -904,13 +904,13 @@ Use `WorkerInferConsumerHandlerEntry` instead. Will be removed in next major ver
904
904
  type WorkerInferSafeConsumerHandlers<TContract> = WorkerInferConsumerHandlers<TContract>;
905
905
  ```
906
906
 
907
- Defined in: [packages/worker/src/types.ts:203](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/types.ts#L203)
907
+ Defined in: [packages/worker/src/types.ts:223](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/types.ts#L223)
908
908
 
909
909
  #### Type Parameters
910
910
 
911
911
  | Type Parameter |
912
912
  | ------ |
913
- | `TContract` *extends* `ContractDefinition` |
913
+ | `TContract` *extends* `ContractDefinitionInput` |
914
914
 
915
915
  #### Deprecated
916
916
 
@@ -929,7 +929,7 @@ function defineHandler<TContract, TName>(
929
929
  handler): WorkerInferConsumerHandlerEntry<TContract, TName>;
930
930
  ```
931
931
 
932
- Defined in: [packages/worker/src/handlers.ts:103](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/handlers.ts#L103)
932
+ Defined in: [packages/worker/src/handlers.ts:103](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/handlers.ts#L103)
933
933
 
934
934
  Define a type-safe handler for a specific consumer in a contract.
935
935
 
@@ -944,7 +944,7 @@ Supports two patterns:
944
944
 
945
945
  | Type Parameter | Description |
946
946
  | ------ | ------ |
947
- | `TContract` *extends* `ContractDefinition` | The contract definition type |
947
+ | `TContract` *extends* `ContractDefinitionInput` | The contract definition type |
948
948
  | `TName` *extends* `string` \| `number` \| `symbol` | The consumer name from the contract |
949
949
 
950
950
  ##### Parameters
@@ -1002,7 +1002,7 @@ function defineHandler<TContract, TName>(
1002
1002
  options): WorkerInferConsumerHandlerEntry<TContract, TName>;
1003
1003
  ```
1004
1004
 
1005
- Defined in: [packages/worker/src/handlers.ts:111](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/handlers.ts#L111)
1005
+ Defined in: [packages/worker/src/handlers.ts:111](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/handlers.ts#L111)
1006
1006
 
1007
1007
  Define a type-safe handler for a specific consumer in a contract.
1008
1008
 
@@ -1017,7 +1017,7 @@ Supports two patterns:
1017
1017
 
1018
1018
  | Type Parameter | Description |
1019
1019
  | ------ | ------ |
1020
- | `TContract` *extends* `ContractDefinition` | The contract definition type |
1020
+ | `TContract` *extends* `ContractDefinitionInput` | The contract definition type |
1021
1021
  | `TName` *extends* `string` \| `number` \| `symbol` | The consumer name from the contract |
1022
1022
 
1023
1023
  ##### Parameters
@@ -1075,7 +1075,7 @@ const validateOrderHandler = defineHandler(
1075
1075
  function defineHandlers<TContract>(contract, handlers): WorkerInferConsumerHandlers<TContract>;
1076
1076
  ```
1077
1077
 
1078
- Defined in: [packages/worker/src/handlers.ts:166](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/handlers.ts#L166)
1078
+ Defined in: [packages/worker/src/handlers.ts:166](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/handlers.ts#L166)
1079
1079
 
1080
1080
  Define multiple type-safe handlers for consumers in a contract.
1081
1081
 
@@ -1086,7 +1086,7 @@ providing explicit error handling and better control over retry behavior.
1086
1086
 
1087
1087
  | Type Parameter | Description |
1088
1088
  | ------ | ------ |
1089
- | `TContract` *extends* `ContractDefinition` | The contract definition type |
1089
+ | `TContract` *extends* `ContractDefinitionInput` | The contract definition type |
1090
1090
 
1091
1091
  #### Parameters
1092
1092
 
@@ -1128,7 +1128,7 @@ const handlers = defineHandlers(orderContract, {
1128
1128
  function isHandlerError(error): error is HandlerError;
1129
1129
  ```
1130
1130
 
1131
- Defined in: [packages/worker/src/errors.ts:149](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L149)
1131
+ Defined in: [packages/worker/src/errors.ts:149](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L149)
1132
1132
 
1133
1133
  Type guard to check if an error is any HandlerError (RetryableError or NonRetryableError).
1134
1134
 
@@ -1165,7 +1165,7 @@ function handleError(error: unknown) {
1165
1165
  function isNonRetryableError(error): error is NonRetryableError;
1166
1166
  ```
1167
1167
 
1168
- Defined in: [packages/worker/src/errors.ts:127](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L127)
1168
+ Defined in: [packages/worker/src/errors.ts:127](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L127)
1169
1169
 
1170
1170
  Type guard to check if an error is a NonRetryableError.
1171
1171
 
@@ -1205,7 +1205,7 @@ try {
1205
1205
  function isRetryableError(error): error is RetryableError;
1206
1206
  ```
1207
1207
 
1208
- Defined in: [packages/worker/src/errors.ts:102](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L102)
1208
+ Defined in: [packages/worker/src/errors.ts:102](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L102)
1209
1209
 
1210
1210
  Type guard to check if an error is a RetryableError.
1211
1211
 
@@ -1247,7 +1247,7 @@ try {
1247
1247
  function nonRetryable(message, cause?): NonRetryableError;
1248
1248
  ```
1249
1249
 
1250
- Defined in: [packages/worker/src/errors.ts:211](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L211)
1250
+ Defined in: [packages/worker/src/errors.ts:211](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L211)
1251
1251
 
1252
1252
  Create a NonRetryableError with less verbosity.
1253
1253
 
@@ -1292,7 +1292,7 @@ const handler = ({ payload }) => {
1292
1292
  function retryable(message, cause?): RetryableError;
1293
1293
  ```
1294
1294
 
1295
- Defined in: [packages/worker/src/errors.ts:181](https://github.com/btravers/amqp-contract/blob/69a6467d137997be809af2ea5c4332c378579b49/packages/worker/src/errors.ts#L181)
1295
+ Defined in: [packages/worker/src/errors.ts:181](https://github.com/btravers/amqp-contract/blob/d132d062ebeaa9cc84db5471805355a29e3a50dc/packages/worker/src/errors.ts#L181)
1296
1296
 
1297
1297
  Create a RetryableError with less verbosity.
1298
1298
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/worker",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Worker utilities for consuming messages using amqp-contract",
5
5
  "keywords": [
6
6
  "amqp",
@@ -52,8 +52,8 @@
52
52
  "dependencies": {
53
53
  "@standard-schema/spec": "1.1.0",
54
54
  "@swan-io/boxed": "3.2.1",
55
- "@amqp-contract/contract": "0.13.0",
56
- "@amqp-contract/core": "0.13.0"
55
+ "@amqp-contract/contract": "0.14.0",
56
+ "@amqp-contract/core": "0.14.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/amqplib": "0.10.8",
@@ -67,7 +67,7 @@
67
67
  "typescript": "5.9.3",
68
68
  "vitest": "4.0.17",
69
69
  "zod": "4.3.5",
70
- "@amqp-contract/testing": "0.13.0",
70
+ "@amqp-contract/testing": "0.14.0",
71
71
  "@amqp-contract/tsconfig": "0.1.0",
72
72
  "@amqp-contract/typedoc": "0.1.0"
73
73
  },