@amqp-contract/core 0.25.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/index.cjs +51 -45
- package/dist/index.d.cts +35 -20
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +35 -20
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +50 -44
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +136 -509
- package/package.json +16 -12
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Core utilities for AMQP setup and management in amqp-contract.**
|
|
4
4
|
|
|
5
|
-
[](https://github.com/btravstack/amqp-contract/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/@amqp-contract/core)
|
|
7
7
|
[](https://www.npmjs.com/package/@amqp-contract/core)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
This package provides centralized functionality for establishing AMQP topology (exchanges, queues, and bindings) from contract definitions, and defines the `Logger` interface used across amqp-contract packages.
|
|
12
12
|
|
|
13
|
-
📖 **[Full documentation →](https://
|
|
13
|
+
📖 **[Full documentation →](https://btravstack.github.io/amqp-contract)**
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
@@ -68,7 +68,7 @@ const amqpClient = new AmqpClient(contract, {
|
|
|
68
68
|
await amqpClient.close();
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
For advanced channel configuration options (custom setup, prefetch, publisher confirms), see the [Channel Configuration Guide](https://
|
|
71
|
+
For advanced channel configuration options (custom setup, prefetch, publisher confirms), see the [Channel Configuration Guide](https://btravstack.github.io/amqp-contract/guide/channel-configuration).
|
|
72
72
|
|
|
73
73
|
### Logger Interface
|
|
74
74
|
|
|
@@ -93,16 +93,16 @@ const client = (
|
|
|
93
93
|
urls: ["amqp://localhost"],
|
|
94
94
|
logger, // Optional: logs published messages
|
|
95
95
|
})
|
|
96
|
-
).
|
|
96
|
+
).unwrap();
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
## API
|
|
100
100
|
|
|
101
|
-
For complete API documentation, see the [@amqp-contract/core API Reference](https://
|
|
101
|
+
For complete API documentation, see the [@amqp-contract/core API Reference](https://btravstack.github.io/amqp-contract/api/core).
|
|
102
102
|
|
|
103
103
|
## Documentation
|
|
104
104
|
|
|
105
|
-
📖 **[Read the full documentation →](https://
|
|
105
|
+
📖 **[Read the full documentation →](https://btravstack.github.io/amqp-contract)**
|
|
106
106
|
|
|
107
107
|
## License
|
|
108
108
|
|
package/dist/index.cjs
CHANGED
|
@@ -21,7 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
-
let
|
|
24
|
+
let unthrown = require("unthrown");
|
|
25
25
|
let amqp_connection_manager = require("amqp-connection-manager");
|
|
26
26
|
amqp_connection_manager = __toESM(amqp_connection_manager, 1);
|
|
27
27
|
let _amqp_contract_contract = require("@amqp-contract/contract");
|
|
@@ -184,33 +184,40 @@ function _resetConnectionsForTesting() {
|
|
|
184
184
|
*
|
|
185
185
|
* This includes AMQP connection failures, channel issues, validation failures,
|
|
186
186
|
* and other runtime errors. This error is shared across core, worker, and client packages.
|
|
187
|
+
*
|
|
188
|
+
* Built on unthrown's {@link TaggedError}, so it carries a `_tag` of
|
|
189
|
+
* `"@amqp-contract/TechnicalError"` for exhaustive dispatch via `matchTags`. The
|
|
190
|
+
* tag is namespaced to avoid colliding with other libraries' tags in a shared
|
|
191
|
+
* `matchTags`; the human-facing `Error.name` is kept bare (`"TechnicalError"`).
|
|
192
|
+
* Remains a real `Error` (and a *modeled* error — it lives in the `E` channel of
|
|
193
|
+
* a `Result`, never the `Defect` channel).
|
|
187
194
|
*/
|
|
188
|
-
var TechnicalError = class extends
|
|
195
|
+
var TechnicalError = class extends (0, unthrown.TaggedError)("@amqp-contract/TechnicalError", { name: "TechnicalError" }) {
|
|
189
196
|
constructor(message, cause) {
|
|
190
|
-
super(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (typeof ErrorConstructor.captureStackTrace === "function") ErrorConstructor.captureStackTrace(this, this.constructor);
|
|
197
|
+
super({
|
|
198
|
+
message,
|
|
199
|
+
cause
|
|
200
|
+
});
|
|
195
201
|
}
|
|
196
202
|
};
|
|
197
203
|
/**
|
|
198
204
|
* Error thrown when message validation fails (payload or headers).
|
|
199
205
|
*
|
|
200
206
|
* Used by both the client (publish-time payload validation) and the worker
|
|
201
|
-
* (consume-time payload and headers validation).
|
|
207
|
+
* (consume-time payload and headers validation). Carries a `_tag` of
|
|
208
|
+
* `"@amqp-contract/MessageValidationError"` (namespaced to avoid collisions);
|
|
209
|
+
* the `Error.name` is kept bare (`"MessageValidationError"`).
|
|
202
210
|
*
|
|
203
211
|
* @param source - The name of the publisher or consumer that triggered the validation
|
|
204
212
|
* @param issues - The validation issues from the Standard Schema validation
|
|
205
213
|
*/
|
|
206
|
-
var MessageValidationError = class extends
|
|
214
|
+
var MessageValidationError = class extends (0, unthrown.TaggedError)("@amqp-contract/MessageValidationError", { name: "MessageValidationError" }) {
|
|
207
215
|
constructor(source, issues) {
|
|
208
|
-
super(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (typeof ErrorConstructor.captureStackTrace === "function") ErrorConstructor.captureStackTrace(this, this.constructor);
|
|
216
|
+
super({
|
|
217
|
+
message: `Message validation failed for "${source}"`,
|
|
218
|
+
source,
|
|
219
|
+
issues
|
|
220
|
+
});
|
|
214
221
|
}
|
|
215
222
|
};
|
|
216
223
|
//#endregion
|
|
@@ -238,10 +245,10 @@ var MessageValidationError = class extends Error {
|
|
|
238
245
|
async function setupAmqpTopology(channel, contract) {
|
|
239
246
|
const exchanges = Object.values(contract.exchanges ?? {}).filter((e) => e.name !== "");
|
|
240
247
|
const exchangeErrors = (await Promise.allSettled(exchanges.map((exchange) => channel.assertExchange(exchange.name, exchange.type, {
|
|
241
|
-
durable: exchange.durable,
|
|
242
|
-
autoDelete: exchange.autoDelete,
|
|
243
|
-
internal: exchange.internal,
|
|
244
|
-
arguments: exchange.arguments
|
|
248
|
+
...exchange.durable !== void 0 && { durable: exchange.durable },
|
|
249
|
+
...exchange.autoDelete !== void 0 && { autoDelete: exchange.autoDelete },
|
|
250
|
+
...exchange.internal !== void 0 && { internal: exchange.internal },
|
|
251
|
+
...exchange.arguments !== void 0 && { arguments: exchange.arguments }
|
|
245
252
|
})))).map((result, i) => ({
|
|
246
253
|
result,
|
|
247
254
|
name: exchanges[i].name
|
|
@@ -272,9 +279,9 @@ async function setupAmqpTopology(channel, contract) {
|
|
|
272
279
|
});
|
|
273
280
|
if (queue.maxPriority !== void 0) queueArguments["x-max-priority"] = queue.maxPriority;
|
|
274
281
|
return channel.assertQueue(queue.name, {
|
|
275
|
-
durable: queue.durable,
|
|
276
|
-
exclusive: queue.exclusive,
|
|
277
|
-
autoDelete: queue.autoDelete,
|
|
282
|
+
...queue.durable !== void 0 && { durable: queue.durable },
|
|
283
|
+
...queue.exclusive !== void 0 && { exclusive: queue.exclusive },
|
|
284
|
+
...queue.autoDelete !== void 0 && { autoDelete: queue.autoDelete },
|
|
278
285
|
arguments: queueArguments
|
|
279
286
|
});
|
|
280
287
|
}))).map((result, i) => ({
|
|
@@ -348,7 +355,7 @@ function resolveConnectTimeoutMs(input) {
|
|
|
348
355
|
* - Automatic AMQP topology setup (exchanges, queues, bindings) from contract
|
|
349
356
|
* - Channel creation with JSON serialization enabled by default
|
|
350
357
|
*
|
|
351
|
-
* All operations return `
|
|
358
|
+
* All operations return `AsyncResult<T, TechnicalError>` for consistent error handling.
|
|
352
359
|
*
|
|
353
360
|
* @example
|
|
354
361
|
* ```typescript
|
|
@@ -357,7 +364,7 @@ function resolveConnectTimeoutMs(input) {
|
|
|
357
364
|
* connectionOptions: { heartbeatIntervalInSeconds: 30 }
|
|
358
365
|
* });
|
|
359
366
|
*
|
|
360
|
-
* // Wait for connection (
|
|
367
|
+
* // Wait for connection (AsyncResult is thenable)
|
|
361
368
|
* await client.waitForConnect();
|
|
362
369
|
*
|
|
363
370
|
* // Publish a message
|
|
@@ -368,6 +375,7 @@ function resolveConnectTimeoutMs(input) {
|
|
|
368
375
|
* ```
|
|
369
376
|
*/
|
|
370
377
|
var AmqpClient = class {
|
|
378
|
+
contract;
|
|
371
379
|
connection;
|
|
372
380
|
channelWrapper;
|
|
373
381
|
urls;
|
|
@@ -431,7 +439,7 @@ var AmqpClient = class {
|
|
|
431
439
|
* Wait for the channel to be connected and ready.
|
|
432
440
|
*
|
|
433
441
|
* If `connectTimeoutMs` was provided in the constructor options, the returned
|
|
434
|
-
*
|
|
442
|
+
* AsyncResult resolves to `err(TechnicalError)` once the timeout elapses.
|
|
435
443
|
* Without a timeout, this waits forever — amqp-connection-manager retries
|
|
436
444
|
* connections indefinitely and never errors on its own.
|
|
437
445
|
*
|
|
@@ -444,7 +452,7 @@ var AmqpClient = class {
|
|
|
444
452
|
waitForConnect() {
|
|
445
453
|
const connectPromise = this.channelWrapper.waitForConnect();
|
|
446
454
|
const timeoutMs = this.connectTimeoutMs;
|
|
447
|
-
|
|
455
|
+
return (0, unthrown.fromPromise)(timeoutMs === null ? connectPromise : new Promise((resolve, reject) => {
|
|
448
456
|
const handle = setTimeout(() => {
|
|
449
457
|
reject(/* @__PURE__ */ new Error(`Timed out waiting for AMQP connection after ${timeoutMs}ms`));
|
|
450
458
|
}, timeoutMs);
|
|
@@ -455,24 +463,23 @@ var AmqpClient = class {
|
|
|
455
463
|
clearTimeout(handle);
|
|
456
464
|
reject(error);
|
|
457
465
|
});
|
|
458
|
-
});
|
|
459
|
-
return neverthrow.ResultAsync.fromPromise(racedPromise, (error) => new TechnicalError("Failed to connect to AMQP broker", error));
|
|
466
|
+
}), (error) => new TechnicalError("Failed to connect to AMQP broker", error));
|
|
460
467
|
}
|
|
461
468
|
/**
|
|
462
469
|
* Publish a message to an exchange.
|
|
463
470
|
*
|
|
464
|
-
* @returns
|
|
471
|
+
* @returns AsyncResult resolving to `true` if the message was sent, `false` if the channel buffer is full.
|
|
465
472
|
*/
|
|
466
473
|
publish(exchange, routingKey, content, options) {
|
|
467
|
-
return
|
|
474
|
+
return (0, unthrown.fromPromise)(this.channelWrapper.publish(exchange, routingKey, content, options), (error) => new TechnicalError("Failed to publish message", error));
|
|
468
475
|
}
|
|
469
476
|
/**
|
|
470
477
|
* Publish a message directly to a queue.
|
|
471
478
|
*
|
|
472
|
-
* @returns
|
|
479
|
+
* @returns AsyncResult resolving to `true` if the message was sent, `false` if the channel buffer is full.
|
|
473
480
|
*/
|
|
474
481
|
sendToQueue(queue, content, options) {
|
|
475
|
-
return
|
|
482
|
+
return (0, unthrown.fromPromise)(this.channelWrapper.sendToQueue(queue, content, options), (error) => new TechnicalError("Failed to publish message to queue", error));
|
|
476
483
|
}
|
|
477
484
|
/**
|
|
478
485
|
* Start consuming messages from a queue.
|
|
@@ -489,17 +496,17 @@ var AmqpClient = class {
|
|
|
489
496
|
* because it is not a valid `amqplib` `Options.Consume` field — leaving it
|
|
490
497
|
* in would just travel as a no-op key-value pair on the consume frame.
|
|
491
498
|
*
|
|
492
|
-
* @returns
|
|
499
|
+
* @returns AsyncResult resolving to the consumer tag.
|
|
493
500
|
*/
|
|
494
501
|
consume(queue, callback, options) {
|
|
495
502
|
const { prefetch, ...consumeOptions } = options ?? {};
|
|
496
503
|
if (prefetch !== void 0) {
|
|
497
|
-
if (!Number.isInteger(prefetch) || prefetch < 0 || prefetch > 65535) return (0,
|
|
504
|
+
if (!Number.isInteger(prefetch) || prefetch < 0 || prefetch > 65535) return (0, unthrown.err)(new TechnicalError(`Invalid prefetch: expected a non-negative integer ≤ 65535, got ${String(prefetch)}`)).toAsync();
|
|
498
505
|
}
|
|
499
506
|
const prefetchSetup = typeof prefetch === "number" ? async (channel) => {
|
|
500
507
|
await channel.prefetch(prefetch, false);
|
|
501
508
|
} : void 0;
|
|
502
|
-
|
|
509
|
+
return (0, unthrown.fromPromise)((async () => {
|
|
503
510
|
if (prefetchSetup) await this.channelWrapper.addSetup(prefetchSetup);
|
|
504
511
|
let reply;
|
|
505
512
|
try {
|
|
@@ -510,14 +517,13 @@ var AmqpClient = class {
|
|
|
510
517
|
}
|
|
511
518
|
if (prefetchSetup) this.prefetchSetups.set(reply.consumerTag, prefetchSetup);
|
|
512
519
|
return reply;
|
|
513
|
-
})();
|
|
514
|
-
return neverthrow.ResultAsync.fromPromise(consumePromise, (error) => new TechnicalError("Failed to start consuming messages", error)).map((reply) => reply.consumerTag);
|
|
520
|
+
})(), (error) => new TechnicalError("Failed to start consuming messages", error)).map((reply) => reply.consumerTag);
|
|
515
521
|
}
|
|
516
522
|
/**
|
|
517
523
|
* Cancel a consumer by its consumer tag.
|
|
518
524
|
*/
|
|
519
525
|
cancel(consumerTag) {
|
|
520
|
-
return
|
|
526
|
+
return (0, unthrown.fromPromise)((async () => {
|
|
521
527
|
const setup = this.prefetchSetups.get(consumerTag);
|
|
522
528
|
this.prefetchSetups.delete(consumerTag);
|
|
523
529
|
try {
|
|
@@ -582,14 +588,14 @@ var AmqpClient = class {
|
|
|
582
588
|
* errors are wrapped in an AggregateError.
|
|
583
589
|
*/
|
|
584
590
|
close() {
|
|
585
|
-
return
|
|
586
|
-
const channelResult = await
|
|
587
|
-
const releaseResult = await
|
|
588
|
-
if (channelResult.isErr() && releaseResult.isErr()) return (0,
|
|
591
|
+
return (0, unthrown.fromSafePromise)((async () => {
|
|
592
|
+
const channelResult = await (0, unthrown.fromPromise)(this.channelWrapper.close(), (error) => new TechnicalError("Failed to close channel", error));
|
|
593
|
+
const releaseResult = await (0, unthrown.fromPromise)(ConnectionManagerSingleton.getInstance().releaseConnection(this.urls, this.connectionOptions), (error) => new TechnicalError("Failed to release connection", error));
|
|
594
|
+
if (channelResult.isErr() && releaseResult.isErr()) return (0, unthrown.err)(new TechnicalError("Failed to close channel and release connection", new AggregateError([channelResult.error, releaseResult.error], "Failed to close channel and release connection")));
|
|
589
595
|
if (channelResult.isErr()) return channelResult;
|
|
590
596
|
if (releaseResult.isErr()) return releaseResult;
|
|
591
|
-
return (0,
|
|
592
|
-
})());
|
|
597
|
+
return (0, unthrown.ok)(void 0);
|
|
598
|
+
})()).flatMap((result) => result);
|
|
593
599
|
}
|
|
594
600
|
/**
|
|
595
601
|
* Reset connection singleton cache (for testing only)
|
|
@@ -623,7 +629,7 @@ var AmqpClient = class {
|
|
|
623
629
|
* ```
|
|
624
630
|
*/
|
|
625
631
|
function safeJsonParse(buffer, errorFn) {
|
|
626
|
-
return
|
|
632
|
+
return (0, unthrown.fromThrowable)(() => JSON.parse(buffer.toString()), errorFn)();
|
|
627
633
|
}
|
|
628
634
|
//#endregion
|
|
629
635
|
//#region src/telemetry.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
1
1
|
import { ContractDefinition } from "@amqp-contract/contract";
|
|
2
2
|
import { AmqpConnectionManager, AmqpConnectionManagerOptions, ConnectionUrl, CreateChannelOpts } from "amqp-connection-manager";
|
|
3
3
|
import { Channel, ConsumeMessage, Options } from "amqplib";
|
|
4
|
-
import {
|
|
4
|
+
import { AsyncResult, Result } from "unthrown";
|
|
5
5
|
import { Attributes, Counter, Histogram, Span, Tracer } from "@opentelemetry/api";
|
|
6
6
|
|
|
7
7
|
//#region src/errors.d.ts
|
|
8
|
+
declare const TechnicalError_base: import("unthrown").TaggedErrorConstructor<"@amqp-contract/TechnicalError">;
|
|
8
9
|
/**
|
|
9
10
|
* Error for technical/runtime failures that cannot be prevented by TypeScript.
|
|
10
11
|
*
|
|
11
12
|
* This includes AMQP connection failures, channel issues, validation failures,
|
|
12
13
|
* and other runtime errors. This error is shared across core, worker, and client packages.
|
|
14
|
+
*
|
|
15
|
+
* Built on unthrown's {@link TaggedError}, so it carries a `_tag` of
|
|
16
|
+
* `"@amqp-contract/TechnicalError"` for exhaustive dispatch via `matchTags`. The
|
|
17
|
+
* tag is namespaced to avoid colliding with other libraries' tags in a shared
|
|
18
|
+
* `matchTags`; the human-facing `Error.name` is kept bare (`"TechnicalError"`).
|
|
19
|
+
* Remains a real `Error` (and a *modeled* error — it lives in the `E` channel of
|
|
20
|
+
* a `Result`, never the `Defect` channel).
|
|
13
21
|
*/
|
|
14
|
-
declare class TechnicalError extends
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
declare class TechnicalError extends TechnicalError_base<{
|
|
23
|
+
message: string;
|
|
24
|
+
cause?: unknown;
|
|
25
|
+
}> {
|
|
26
|
+
constructor(message: string, cause?: unknown);
|
|
17
27
|
}
|
|
28
|
+
declare const MessageValidationError_base: import("unthrown").TaggedErrorConstructor<"@amqp-contract/MessageValidationError">;
|
|
18
29
|
/**
|
|
19
30
|
* Error thrown when message validation fails (payload or headers).
|
|
20
31
|
*
|
|
21
32
|
* Used by both the client (publish-time payload validation) and the worker
|
|
22
|
-
* (consume-time payload and headers validation).
|
|
33
|
+
* (consume-time payload and headers validation). Carries a `_tag` of
|
|
34
|
+
* `"@amqp-contract/MessageValidationError"` (namespaced to avoid collisions);
|
|
35
|
+
* the `Error.name` is kept bare (`"MessageValidationError"`).
|
|
23
36
|
*
|
|
24
37
|
* @param source - The name of the publisher or consumer that triggered the validation
|
|
25
38
|
* @param issues - The validation issues from the Standard Schema validation
|
|
26
39
|
*/
|
|
27
|
-
declare class MessageValidationError extends
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
declare class MessageValidationError extends MessageValidationError_base<{
|
|
41
|
+
message: string;
|
|
42
|
+
source: string;
|
|
43
|
+
issues: unknown;
|
|
44
|
+
}> {
|
|
30
45
|
constructor(source: string, issues: unknown);
|
|
31
46
|
}
|
|
32
47
|
//#endregion
|
|
@@ -96,7 +111,7 @@ type ConsumerOptions = Options.Consume & {
|
|
|
96
111
|
* - Automatic AMQP topology setup (exchanges, queues, bindings) from contract
|
|
97
112
|
* - Channel creation with JSON serialization enabled by default
|
|
98
113
|
*
|
|
99
|
-
* All operations return `
|
|
114
|
+
* All operations return `AsyncResult<T, TechnicalError>` for consistent error handling.
|
|
100
115
|
*
|
|
101
116
|
* @example
|
|
102
117
|
* ```typescript
|
|
@@ -105,7 +120,7 @@ type ConsumerOptions = Options.Consume & {
|
|
|
105
120
|
* connectionOptions: { heartbeatIntervalInSeconds: 30 }
|
|
106
121
|
* });
|
|
107
122
|
*
|
|
108
|
-
* // Wait for connection (
|
|
123
|
+
* // Wait for connection (AsyncResult is thenable)
|
|
109
124
|
* await client.waitForConnect();
|
|
110
125
|
*
|
|
111
126
|
* // Publish a message
|
|
@@ -158,7 +173,7 @@ declare class AmqpClient {
|
|
|
158
173
|
* Wait for the channel to be connected and ready.
|
|
159
174
|
*
|
|
160
175
|
* If `connectTimeoutMs` was provided in the constructor options, the returned
|
|
161
|
-
*
|
|
176
|
+
* AsyncResult resolves to `err(TechnicalError)` once the timeout elapses.
|
|
162
177
|
* Without a timeout, this waits forever — amqp-connection-manager retries
|
|
163
178
|
* connections indefinitely and never errors on its own.
|
|
164
179
|
*
|
|
@@ -168,19 +183,19 @@ declare class AmqpClient {
|
|
|
168
183
|
* path to release the connection — `waitForConnect` does not do this
|
|
169
184
|
* automatically. The typed factories handle this cleanup for you.
|
|
170
185
|
*/
|
|
171
|
-
waitForConnect():
|
|
186
|
+
waitForConnect(): AsyncResult<void, TechnicalError>;
|
|
172
187
|
/**
|
|
173
188
|
* Publish a message to an exchange.
|
|
174
189
|
*
|
|
175
|
-
* @returns
|
|
190
|
+
* @returns AsyncResult resolving to `true` if the message was sent, `false` if the channel buffer is full.
|
|
176
191
|
*/
|
|
177
|
-
publish(exchange: string, routingKey: string, content: Buffer | unknown, options?: PublishOptions):
|
|
192
|
+
publish(exchange: string, routingKey: string, content: Buffer | unknown, options?: PublishOptions): AsyncResult<boolean, TechnicalError>;
|
|
178
193
|
/**
|
|
179
194
|
* Publish a message directly to a queue.
|
|
180
195
|
*
|
|
181
|
-
* @returns
|
|
196
|
+
* @returns AsyncResult resolving to `true` if the message was sent, `false` if the channel buffer is full.
|
|
182
197
|
*/
|
|
183
|
-
sendToQueue(queue: string, content: Buffer | unknown, options?: PublishOptions):
|
|
198
|
+
sendToQueue(queue: string, content: Buffer | unknown, options?: PublishOptions): AsyncResult<boolean, TechnicalError>;
|
|
184
199
|
/**
|
|
185
200
|
* Start consuming messages from a queue.
|
|
186
201
|
*
|
|
@@ -196,13 +211,13 @@ declare class AmqpClient {
|
|
|
196
211
|
* because it is not a valid `amqplib` `Options.Consume` field — leaving it
|
|
197
212
|
* in would just travel as a no-op key-value pair on the consume frame.
|
|
198
213
|
*
|
|
199
|
-
* @returns
|
|
214
|
+
* @returns AsyncResult resolving to the consumer tag.
|
|
200
215
|
*/
|
|
201
|
-
consume(queue: string, callback: ConsumeCallback, options?: ConsumerOptions):
|
|
216
|
+
consume(queue: string, callback: ConsumeCallback, options?: ConsumerOptions): AsyncResult<string, TechnicalError>;
|
|
202
217
|
/**
|
|
203
218
|
* Cancel a consumer by its consumer tag.
|
|
204
219
|
*/
|
|
205
|
-
cancel(consumerTag: string):
|
|
220
|
+
cancel(consumerTag: string): AsyncResult<void, TechnicalError>;
|
|
206
221
|
/**
|
|
207
222
|
* Acknowledge a message.
|
|
208
223
|
*
|
|
@@ -249,7 +264,7 @@ declare class AmqpClient {
|
|
|
249
264
|
* Both steps run regardless of each other's outcome; if both fail, the
|
|
250
265
|
* errors are wrapped in an AggregateError.
|
|
251
266
|
*/
|
|
252
|
-
close():
|
|
267
|
+
close(): AsyncResult<void, TechnicalError>;
|
|
253
268
|
/**
|
|
254
269
|
* Reset connection singleton cache (for testing only)
|
|
255
270
|
* @internal
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/amqp-client.ts","../src/connection-manager.ts","../src/logger.ts","../src/parsing.ts","../src/setup.ts","../src/telemetry.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/amqp-client.ts","../src/connection-manager.ts","../src/logger.ts","../src/parsing.ts","../src/setup.ts","../src/telemetry.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AsyncResult, Result } from "unthrown";
|
|
2
2
|
import { AmqpConnectionManager, AmqpConnectionManagerOptions, ConnectionUrl, CreateChannelOpts } from "amqp-connection-manager";
|
|
3
3
|
import { ContractDefinition } from "@amqp-contract/contract";
|
|
4
4
|
import { Attributes, Counter, Histogram, Span, Tracer } from "@opentelemetry/api";
|
|
5
5
|
import { Channel, ConsumeMessage, Options } from "amqplib";
|
|
6
6
|
|
|
7
7
|
//#region src/errors.d.ts
|
|
8
|
+
declare const TechnicalError_base: import("unthrown").TaggedErrorConstructor<"@amqp-contract/TechnicalError">;
|
|
8
9
|
/**
|
|
9
10
|
* Error for technical/runtime failures that cannot be prevented by TypeScript.
|
|
10
11
|
*
|
|
11
12
|
* This includes AMQP connection failures, channel issues, validation failures,
|
|
12
13
|
* and other runtime errors. This error is shared across core, worker, and client packages.
|
|
14
|
+
*
|
|
15
|
+
* Built on unthrown's {@link TaggedError}, so it carries a `_tag` of
|
|
16
|
+
* `"@amqp-contract/TechnicalError"` for exhaustive dispatch via `matchTags`. The
|
|
17
|
+
* tag is namespaced to avoid colliding with other libraries' tags in a shared
|
|
18
|
+
* `matchTags`; the human-facing `Error.name` is kept bare (`"TechnicalError"`).
|
|
19
|
+
* Remains a real `Error` (and a *modeled* error — it lives in the `E` channel of
|
|
20
|
+
* a `Result`, never the `Defect` channel).
|
|
13
21
|
*/
|
|
14
|
-
declare class TechnicalError extends
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
declare class TechnicalError extends TechnicalError_base<{
|
|
23
|
+
message: string;
|
|
24
|
+
cause?: unknown;
|
|
25
|
+
}> {
|
|
26
|
+
constructor(message: string, cause?: unknown);
|
|
17
27
|
}
|
|
28
|
+
declare const MessageValidationError_base: import("unthrown").TaggedErrorConstructor<"@amqp-contract/MessageValidationError">;
|
|
18
29
|
/**
|
|
19
30
|
* Error thrown when message validation fails (payload or headers).
|
|
20
31
|
*
|
|
21
32
|
* Used by both the client (publish-time payload validation) and the worker
|
|
22
|
-
* (consume-time payload and headers validation).
|
|
33
|
+
* (consume-time payload and headers validation). Carries a `_tag` of
|
|
34
|
+
* `"@amqp-contract/MessageValidationError"` (namespaced to avoid collisions);
|
|
35
|
+
* the `Error.name` is kept bare (`"MessageValidationError"`).
|
|
23
36
|
*
|
|
24
37
|
* @param source - The name of the publisher or consumer that triggered the validation
|
|
25
38
|
* @param issues - The validation issues from the Standard Schema validation
|
|
26
39
|
*/
|
|
27
|
-
declare class MessageValidationError extends
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
declare class MessageValidationError extends MessageValidationError_base<{
|
|
41
|
+
message: string;
|
|
42
|
+
source: string;
|
|
43
|
+
issues: unknown;
|
|
44
|
+
}> {
|
|
30
45
|
constructor(source: string, issues: unknown);
|
|
31
46
|
}
|
|
32
47
|
//#endregion
|
|
@@ -96,7 +111,7 @@ type ConsumerOptions = Options.Consume & {
|
|
|
96
111
|
* - Automatic AMQP topology setup (exchanges, queues, bindings) from contract
|
|
97
112
|
* - Channel creation with JSON serialization enabled by default
|
|
98
113
|
*
|
|
99
|
-
* All operations return `
|
|
114
|
+
* All operations return `AsyncResult<T, TechnicalError>` for consistent error handling.
|
|
100
115
|
*
|
|
101
116
|
* @example
|
|
102
117
|
* ```typescript
|
|
@@ -105,7 +120,7 @@ type ConsumerOptions = Options.Consume & {
|
|
|
105
120
|
* connectionOptions: { heartbeatIntervalInSeconds: 30 }
|
|
106
121
|
* });
|
|
107
122
|
*
|
|
108
|
-
* // Wait for connection (
|
|
123
|
+
* // Wait for connection (AsyncResult is thenable)
|
|
109
124
|
* await client.waitForConnect();
|
|
110
125
|
*
|
|
111
126
|
* // Publish a message
|
|
@@ -158,7 +173,7 @@ declare class AmqpClient {
|
|
|
158
173
|
* Wait for the channel to be connected and ready.
|
|
159
174
|
*
|
|
160
175
|
* If `connectTimeoutMs` was provided in the constructor options, the returned
|
|
161
|
-
*
|
|
176
|
+
* AsyncResult resolves to `err(TechnicalError)` once the timeout elapses.
|
|
162
177
|
* Without a timeout, this waits forever — amqp-connection-manager retries
|
|
163
178
|
* connections indefinitely and never errors on its own.
|
|
164
179
|
*
|
|
@@ -168,19 +183,19 @@ declare class AmqpClient {
|
|
|
168
183
|
* path to release the connection — `waitForConnect` does not do this
|
|
169
184
|
* automatically. The typed factories handle this cleanup for you.
|
|
170
185
|
*/
|
|
171
|
-
waitForConnect():
|
|
186
|
+
waitForConnect(): AsyncResult<void, TechnicalError>;
|
|
172
187
|
/**
|
|
173
188
|
* Publish a message to an exchange.
|
|
174
189
|
*
|
|
175
|
-
* @returns
|
|
190
|
+
* @returns AsyncResult resolving to `true` if the message was sent, `false` if the channel buffer is full.
|
|
176
191
|
*/
|
|
177
|
-
publish(exchange: string, routingKey: string, content: Buffer | unknown, options?: PublishOptions):
|
|
192
|
+
publish(exchange: string, routingKey: string, content: Buffer | unknown, options?: PublishOptions): AsyncResult<boolean, TechnicalError>;
|
|
178
193
|
/**
|
|
179
194
|
* Publish a message directly to a queue.
|
|
180
195
|
*
|
|
181
|
-
* @returns
|
|
196
|
+
* @returns AsyncResult resolving to `true` if the message was sent, `false` if the channel buffer is full.
|
|
182
197
|
*/
|
|
183
|
-
sendToQueue(queue: string, content: Buffer | unknown, options?: PublishOptions):
|
|
198
|
+
sendToQueue(queue: string, content: Buffer | unknown, options?: PublishOptions): AsyncResult<boolean, TechnicalError>;
|
|
184
199
|
/**
|
|
185
200
|
* Start consuming messages from a queue.
|
|
186
201
|
*
|
|
@@ -196,13 +211,13 @@ declare class AmqpClient {
|
|
|
196
211
|
* because it is not a valid `amqplib` `Options.Consume` field — leaving it
|
|
197
212
|
* in would just travel as a no-op key-value pair on the consume frame.
|
|
198
213
|
*
|
|
199
|
-
* @returns
|
|
214
|
+
* @returns AsyncResult resolving to the consumer tag.
|
|
200
215
|
*/
|
|
201
|
-
consume(queue: string, callback: ConsumeCallback, options?: ConsumerOptions):
|
|
216
|
+
consume(queue: string, callback: ConsumeCallback, options?: ConsumerOptions): AsyncResult<string, TechnicalError>;
|
|
202
217
|
/**
|
|
203
218
|
* Cancel a consumer by its consumer tag.
|
|
204
219
|
*/
|
|
205
|
-
cancel(consumerTag: string):
|
|
220
|
+
cancel(consumerTag: string): AsyncResult<void, TechnicalError>;
|
|
206
221
|
/**
|
|
207
222
|
* Acknowledge a message.
|
|
208
223
|
*
|
|
@@ -249,7 +264,7 @@ declare class AmqpClient {
|
|
|
249
264
|
* Both steps run regardless of each other's outcome; if both fail, the
|
|
250
265
|
* errors are wrapped in an AggregateError.
|
|
251
266
|
*/
|
|
252
|
-
close():
|
|
267
|
+
close(): AsyncResult<void, TechnicalError>;
|
|
253
268
|
/**
|
|
254
269
|
* Reset connection singleton cache (for testing only)
|
|
255
270
|
* @internal
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/amqp-client.ts","../src/connection-manager.ts","../src/logger.ts","../src/parsing.ts","../src/setup.ts","../src/telemetry.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/amqp-client.ts","../src/connection-manager.ts","../src/logger.ts","../src/parsing.ts","../src/setup.ts","../src/telemetry.ts"],"mappings":"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"}
|