@amqp-contract/worker 0.0.6 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @amqp-contract/worker
2
2
 
3
- Type-safe AMQP worker for consuming messages using amqp-contract.
3
+ Type-safe AMQP worker for consuming messages using amqp-contract with standard async/await error handling.
4
4
 
5
5
  📖 **[Full documentation →](https://btravers.github.io/amqp-contract/api/worker)**
6
6
 
@@ -22,7 +22,12 @@ const worker = await TypedAmqpWorker.create({
22
22
  handlers: {
23
23
  processOrder: async (message) => {
24
24
  console.log('Processing order:', message.orderId);
25
+
25
26
  // Your business logic here
27
+ await processPayment(message);
28
+ await updateInventory(message);
29
+
30
+ // If an exception is thrown, the message is automatically requeued
26
31
  },
27
32
  },
28
33
  connection: 'amqp://localhost',
@@ -34,6 +39,35 @@ const worker = await TypedAmqpWorker.create({
34
39
  // await worker.close();
35
40
  ```
36
41
 
42
+ ## Error Handling
43
+
44
+ Worker handlers use standard Promise-based async/await pattern:
45
+
46
+ ```typescript
47
+ handlers: {
48
+ processOrder: async (message) => {
49
+ // Standard async/await - no Result wrapping needed
50
+ try {
51
+ await process(message);
52
+ // Message acknowledged automatically on success
53
+ } catch (error) {
54
+ // Exception automatically caught by worker
55
+ // Message is requeued for retry
56
+ throw error;
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ **Error Types:**
63
+
64
+ Worker defines error classes for internal use:
65
+
66
+ - `TechnicalError` - Runtime failures (parsing, processing)
67
+ - `MessageValidationError` - Message fails schema validation
68
+
69
+ These errors are logged but **handlers don't need to use them** - just throw standard exceptions.
70
+
37
71
  ## API
38
72
 
39
73
  ### `TypedAmqpWorker.create(options)`
@@ -43,13 +77,55 @@ Create a type-safe AMQP worker from a contract with message handlers. Automatica
43
77
  **Parameters:**
44
78
 
45
79
  - `options.contract` - Contract definition
46
- - `options.handlers` - Object with handler functions for each consumer
80
+ - `options.handlers` - Object with async handler functions for each consumer
47
81
  - `options.connection` - AMQP connection URL (string) or connection options (Options.Connect)
48
82
 
83
+ **Returns:** `Promise<TypedAmqpWorker>`
84
+
85
+ **Example:**
86
+
87
+ ```typescript
88
+ const worker = await TypedAmqpWorker.create({
89
+ contract,
90
+ handlers: {
91
+ // Each handler receives type-checked message
92
+ processOrder: async (message) => {
93
+ // message.orderId is type-checked
94
+ console.log(message.orderId);
95
+ },
96
+ processPayment: async (message) => {
97
+ // Different message type for this consumer
98
+ await handlePayment(message);
99
+ },
100
+ },
101
+ connection: {
102
+ hostname: 'localhost',
103
+ port: 5672,
104
+ username: 'guest',
105
+ password: 'guest',
106
+ },
107
+ });
108
+ ```
109
+
110
+ ### Handler Signature
111
+
112
+ ```typescript
113
+ type Handler<T> = (message: T) => Promise<void>
114
+ ```
115
+
116
+ Handlers are simple async functions that:
117
+
118
+ - Receive type-checked message as parameter
119
+ - Return `Promise<void>`
120
+ - Can throw exceptions (message will be requeued)
121
+ - Message is acknowledged automatically on success
122
+
49
123
  ### `TypedAmqpWorker.close()`
50
124
 
51
125
  Stop consuming and close the channel and connection.
52
126
 
127
+ **Returns:** `Promise<void>`
128
+
53
129
  ## License
54
130
 
55
131
  MIT
package/dist/index.cjs CHANGED
@@ -1,5 +1,42 @@
1
1
  let amqplib = require("amqplib");
2
+ let _swan_io_boxed = require("@swan-io/boxed");
2
3
 
4
+ //#region src/errors.ts
5
+ /**
6
+ * Base error class for worker errors
7
+ */
8
+ var WorkerError = class extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "WorkerError";
12
+ const ErrorConstructor = Error;
13
+ if (typeof ErrorConstructor.captureStackTrace === "function") ErrorConstructor.captureStackTrace(this, this.constructor);
14
+ }
15
+ };
16
+ /**
17
+ * Error for technical/runtime failures in worker operations
18
+ * This includes validation failures, parsing failures, and processing failures
19
+ */
20
+ var TechnicalError = class extends WorkerError {
21
+ constructor(message, cause) {
22
+ super(message);
23
+ this.cause = cause;
24
+ this.name = "TechnicalError";
25
+ }
26
+ };
27
+ /**
28
+ * Error thrown when message validation fails
29
+ */
30
+ var MessageValidationError = class extends WorkerError {
31
+ constructor(consumerName, issues) {
32
+ super(`Message validation failed for consumer "${consumerName}"`);
33
+ this.consumerName = consumerName;
34
+ this.issues = issues;
35
+ this.name = "MessageValidationError";
36
+ }
37
+ };
38
+
39
+ //#endregion
3
40
  //#region src/worker.ts
4
41
  /**
5
42
  * Type-safe AMQP worker for consuming messages
@@ -73,25 +110,38 @@ var TypedAmqpWorker = class TypedAmqpWorker {
73
110
  const consumers = this.contract.consumers;
74
111
  if (!consumers) throw new Error("No consumers defined in contract");
75
112
  const consumer = consumers[consumerName];
76
- if (!consumer || typeof consumer !== "object") throw new Error(`Consumer "${String(consumerName)}" not found in contract`);
113
+ if (!consumer || typeof consumer !== "object") {
114
+ const availableConsumers = Object.keys(consumers);
115
+ const available = availableConsumers.length > 0 ? availableConsumers.join(", ") : "none";
116
+ throw new Error(`Consumer not found: "${String(consumerName)}". Available consumers: ${available}`);
117
+ }
77
118
  const consumerDef = consumer;
78
119
  const handler = this.handlers[consumerName];
79
120
  if (!handler) throw new Error(`Handler for "${String(consumerName)}" not provided`);
80
121
  if (consumerDef.prefetch !== void 0) await this.channel.prefetch(consumerDef.prefetch);
81
122
  const result = await this.channel.consume(consumerDef.queue, async (msg) => {
82
123
  if (!msg) return;
124
+ const parseResult = _swan_io_boxed.Result.fromExecution(() => JSON.parse(msg.content.toString()));
125
+ if (parseResult.isError()) {
126
+ console.error(new TechnicalError(`Error parsing message for consumer "${String(consumerName)}"`, parseResult.error));
127
+ this.channel?.nack(msg, false, false);
128
+ return;
129
+ }
130
+ const content = parseResult.value;
131
+ const rawValidation = consumerDef.message["~standard"].validate(content);
132
+ const resolvedValidation = rawValidation instanceof Promise ? await rawValidation : rawValidation;
133
+ const validationResult = typeof resolvedValidation === "object" && resolvedValidation !== null && "issues" in resolvedValidation && resolvedValidation.issues ? _swan_io_boxed.Result.Error(new MessageValidationError(String(consumerName), resolvedValidation.issues)) : _swan_io_boxed.Result.Ok(typeof resolvedValidation === "object" && resolvedValidation !== null && "value" in resolvedValidation ? resolvedValidation.value : content);
134
+ if (validationResult.isError()) {
135
+ console.error(validationResult.error);
136
+ this.channel?.nack(msg, false, false);
137
+ return;
138
+ }
139
+ const validatedMessage = validationResult.value;
83
140
  try {
84
- const content = JSON.parse(msg.content.toString());
85
- const validation = consumerDef.message["~standard"].validate(content);
86
- if (typeof validation === "object" && validation !== null && "issues" in validation && validation.issues) {
87
- console.error("Message validation failed:", validation.issues);
88
- this.channel?.nack(msg, false, false);
89
- return;
90
- }
91
- await handler(typeof validation === "object" && validation !== null && "value" in validation ? validation.value : content);
141
+ await handler(validatedMessage);
92
142
  if (!consumerDef.noAck) this.channel?.ack(msg);
93
143
  } catch (error) {
94
- console.error("Error processing message:", error);
144
+ console.error(new TechnicalError(`Error processing message for consumer "${String(consumerName)}"`, error));
95
145
  this.channel?.nack(msg, false, true);
96
146
  }
97
147
  }, { noAck: consumerDef.noAck ?? false });
@@ -108,4 +158,6 @@ var TypedAmqpWorker = class TypedAmqpWorker {
108
158
  };
109
159
 
110
160
  //#endregion
161
+ exports.MessageValidationError = MessageValidationError;
162
+ exports.TechnicalError = TechnicalError;
111
163
  exports.TypedAmqpWorker = TypedAmqpWorker;
package/dist/index.d.cts CHANGED
@@ -49,5 +49,29 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
49
49
  private stopConsuming;
50
50
  }
51
51
  //#endregion
52
- export { type CreateWorkerOptions, TypedAmqpWorker };
52
+ //#region src/errors.d.ts
53
+ /**
54
+ * Base error class for worker errors
55
+ */
56
+ declare abstract class WorkerError extends Error {
57
+ protected constructor(message: string);
58
+ }
59
+ /**
60
+ * Error for technical/runtime failures in worker operations
61
+ * This includes validation failures, parsing failures, and processing failures
62
+ */
63
+ declare class TechnicalError extends WorkerError {
64
+ readonly cause?: unknown | undefined;
65
+ constructor(message: string, cause?: unknown | undefined);
66
+ }
67
+ /**
68
+ * Error thrown when message validation fails
69
+ */
70
+ declare class MessageValidationError extends WorkerError {
71
+ readonly consumerName: string;
72
+ readonly issues: unknown;
73
+ constructor(consumerName: string, issues: unknown);
74
+ }
75
+ //#endregion
76
+ export { type CreateWorkerOptions, MessageValidationError, TechnicalError, TypedAmqpWorker };
53
77
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/worker.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAAuD,UAAtC,mBAAsC,CAAA,kBAAA,kBAAA,CAAA,CAAA;EAC3C,QAAA,EAAA,SAAA;EAC4B,QAAA,EAA5B,2BAA4B,CAAA,SAAA,CAAA;EAA5B,UAAA,EAAA,MAAA,GACW,OAAA,CAAQ,OADnB;;;AAOZ;;AAewC,cAf3B,eAe2B,CAAA,kBAfO,kBAeP,CAAA,CAAA;EACP,iBAAA,QAAA;EAApB,iBAAA,QAAA;EACgB,iBAAA,iBAAA;EAAhB,QAAA,OAAA;EAAR,QAAA,UAAA;EAUY,QAAA,YAAA;EAAO,QAAA,WAAA,CAAA;;;;;kCAZgB,6BAC3B,oBAAoB,aAC5B,QAAQ,gBAAgB;;;;WAUZ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/worker.ts","../src/errors.ts"],"sourcesContent":[],"mappings":";;;;;;;AAcA;AAAuD,UAAtC,mBAAsC,CAAA,kBAAA,kBAAA,CAAA,CAAA;EAC3C,QAAA,EAAA,SAAA;EAC4B,QAAA,EAA5B,2BAA4B,CAAA,SAAA,CAAA;EAA5B,UAAA,EAAA,MAAA,GACW,OAAA,CAAQ,OADnB;;;AAOZ;;AAewC,cAf3B,eAe2B,CAAA,kBAfO,kBAeP,CAAA,CAAA;EACP,iBAAA,QAAA;EAApB,iBAAA,QAAA;EACgB,iBAAA,iBAAA;EAAhB,QAAA,OAAA;EAAR,QAAA,UAAA;EAUY,QAAA,YAAA;EAAO,QAAA,WAAA,CAAA;;;;;EC7BX,OAAA,MAAA,CAAA,kBDiB2B,kBCjBO,CAAA,CAAA,OAAA,EDkBlC,mBClBkC,CDkBd,SClBc,CAAA,CAAA,EDmB1C,OCnB0C,CDmBlC,eCnBkC,CDmBlB,SCnBkB,CAAA,CAAA;EAalC;;;WDgBI;;;;;;;;;;;;;;;;;;;;;;;uBC/CF,WAAA,SAAoB,KAAA;EDWlB,UAAA,WAAA,CAAmB,OAAA,EAAA,MAAA;;;;;;AAGE,cCIzB,cAAA,SAAuB,WAAA,CDJE;EAMzB,SAAA,KAAA,CAAA,EAAA,OAAe,GAAA,SAAA;EAAmB,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAA,OAAA,GAAA,SAAA;;;;;AAiBlC,cCNA,sBAAA,SAA+B,WAAA,CDM/B;EAAR,SAAA,YAAA,EAAA,MAAA;EAUY,SAAA,MAAA,EAAA,OAAA;EAAO,WAAA,CAAA,YAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA"}
package/dist/index.d.mts CHANGED
@@ -49,5 +49,29 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
49
49
  private stopConsuming;
50
50
  }
51
51
  //#endregion
52
- export { type CreateWorkerOptions, TypedAmqpWorker };
52
+ //#region src/errors.d.ts
53
+ /**
54
+ * Base error class for worker errors
55
+ */
56
+ declare abstract class WorkerError extends Error {
57
+ protected constructor(message: string);
58
+ }
59
+ /**
60
+ * Error for technical/runtime failures in worker operations
61
+ * This includes validation failures, parsing failures, and processing failures
62
+ */
63
+ declare class TechnicalError extends WorkerError {
64
+ readonly cause?: unknown | undefined;
65
+ constructor(message: string, cause?: unknown | undefined);
66
+ }
67
+ /**
68
+ * Error thrown when message validation fails
69
+ */
70
+ declare class MessageValidationError extends WorkerError {
71
+ readonly consumerName: string;
72
+ readonly issues: unknown;
73
+ constructor(consumerName: string, issues: unknown);
74
+ }
75
+ //#endregion
76
+ export { type CreateWorkerOptions, MessageValidationError, TechnicalError, TypedAmqpWorker };
53
77
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/worker.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAAuD,UAAtC,mBAAsC,CAAA,kBAAA,kBAAA,CAAA,CAAA;EAC3C,QAAA,EAAA,SAAA;EAC4B,QAAA,EAA5B,2BAA4B,CAAA,SAAA,CAAA;EAA5B,UAAA,EAAA,MAAA,GACW,OAAA,CAAQ,OADnB;;;AAOZ;;AAewC,cAf3B,eAe2B,CAAA,kBAfO,kBAeP,CAAA,CAAA;EACP,iBAAA,QAAA;EAApB,iBAAA,QAAA;EACgB,iBAAA,iBAAA;EAAhB,QAAA,OAAA;EAAR,QAAA,UAAA;EAUY,QAAA,YAAA;EAAO,QAAA,WAAA,CAAA;;;;;kCAZgB,6BAC3B,oBAAoB,aAC5B,QAAQ,gBAAgB;;;;WAUZ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/worker.ts","../src/errors.ts"],"sourcesContent":[],"mappings":";;;;;;;AAcA;AAAuD,UAAtC,mBAAsC,CAAA,kBAAA,kBAAA,CAAA,CAAA;EAC3C,QAAA,EAAA,SAAA;EAC4B,QAAA,EAA5B,2BAA4B,CAAA,SAAA,CAAA;EAA5B,UAAA,EAAA,MAAA,GACW,OAAA,CAAQ,OADnB;;;AAOZ;;AAewC,cAf3B,eAe2B,CAAA,kBAfO,kBAeP,CAAA,CAAA;EACP,iBAAA,QAAA;EAApB,iBAAA,QAAA;EACgB,iBAAA,iBAAA;EAAhB,QAAA,OAAA;EAAR,QAAA,UAAA;EAUY,QAAA,YAAA;EAAO,QAAA,WAAA,CAAA;;;;;EC7BX,OAAA,MAAA,CAAA,kBDiB2B,kBCjBO,CAAA,CAAA,OAAA,EDkBlC,mBClBkC,CDkBd,SClBc,CAAA,CAAA,EDmB1C,OCnB0C,CDmBlC,eCnBkC,CDmBlB,SCnBkB,CAAA,CAAA;EAalC;;;WDgBI;;;;;;;;;;;;;;;;;;;;;;;uBC/CF,WAAA,SAAoB,KAAA;EDWlB,UAAA,WAAA,CAAmB,OAAA,EAAA,MAAA;;;;;;AAGE,cCIzB,cAAA,SAAuB,WAAA,CDJE;EAMzB,SAAA,KAAA,CAAA,EAAA,OAAe,GAAA,SAAA;EAAmB,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAA,OAAA,GAAA,SAAA;;;;;AAiBlC,cCNA,sBAAA,SAA+B,WAAA,CDM/B;EAAR,SAAA,YAAA,EAAA,MAAA;EAUY,SAAA,MAAA,EAAA,OAAA;EAAO,WAAA,CAAA,YAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,42 @@
1
1
  import { connect } from "amqplib";
2
+ import { Result } from "@swan-io/boxed";
2
3
 
4
+ //#region src/errors.ts
5
+ /**
6
+ * Base error class for worker errors
7
+ */
8
+ var WorkerError = class extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "WorkerError";
12
+ const ErrorConstructor = Error;
13
+ if (typeof ErrorConstructor.captureStackTrace === "function") ErrorConstructor.captureStackTrace(this, this.constructor);
14
+ }
15
+ };
16
+ /**
17
+ * Error for technical/runtime failures in worker operations
18
+ * This includes validation failures, parsing failures, and processing failures
19
+ */
20
+ var TechnicalError = class extends WorkerError {
21
+ constructor(message, cause) {
22
+ super(message);
23
+ this.cause = cause;
24
+ this.name = "TechnicalError";
25
+ }
26
+ };
27
+ /**
28
+ * Error thrown when message validation fails
29
+ */
30
+ var MessageValidationError = class extends WorkerError {
31
+ constructor(consumerName, issues) {
32
+ super(`Message validation failed for consumer "${consumerName}"`);
33
+ this.consumerName = consumerName;
34
+ this.issues = issues;
35
+ this.name = "MessageValidationError";
36
+ }
37
+ };
38
+
39
+ //#endregion
3
40
  //#region src/worker.ts
4
41
  /**
5
42
  * Type-safe AMQP worker for consuming messages
@@ -73,25 +110,38 @@ var TypedAmqpWorker = class TypedAmqpWorker {
73
110
  const consumers = this.contract.consumers;
74
111
  if (!consumers) throw new Error("No consumers defined in contract");
75
112
  const consumer = consumers[consumerName];
76
- if (!consumer || typeof consumer !== "object") throw new Error(`Consumer "${String(consumerName)}" not found in contract`);
113
+ if (!consumer || typeof consumer !== "object") {
114
+ const availableConsumers = Object.keys(consumers);
115
+ const available = availableConsumers.length > 0 ? availableConsumers.join(", ") : "none";
116
+ throw new Error(`Consumer not found: "${String(consumerName)}". Available consumers: ${available}`);
117
+ }
77
118
  const consumerDef = consumer;
78
119
  const handler = this.handlers[consumerName];
79
120
  if (!handler) throw new Error(`Handler for "${String(consumerName)}" not provided`);
80
121
  if (consumerDef.prefetch !== void 0) await this.channel.prefetch(consumerDef.prefetch);
81
122
  const result = await this.channel.consume(consumerDef.queue, async (msg) => {
82
123
  if (!msg) return;
124
+ const parseResult = Result.fromExecution(() => JSON.parse(msg.content.toString()));
125
+ if (parseResult.isError()) {
126
+ console.error(new TechnicalError(`Error parsing message for consumer "${String(consumerName)}"`, parseResult.error));
127
+ this.channel?.nack(msg, false, false);
128
+ return;
129
+ }
130
+ const content = parseResult.value;
131
+ const rawValidation = consumerDef.message["~standard"].validate(content);
132
+ const resolvedValidation = rawValidation instanceof Promise ? await rawValidation : rawValidation;
133
+ const validationResult = typeof resolvedValidation === "object" && resolvedValidation !== null && "issues" in resolvedValidation && resolvedValidation.issues ? Result.Error(new MessageValidationError(String(consumerName), resolvedValidation.issues)) : Result.Ok(typeof resolvedValidation === "object" && resolvedValidation !== null && "value" in resolvedValidation ? resolvedValidation.value : content);
134
+ if (validationResult.isError()) {
135
+ console.error(validationResult.error);
136
+ this.channel?.nack(msg, false, false);
137
+ return;
138
+ }
139
+ const validatedMessage = validationResult.value;
83
140
  try {
84
- const content = JSON.parse(msg.content.toString());
85
- const validation = consumerDef.message["~standard"].validate(content);
86
- if (typeof validation === "object" && validation !== null && "issues" in validation && validation.issues) {
87
- console.error("Message validation failed:", validation.issues);
88
- this.channel?.nack(msg, false, false);
89
- return;
90
- }
91
- await handler(typeof validation === "object" && validation !== null && "value" in validation ? validation.value : content);
141
+ await handler(validatedMessage);
92
142
  if (!consumerDef.noAck) this.channel?.ack(msg);
93
143
  } catch (error) {
94
- console.error("Error processing message:", error);
144
+ console.error(new TechnicalError(`Error processing message for consumer "${String(consumerName)}"`, error));
95
145
  this.channel?.nack(msg, false, true);
96
146
  }
97
147
  }, { noAck: consumerDef.noAck ?? false });
@@ -108,5 +158,5 @@ var TypedAmqpWorker = class TypedAmqpWorker {
108
158
  };
109
159
 
110
160
  //#endregion
111
- export { TypedAmqpWorker };
161
+ export { MessageValidationError, TechnicalError, TypedAmqpWorker };
112
162
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["contract: TContract","handlers: WorkerInferConsumerHandlers<TContract>","connectionOptions: string | Options.Connect"],"sources":["../src/worker.ts"],"sourcesContent":["import { connect } from \"amqplib\";\nimport type { Channel, ChannelModel, ConsumeMessage, Options } from \"amqplib\";\nimport type {\n ContractDefinition,\n InferConsumerNames,\n WorkerInferConsumerHandlers,\n} from \"@amqp-contract/contract\";\n\n/**\n * Options for creating a worker\n */\nexport interface CreateWorkerOptions<TContract extends ContractDefinition> {\n contract: TContract;\n handlers: WorkerInferConsumerHandlers<TContract>;\n connection: string | Options.Connect;\n}\n\n/**\n * Type-safe AMQP worker for consuming messages\n */\nexport class TypedAmqpWorker<TContract extends ContractDefinition> {\n private channel: Channel | null = null;\n private connection: ChannelModel | null = null;\n private consumerTags: string[] = [];\n\n private constructor(\n private readonly contract: TContract,\n private readonly handlers: WorkerInferConsumerHandlers<TContract>,\n private readonly connectionOptions: string | Options.Connect,\n ) {}\n\n /**\n * Create a type-safe AMQP worker from a contract\n * The worker will automatically connect and start consuming all messages\n */\n static async create<TContract extends ContractDefinition>(\n options: CreateWorkerOptions<TContract>,\n ): Promise<TypedAmqpWorker<TContract>> {\n const worker = new TypedAmqpWorker(options.contract, options.handlers, options.connection);\n await worker.init();\n await worker.consumeAll();\n return worker;\n }\n\n /**\n * Close the connection\n */\n async close(): Promise<void> {\n await this.stopConsuming();\n\n if (this.channel) {\n await this.channel.close();\n this.channel = null;\n }\n\n if (this.connection) {\n await this.connection.close();\n this.connection = null;\n }\n }\n\n /**\n * Connect to AMQP broker\n */\n private async init(): Promise<void> {\n this.connection = await connect(this.connectionOptions);\n this.channel = await this.connection.createChannel();\n\n // Setup exchanges\n if (this.contract.exchanges) {\n for (const exchange of Object.values(this.contract.exchanges)) {\n await this.channel.assertExchange(exchange.name, exchange.type, {\n durable: exchange.durable,\n autoDelete: exchange.autoDelete,\n internal: exchange.internal,\n arguments: exchange.arguments,\n });\n }\n }\n\n // Setup queues\n if (this.contract.queues) {\n for (const queue of Object.values(this.contract.queues)) {\n await this.channel.assertQueue(queue.name, {\n durable: queue.durable,\n exclusive: queue.exclusive,\n autoDelete: queue.autoDelete,\n arguments: queue.arguments,\n });\n }\n }\n\n // Setup bindings\n if (this.contract.bindings) {\n for (const binding of Object.values(this.contract.bindings)) {\n await this.channel.bindQueue(\n binding.queue,\n binding.exchange,\n binding.routingKey ?? \"\",\n binding.arguments,\n );\n }\n }\n }\n\n /**\n * Start consuming messages for all consumers\n */\n private async consumeAll(): Promise<void> {\n if (!this.contract.consumers) {\n throw new Error(\"No consumers defined in contract\");\n }\n\n const consumerNames = Object.keys(this.contract.consumers) as InferConsumerNames<TContract>[];\n\n for (const consumerName of consumerNames) {\n await this.consume(consumerName);\n }\n }\n\n /**\n * Start consuming messages for a specific consumer\n */\n private async consume<TName extends InferConsumerNames<TContract>>(\n consumerName: TName,\n ): Promise<void> {\n if (!this.channel) {\n throw new Error(\n \"Worker not initialized. Use TypedAmqpWorker.create() to obtain an initialized worker instance.\",\n );\n }\n\n const consumers = this.contract.consumers as Record<string, unknown>;\n if (!consumers) {\n throw new Error(\"No consumers defined in contract\");\n }\n\n const consumer = consumers[consumerName as string];\n if (!consumer || typeof consumer !== \"object\") {\n throw new Error(`Consumer \"${String(consumerName)}\" not found in contract`);\n }\n\n const consumerDef = consumer as {\n queue: string;\n message: { \"~standard\": { validate: (value: unknown) => unknown } };\n prefetch?: number;\n noAck?: boolean;\n };\n\n const handler = this.handlers[consumerName];\n if (!handler) {\n throw new Error(`Handler for \"${String(consumerName)}\" not provided`);\n }\n\n // Set prefetch if specified\n if (consumerDef.prefetch !== undefined) {\n await this.channel.prefetch(consumerDef.prefetch);\n }\n\n // Start consuming\n const result = await this.channel.consume(\n consumerDef.queue,\n async (msg: ConsumeMessage | null) => {\n if (!msg) {\n return;\n }\n\n try {\n // Parse message\n const content = JSON.parse(msg.content.toString());\n\n // Validate message using schema\n const validation = consumerDef.message[\"~standard\"].validate(content);\n if (\n typeof validation === \"object\" &&\n validation !== null &&\n \"issues\" in validation &&\n validation.issues\n ) {\n console.error(\"Message validation failed:\", validation.issues);\n // Reject message with no requeue\n this.channel?.nack(msg, false, false);\n return;\n }\n\n const validatedMessage =\n typeof validation === \"object\" && validation !== null && \"value\" in validation\n ? validation.value\n : content;\n\n // Call handler\n await handler(validatedMessage);\n\n // Acknowledge message if not in noAck mode\n if (!consumerDef.noAck) {\n this.channel?.ack(msg);\n }\n } catch (error) {\n console.error(\"Error processing message:\", error);\n // Reject message and requeue\n this.channel?.nack(msg, false, true);\n }\n },\n {\n noAck: consumerDef.noAck ?? false,\n },\n );\n\n this.consumerTags.push(result.consumerTag);\n }\n\n /**\n * Stop consuming messages\n */\n private async stopConsuming(): Promise<void> {\n if (!this.channel) {\n return;\n }\n\n for (const tag of this.consumerTags) {\n await this.channel.cancel(tag);\n }\n\n this.consumerTags = [];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["cause?: unknown","consumerName: string","issues: unknown","contract: TContract","handlers: WorkerInferConsumerHandlers<TContract>","connectionOptions: string | Options.Connect","validationResult: Result<unknown, MessageValidationError>"],"sources":["../src/errors.ts","../src/worker.ts"],"sourcesContent":["/**\n * Base error class for worker errors\n */\nabstract class WorkerError extends Error {\n protected constructor(message: string) {\n super(message);\n this.name = \"WorkerError\";\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 * Error for technical/runtime failures in worker operations\n * This includes validation failures, parsing failures, and processing failures\n */\nexport class TechnicalError extends WorkerError {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"TechnicalError\";\n }\n}\n\n/**\n * Error thrown when message validation fails\n */\nexport class MessageValidationError extends WorkerError {\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 }\n}\n","import { connect } from \"amqplib\";\nimport type { Channel, ChannelModel, ConsumeMessage, Options } from \"amqplib\";\nimport type {\n ContractDefinition,\n InferConsumerNames,\n WorkerInferConsumerHandlers,\n WorkerInferConsumerInput,\n} from \"@amqp-contract/contract\";\nimport { Result } from \"@swan-io/boxed\";\nimport { MessageValidationError, TechnicalError } from \"./errors.js\";\n\n/**\n * Options for creating a worker\n */\nexport interface CreateWorkerOptions<TContract extends ContractDefinition> {\n contract: TContract;\n handlers: WorkerInferConsumerHandlers<TContract>;\n connection: string | Options.Connect;\n}\n\n/**\n * Type-safe AMQP worker for consuming messages\n */\nexport class TypedAmqpWorker<TContract extends ContractDefinition> {\n private channel: Channel | null = null;\n private connection: ChannelModel | null = null;\n private consumerTags: string[] = [];\n\n private constructor(\n private readonly contract: TContract,\n private readonly handlers: WorkerInferConsumerHandlers<TContract>,\n private readonly connectionOptions: string | Options.Connect,\n ) {}\n\n /**\n * Create a type-safe AMQP worker from a contract\n * The worker will automatically connect and start consuming all messages\n */\n static async create<TContract extends ContractDefinition>(\n options: CreateWorkerOptions<TContract>,\n ): Promise<TypedAmqpWorker<TContract>> {\n const worker = new TypedAmqpWorker(options.contract, options.handlers, options.connection);\n await worker.init();\n await worker.consumeAll();\n return worker;\n }\n\n /**\n * Close the connection\n */\n async close(): Promise<void> {\n await this.stopConsuming();\n\n if (this.channel) {\n await this.channel.close();\n this.channel = null;\n }\n\n if (this.connection) {\n await this.connection.close();\n this.connection = null;\n }\n }\n\n /**\n * Connect to AMQP broker\n */\n private async init(): Promise<void> {\n this.connection = await connect(this.connectionOptions);\n this.channel = await this.connection.createChannel();\n\n // Setup exchanges\n if (this.contract.exchanges) {\n for (const exchange of Object.values(this.contract.exchanges)) {\n await this.channel.assertExchange(exchange.name, exchange.type, {\n durable: exchange.durable,\n autoDelete: exchange.autoDelete,\n internal: exchange.internal,\n arguments: exchange.arguments,\n });\n }\n }\n\n // Setup queues\n if (this.contract.queues) {\n for (const queue of Object.values(this.contract.queues)) {\n await this.channel.assertQueue(queue.name, {\n durable: queue.durable,\n exclusive: queue.exclusive,\n autoDelete: queue.autoDelete,\n arguments: queue.arguments,\n });\n }\n }\n\n // Setup bindings\n if (this.contract.bindings) {\n for (const binding of Object.values(this.contract.bindings)) {\n await this.channel.bindQueue(\n binding.queue,\n binding.exchange,\n binding.routingKey ?? \"\",\n binding.arguments,\n );\n }\n }\n }\n\n /**\n * Start consuming messages for all consumers\n */\n private async consumeAll(): Promise<void> {\n if (!this.contract.consumers) {\n throw new Error(\"No consumers defined in contract\");\n }\n\n const consumerNames = Object.keys(this.contract.consumers) as InferConsumerNames<TContract>[];\n\n for (const consumerName of consumerNames) {\n await this.consume(consumerName);\n }\n }\n\n /**\n * Start consuming messages for a specific consumer\n */\n private async consume<TName extends InferConsumerNames<TContract>>(\n consumerName: TName,\n ): Promise<void> {\n if (!this.channel) {\n throw new Error(\n \"Worker not initialized. Use TypedAmqpWorker.create() to obtain an initialized worker instance.\",\n );\n }\n\n const consumers = this.contract.consumers as Record<string, unknown>;\n if (!consumers) {\n throw new Error(\"No consumers defined in contract\");\n }\n\n const consumer = consumers[consumerName as string];\n if (!consumer || typeof consumer !== \"object\") {\n const availableConsumers = Object.keys(consumers);\n const available = availableConsumers.length > 0 ? availableConsumers.join(\", \") : \"none\";\n throw new Error(\n `Consumer not found: \"${String(consumerName)}\". Available consumers: ${available}`,\n );\n }\n\n const consumerDef = consumer as {\n queue: string;\n message: { \"~standard\": { validate: (value: unknown) => unknown } };\n prefetch?: number;\n noAck?: boolean;\n };\n\n const handler = this.handlers[consumerName];\n if (!handler) {\n throw new Error(`Handler for \"${String(consumerName)}\" not provided`);\n }\n\n // Set prefetch if specified\n if (consumerDef.prefetch !== undefined) {\n await this.channel.prefetch(consumerDef.prefetch);\n }\n\n // Start consuming\n const result = await this.channel.consume(\n consumerDef.queue,\n async (msg: ConsumeMessage | null) => {\n if (!msg) {\n return;\n }\n\n // Parse message\n const parseResult = Result.fromExecution(() => JSON.parse(msg.content.toString()));\n\n if (parseResult.isError()) {\n console.error(\n new TechnicalError(\n `Error parsing message for consumer \"${String(consumerName)}\"`,\n parseResult.error,\n ),\n );\n // Reject message with no requeue (malformed JSON)\n this.channel?.nack(msg, false, false);\n return;\n }\n\n const content = parseResult.value;\n\n // Validate message using schema (supports sync and async validators)\n const rawValidation = consumerDef.message[\"~standard\"].validate(content);\n const resolvedValidation =\n rawValidation instanceof Promise ? await rawValidation : rawValidation;\n const validationResult: Result<unknown, MessageValidationError> =\n typeof resolvedValidation === \"object\" &&\n resolvedValidation !== null &&\n \"issues\" in resolvedValidation &&\n resolvedValidation.issues\n ? Result.Error(\n new MessageValidationError(String(consumerName), resolvedValidation.issues),\n )\n : Result.Ok(\n typeof resolvedValidation === \"object\" &&\n resolvedValidation !== null &&\n \"value\" in resolvedValidation\n ? resolvedValidation.value\n : content,\n );\n\n if (validationResult.isError()) {\n console.error(validationResult.error);\n // Reject message with no requeue (validation failed)\n this.channel?.nack(msg, false, false);\n return;\n }\n\n const validatedMessage = validationResult.value as WorkerInferConsumerInput<\n TContract,\n TName\n >;\n\n // Call handler and wait for Promise to resolve\n try {\n await handler(validatedMessage);\n\n // Acknowledge message if not in noAck mode\n if (!consumerDef.noAck) {\n this.channel?.ack(msg);\n }\n } catch (error) {\n console.error(\n new TechnicalError(\n `Error processing message for consumer \"${String(consumerName)}\"`,\n error,\n ),\n );\n // Reject message and requeue (handler failed)\n this.channel?.nack(msg, false, true);\n }\n },\n {\n noAck: consumerDef.noAck ?? false,\n },\n );\n\n this.consumerTags.push(result.consumerTag);\n }\n\n /**\n * Stop consuming messages\n */\n private async stopConsuming(): Promise<void> {\n if (!this.channel) {\n return;\n }\n\n for (const tag of this.consumerTags) {\n await this.channel.cancel(tag);\n }\n\n this.consumerTags = [];\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/worker",
3
- "version": "0.0.6",
3
+ "version": "0.1.1",
4
4
  "description": "Worker utilities for consuming messages using amqp-contract",
5
5
  "keywords": [
6
6
  "amqp",
@@ -41,19 +41,20 @@
41
41
  "dist"
42
42
  ],
43
43
  "dependencies": {
44
- "@amqp-contract/contract": "0.0.6"
44
+ "@swan-io/boxed": "3.2.1",
45
+ "@amqp-contract/contract": "0.1.1"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@types/amqplib": "0.10.8",
48
49
  "@types/node": "25.0.3",
49
50
  "@vitest/coverage-v8": "4.0.16",
50
51
  "amqplib": "0.10.9",
51
- "tsdown": "0.18.1",
52
+ "tsdown": "0.18.2",
52
53
  "typescript": "5.9.3",
53
54
  "vitest": "4.0.16",
54
55
  "zod": "4.2.1",
55
- "@amqp-contract/client": "0.0.6",
56
- "@amqp-contract/testing": "0.0.6",
56
+ "@amqp-contract/client": "0.1.1",
57
+ "@amqp-contract/testing": "0.1.1",
57
58
  "@amqp-contract/tsconfig": "0.0.0"
58
59
  },
59
60
  "peerDependencies": {