@relaybus/rabbitmq 0.2.0 → 0.3.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 +88 -46
- package/dist/index.cjs +624 -398
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -45
- package/dist/index.d.ts +121 -45
- package/dist/index.js +611 -394
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { NonRetryableError, RelayBusError, EventHeaders, EventEnvelope, RetryPolicyOptions, Duration, RelayBusLogger,
|
|
2
|
+
import { NonRetryableError, RelayBusError, EventHeaders, EventEnvelope, RetryPolicyOptions, Duration, RelayBusLogger, CloseOptions } from '@relaybus/core';
|
|
3
|
+
import { JsonEnvelopeMapping, SubscribingTransport, TransportSubscription } from '@relaybus/core/internal';
|
|
4
|
+
export { fromHeader, fromPayloadField } from '@relaybus/core/internal';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* The slice of amqplib this package relies on. Declaring it here keeps the
|
|
@@ -74,18 +76,26 @@ interface AmqpConnection extends EventEmitter {
|
|
|
74
76
|
* Always retryable; the outbox keeps the delivery and tries again.
|
|
75
77
|
*/
|
|
76
78
|
declare class RabbitMqUnavailableError extends RelayBusError {
|
|
79
|
+
name: string;
|
|
80
|
+
readonly code: string;
|
|
77
81
|
}
|
|
78
82
|
/** The broker negatively acknowledged a published message. Retryable. */
|
|
79
83
|
declare class RabbitMqPublishRejectedError extends RelayBusError {
|
|
84
|
+
name: string;
|
|
85
|
+
readonly code: string;
|
|
80
86
|
}
|
|
81
87
|
/**
|
|
82
88
|
* The broker accepted the message but no queue is bound to its routing key, so
|
|
83
89
|
* it would have been discarded. Retryable: it succeeds once a consumer binds.
|
|
84
90
|
*/
|
|
85
91
|
declare class UnroutableMessageError extends RelayBusError {
|
|
92
|
+
name: string;
|
|
93
|
+
readonly code: string;
|
|
86
94
|
}
|
|
87
95
|
/** A received message is not a valid relaybus CloudEvent. It is dead-lettered. */
|
|
88
96
|
declare class MalformedMessageError extends RelayBusError {
|
|
97
|
+
name: string;
|
|
98
|
+
readonly code: string;
|
|
89
99
|
}
|
|
90
100
|
/**
|
|
91
101
|
* The payload of an event cannot be represented as JSON without losing or
|
|
@@ -94,6 +104,7 @@ declare class MalformedMessageError extends RelayBusError {
|
|
|
94
104
|
*/
|
|
95
105
|
declare class UnserializablePayloadError extends NonRetryableError {
|
|
96
106
|
name: string;
|
|
107
|
+
readonly code: string;
|
|
97
108
|
}
|
|
98
109
|
/**
|
|
99
110
|
* A value exceeds a protocol limit of AMQP 0-9-1, for example an event id or a
|
|
@@ -101,6 +112,15 @@ declare class UnserializablePayloadError extends NonRetryableError {
|
|
|
101
112
|
*/
|
|
102
113
|
declare class AmqpLimitExceededError extends NonRetryableError {
|
|
103
114
|
name: string;
|
|
115
|
+
readonly code: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* An event the configured codec cannot write: a header name the format
|
|
119
|
+
* reserves, or a type a fixed-type route does not carry. Never retried.
|
|
120
|
+
*/
|
|
121
|
+
declare class RabbitMqUnencodableEventError extends NonRetryableError {
|
|
122
|
+
name: string;
|
|
123
|
+
readonly code: string;
|
|
104
124
|
}
|
|
105
125
|
|
|
106
126
|
/**
|
|
@@ -210,6 +230,73 @@ declare function decodeCloudEvent(message: AmqpMessage): EventEnvelope;
|
|
|
210
230
|
*/
|
|
211
231
|
declare function plainJsonDecoder(options: PlainJsonDecoderOptions): RabbitMqMessageDecoder;
|
|
212
232
|
|
|
233
|
+
/** A serialized event, ready for `channel.publish`. */
|
|
234
|
+
interface EncodedMessage {
|
|
235
|
+
readonly content: Buffer;
|
|
236
|
+
readonly options: AmqpPublishOptions;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The wire format of a {@link RabbitMqTransport}: how an event becomes a
|
|
241
|
+
* message (`encode`, on publish) and a consumed message becomes an event
|
|
242
|
+
* (`decode`).
|
|
243
|
+
*
|
|
244
|
+
* Both must be synchronous and free of side effects. What `encode` throws
|
|
245
|
+
* fails the publish: the outbox retries it, unless it is a `NonRetryableError`
|
|
246
|
+
* such as {@link RabbitMqUnencodableEventError}. Give every message a
|
|
247
|
+
* `messageId`: the transport matches broker returns of unroutable messages by
|
|
248
|
+
* it. What `decode` throws marks the message as malformed: it is
|
|
249
|
+
* dead-lettered and the consumer moves on. See {@link RabbitMqMessageDecoder}
|
|
250
|
+
* for the decode contract.
|
|
251
|
+
*/
|
|
252
|
+
interface RabbitMqCodec {
|
|
253
|
+
readonly encode: (envelope: EventEnvelope) => EncodedMessage;
|
|
254
|
+
readonly decode: RabbitMqMessageDecoder;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* CloudEvents 1.0 binary content mode, the default: the body is the JSON
|
|
258
|
+
* payload, the attributes travel as `cloudEvents:*` headers mirrored in the
|
|
259
|
+
* AMQP properties. Decoding is strict: any other message is malformed.
|
|
260
|
+
*/
|
|
261
|
+
declare const cloudEventsBinary: RabbitMqCodec;
|
|
262
|
+
/**
|
|
263
|
+
* CloudEvents 1.0 structured content mode: the body is one
|
|
264
|
+
* `application/cloudevents+json` document with the attributes and `data`.
|
|
265
|
+
* Decoding accepts structured and binary mode ({@link decodeCloudEvent}).
|
|
266
|
+
* Event headers travel under their own names; names starting with `x-death`,
|
|
267
|
+
* `x-first-death-`, `x-last-death-` or `x-relaybus-` are refused.
|
|
268
|
+
*/
|
|
269
|
+
declare const cloudEventsStructured: RabbitMqCodec;
|
|
270
|
+
/**
|
|
271
|
+
* Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides
|
|
272
|
+
* `{ body }` and `{ header }`, the id may be `'message-id-property'`: the
|
|
273
|
+
* AMQP `messageId` property, which the codec always writes and which survives
|
|
274
|
+
* redeliveries; a message without one is malformed.
|
|
275
|
+
*/
|
|
276
|
+
type RabbitMqJsonEnvelopeMapping = JsonEnvelopeMapping<'message-id-property'>;
|
|
277
|
+
/**
|
|
278
|
+
* A JSON wire format declared by a mapping, in both directions: for queues
|
|
279
|
+
* shared with services that wrap events in their own envelope
|
|
280
|
+
* (`{ "eventName": ..., "data": {...} }`, MassTransit) or send the bare
|
|
281
|
+
* payload. Every message also gets the AMQP properties of binary mode:
|
|
282
|
+
* `messageId` (the event id), `type`, `appId` (the source), `correlationId`,
|
|
283
|
+
* `timestamp` (seconds) and `persistent`. Event
|
|
284
|
+
* headers that are message headers are written as they are, so a name the
|
|
285
|
+
* mapping uses for another field, or one the broker reserves, is refused
|
|
286
|
+
* with {@link RabbitMqUnencodableEventError}.
|
|
287
|
+
*
|
|
288
|
+
* ```ts
|
|
289
|
+
* codec: jsonEnvelope({
|
|
290
|
+
* type: { body: 'eventName' },
|
|
291
|
+
* id: 'message-id-property',
|
|
292
|
+
* payload: { body: 'data' },
|
|
293
|
+
* })
|
|
294
|
+
* ```
|
|
295
|
+
*
|
|
296
|
+
* @throws ConfigurationError for an incomplete or self-overlapping mapping.
|
|
297
|
+
*/
|
|
298
|
+
declare function jsonEnvelope(mapping: RabbitMqJsonEnvelopeMapping): RabbitMqCodec;
|
|
299
|
+
|
|
213
300
|
/** Connection settings accepted by `amqplib.connect`, given as an object instead of a URL. */
|
|
214
301
|
interface BrokerConnectionSettings {
|
|
215
302
|
readonly protocol?: string;
|
|
@@ -246,9 +333,11 @@ interface RabbitMqTransportOptions {
|
|
|
246
333
|
readonly url?: string | BrokerConnectionSettings;
|
|
247
334
|
/**
|
|
248
335
|
* Opens one connection. Called again after every connection loss. Use it for
|
|
249
|
-
* TLS options, custom credentials or an alternative amqplib instance.
|
|
336
|
+
* TLS options, custom credentials or an alternative amqplib instance. `signal` aborts when a
|
|
337
|
+
* shutdown runs past its deadline: pass it on (`amqplib.connect(url, { signal })`) so a broker
|
|
338
|
+
* that never answers the handshake cannot hold the socket open.
|
|
250
339
|
*/
|
|
251
|
-
readonly connect?: () => Promise<AmqpConnection>;
|
|
340
|
+
readonly connect?: (options: ConnectOptions) => Promise<AmqpConnection>;
|
|
252
341
|
/** Topic exchange events are published to. Durable, created when missing. Default `'relaybus'`. */
|
|
253
342
|
readonly exchange?: string;
|
|
254
343
|
/**
|
|
@@ -317,22 +406,35 @@ interface RabbitMqTransportOptions {
|
|
|
317
406
|
/** How long `close` waits for running handlers. Default `'30s'`. */
|
|
318
407
|
readonly shutdownTimeout?: Duration;
|
|
319
408
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* Whatever
|
|
409
|
+
* The wire format, both ways: how events become messages and consumed
|
|
410
|
+
* messages become events. Default {@link cloudEventsBinary}: CloudEvents
|
|
411
|
+
* binary mode (`cloudEvents:*` headers, AMQP properties as fallback), any
|
|
412
|
+
* other message is malformed and dead-lettered. {@link cloudEventsStructured}
|
|
413
|
+
* writes structured mode and reads both, {@link jsonEnvelope} maps a JSON
|
|
414
|
+
* format of your own (an envelope with the payload inside, or the bare
|
|
415
|
+
* payload), and an object with `encode` and `decode` can do anything else.
|
|
416
|
+
* Whatever `decode` throws marks the message as malformed: it is
|
|
328
417
|
* dead-lettered, the consumer keeps running.
|
|
329
418
|
*/
|
|
419
|
+
readonly codec?: RabbitMqCodec;
|
|
420
|
+
/**
|
|
421
|
+
* How consumed messages become events; events are still written in
|
|
422
|
+
* CloudEvents binary mode.
|
|
423
|
+
*
|
|
424
|
+
* @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.
|
|
425
|
+
* Giving both `decode` and `codec` is a configuration error.
|
|
426
|
+
*/
|
|
330
427
|
readonly decode?: RabbitMqMessageDecoder;
|
|
331
428
|
/** Default: `console`. */
|
|
332
429
|
readonly logger?: RelayBusLogger;
|
|
333
430
|
/** Random source for jitter. Default `Math.random`. Intended for tests. */
|
|
334
431
|
readonly random?: () => number;
|
|
335
432
|
}
|
|
433
|
+
/** What `connect` gets for each connection it opens. */
|
|
434
|
+
interface ConnectOptions {
|
|
435
|
+
/** Aborted when a shutdown runs past its deadline; destroys a socket still connecting. */
|
|
436
|
+
readonly signal: AbortSignal;
|
|
437
|
+
}
|
|
336
438
|
|
|
337
439
|
/**
|
|
338
440
|
* RabbitMQ {@link Transport} built on amqplib.
|
|
@@ -356,9 +458,10 @@ interface RabbitMqTransportOptions {
|
|
|
356
458
|
* consumer. Events published meanwhile are rejected, and therefore retried by
|
|
357
459
|
* the outbox, rather than buffered in memory.
|
|
358
460
|
*/
|
|
359
|
-
declare class RabbitMqTransport
|
|
461
|
+
declare class RabbitMqTransport extends SubscribingTransport {
|
|
360
462
|
#private;
|
|
361
463
|
readonly name: string;
|
|
464
|
+
readonly system = "rabbitmq";
|
|
362
465
|
constructor(options: RabbitMqTransportOptions);
|
|
363
466
|
/**
|
|
364
467
|
* True while the connection is open and publishing and consuming are set up.
|
|
@@ -381,6 +484,7 @@ declare class RabbitMqTransport implements Transport {
|
|
|
381
484
|
* @throws {RabbitMqUnavailableError} not connected, channel lost, or confirm timed out
|
|
382
485
|
* @throws {RabbitMqPublishRejectedError} the broker nacked the message
|
|
383
486
|
* @throws {UnroutableMessageError} no queue is bound to `destination` (unless `allowUnroutable`)
|
|
487
|
+
* @throws whatever the `codec`'s `encode` throws, such as {@link RabbitMqUnencodableEventError}
|
|
384
488
|
*/
|
|
385
489
|
publish(envelope: EventEnvelope, destination: string): Promise<void>;
|
|
386
490
|
/**
|
|
@@ -388,42 +492,14 @@ declare class RabbitMqTransport implements Transport {
|
|
|
388
492
|
* to `onMessage`. Call it once per transport; give each subscription its own
|
|
389
493
|
* transport instance, with its own `name` and `consumerGroup`.
|
|
390
494
|
*/
|
|
391
|
-
|
|
495
|
+
protected openSubscription({ destinations, onMessage, hooks, }: TransportSubscription): Promise<void>;
|
|
392
496
|
/**
|
|
393
497
|
* Stops consuming, waits up to `shutdownTimeout` for running handlers
|
|
394
498
|
* (messages still being retried go back to the queue), then closes the
|
|
395
|
-
* channels and the connection.
|
|
499
|
+
* channels and the connection. Once `options.signal` aborts (the bus shutdown deadline passed),
|
|
500
|
+
* the connection's socket is destroyed instead of waiting for the broker.
|
|
396
501
|
*/
|
|
397
|
-
close(): Promise<void>;
|
|
502
|
+
close(options?: CloseOptions): Promise<void>;
|
|
398
503
|
}
|
|
399
504
|
|
|
400
|
-
|
|
401
|
-
* Reads one header of an incoming message, for the `type`, `id`, `key` or
|
|
402
|
-
* `source` option of {@link plainJsonDecoder}. Header names are compared
|
|
403
|
-
* exactly (AMQP header names are case-sensitive). Returns undefined when the
|
|
404
|
-
* header is absent, so the decoder falls back to its default.
|
|
405
|
-
*
|
|
406
|
-
* ```ts
|
|
407
|
-
* plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })
|
|
408
|
-
* ```
|
|
409
|
-
*/
|
|
410
|
-
declare function fromHeader(name: string): (message: {
|
|
411
|
-
readonly headers: EventHeaders;
|
|
412
|
-
}) => string | undefined;
|
|
413
|
-
/**
|
|
414
|
-
* Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for
|
|
415
|
-
* the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A
|
|
416
|
-
* string is returned as is and a safe integer as its decimal text (numeric ids
|
|
417
|
-
* are common). Anything else returns undefined so the decoder falls back to its
|
|
418
|
-
* default: a missing field, and also a fraction or an integer beyond 2^53, which
|
|
419
|
-
* JSON parsing may already have rounded, so two different ids could collide.
|
|
420
|
-
*
|
|
421
|
-
* ```ts
|
|
422
|
-
* plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })
|
|
423
|
-
* ```
|
|
424
|
-
*/
|
|
425
|
-
declare function fromPayloadField(path: string): (message: {
|
|
426
|
-
readonly payload: unknown;
|
|
427
|
-
}) => string | undefined;
|
|
428
|
-
|
|
429
|
-
export { type AmqpChannel, type AmqpConfirmChannel, type AmqpConnection, AmqpLimitExceededError, type AmqpMessage, type AmqpMessageProperties, type AmqpPublishOptions, type BrokerConnectionSettings, type DecodedEvent, MalformedMessageError, type PlainJsonDecoderOptions, type PlainJsonMessage, type RabbitMqMessageDecoder, RabbitMqPublishRejectedError, RabbitMqTransport, type RabbitMqTransportOptions, RabbitMqUnavailableError, type ReconnectOptions, type RedeliveryOptions, UnroutableMessageError, UnserializablePayloadError, decodeCloudEvent, fromHeader, fromPayloadField, plainJsonDecoder };
|
|
505
|
+
export { type AmqpChannel, type AmqpConfirmChannel, type AmqpConnection, AmqpLimitExceededError, type AmqpMessage, type AmqpMessageProperties, type AmqpPublishOptions, type BrokerConnectionSettings, type DecodedEvent, type EncodedMessage, MalformedMessageError, type PlainJsonDecoderOptions, type PlainJsonMessage, type RabbitMqCodec, type RabbitMqJsonEnvelopeMapping, type RabbitMqMessageDecoder, RabbitMqPublishRejectedError, RabbitMqTransport, type RabbitMqTransportOptions, RabbitMqUnavailableError, RabbitMqUnencodableEventError, type ReconnectOptions, type RedeliveryOptions, UnroutableMessageError, UnserializablePayloadError, cloudEventsBinary, cloudEventsStructured, decodeCloudEvent, jsonEnvelope, plainJsonDecoder };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { NonRetryableError, RelayBusError, EventHeaders, EventEnvelope, RetryPolicyOptions, Duration, RelayBusLogger,
|
|
2
|
+
import { NonRetryableError, RelayBusError, EventHeaders, EventEnvelope, RetryPolicyOptions, Duration, RelayBusLogger, CloseOptions } from '@relaybus/core';
|
|
3
|
+
import { JsonEnvelopeMapping, SubscribingTransport, TransportSubscription } from '@relaybus/core/internal';
|
|
4
|
+
export { fromHeader, fromPayloadField } from '@relaybus/core/internal';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* The slice of amqplib this package relies on. Declaring it here keeps the
|
|
@@ -74,18 +76,26 @@ interface AmqpConnection extends EventEmitter {
|
|
|
74
76
|
* Always retryable; the outbox keeps the delivery and tries again.
|
|
75
77
|
*/
|
|
76
78
|
declare class RabbitMqUnavailableError extends RelayBusError {
|
|
79
|
+
name: string;
|
|
80
|
+
readonly code: string;
|
|
77
81
|
}
|
|
78
82
|
/** The broker negatively acknowledged a published message. Retryable. */
|
|
79
83
|
declare class RabbitMqPublishRejectedError extends RelayBusError {
|
|
84
|
+
name: string;
|
|
85
|
+
readonly code: string;
|
|
80
86
|
}
|
|
81
87
|
/**
|
|
82
88
|
* The broker accepted the message but no queue is bound to its routing key, so
|
|
83
89
|
* it would have been discarded. Retryable: it succeeds once a consumer binds.
|
|
84
90
|
*/
|
|
85
91
|
declare class UnroutableMessageError extends RelayBusError {
|
|
92
|
+
name: string;
|
|
93
|
+
readonly code: string;
|
|
86
94
|
}
|
|
87
95
|
/** A received message is not a valid relaybus CloudEvent. It is dead-lettered. */
|
|
88
96
|
declare class MalformedMessageError extends RelayBusError {
|
|
97
|
+
name: string;
|
|
98
|
+
readonly code: string;
|
|
89
99
|
}
|
|
90
100
|
/**
|
|
91
101
|
* The payload of an event cannot be represented as JSON without losing or
|
|
@@ -94,6 +104,7 @@ declare class MalformedMessageError extends RelayBusError {
|
|
|
94
104
|
*/
|
|
95
105
|
declare class UnserializablePayloadError extends NonRetryableError {
|
|
96
106
|
name: string;
|
|
107
|
+
readonly code: string;
|
|
97
108
|
}
|
|
98
109
|
/**
|
|
99
110
|
* A value exceeds a protocol limit of AMQP 0-9-1, for example an event id or a
|
|
@@ -101,6 +112,15 @@ declare class UnserializablePayloadError extends NonRetryableError {
|
|
|
101
112
|
*/
|
|
102
113
|
declare class AmqpLimitExceededError extends NonRetryableError {
|
|
103
114
|
name: string;
|
|
115
|
+
readonly code: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* An event the configured codec cannot write: a header name the format
|
|
119
|
+
* reserves, or a type a fixed-type route does not carry. Never retried.
|
|
120
|
+
*/
|
|
121
|
+
declare class RabbitMqUnencodableEventError extends NonRetryableError {
|
|
122
|
+
name: string;
|
|
123
|
+
readonly code: string;
|
|
104
124
|
}
|
|
105
125
|
|
|
106
126
|
/**
|
|
@@ -210,6 +230,73 @@ declare function decodeCloudEvent(message: AmqpMessage): EventEnvelope;
|
|
|
210
230
|
*/
|
|
211
231
|
declare function plainJsonDecoder(options: PlainJsonDecoderOptions): RabbitMqMessageDecoder;
|
|
212
232
|
|
|
233
|
+
/** A serialized event, ready for `channel.publish`. */
|
|
234
|
+
interface EncodedMessage {
|
|
235
|
+
readonly content: Buffer;
|
|
236
|
+
readonly options: AmqpPublishOptions;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The wire format of a {@link RabbitMqTransport}: how an event becomes a
|
|
241
|
+
* message (`encode`, on publish) and a consumed message becomes an event
|
|
242
|
+
* (`decode`).
|
|
243
|
+
*
|
|
244
|
+
* Both must be synchronous and free of side effects. What `encode` throws
|
|
245
|
+
* fails the publish: the outbox retries it, unless it is a `NonRetryableError`
|
|
246
|
+
* such as {@link RabbitMqUnencodableEventError}. Give every message a
|
|
247
|
+
* `messageId`: the transport matches broker returns of unroutable messages by
|
|
248
|
+
* it. What `decode` throws marks the message as malformed: it is
|
|
249
|
+
* dead-lettered and the consumer moves on. See {@link RabbitMqMessageDecoder}
|
|
250
|
+
* for the decode contract.
|
|
251
|
+
*/
|
|
252
|
+
interface RabbitMqCodec {
|
|
253
|
+
readonly encode: (envelope: EventEnvelope) => EncodedMessage;
|
|
254
|
+
readonly decode: RabbitMqMessageDecoder;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* CloudEvents 1.0 binary content mode, the default: the body is the JSON
|
|
258
|
+
* payload, the attributes travel as `cloudEvents:*` headers mirrored in the
|
|
259
|
+
* AMQP properties. Decoding is strict: any other message is malformed.
|
|
260
|
+
*/
|
|
261
|
+
declare const cloudEventsBinary: RabbitMqCodec;
|
|
262
|
+
/**
|
|
263
|
+
* CloudEvents 1.0 structured content mode: the body is one
|
|
264
|
+
* `application/cloudevents+json` document with the attributes and `data`.
|
|
265
|
+
* Decoding accepts structured and binary mode ({@link decodeCloudEvent}).
|
|
266
|
+
* Event headers travel under their own names; names starting with `x-death`,
|
|
267
|
+
* `x-first-death-`, `x-last-death-` or `x-relaybus-` are refused.
|
|
268
|
+
*/
|
|
269
|
+
declare const cloudEventsStructured: RabbitMqCodec;
|
|
270
|
+
/**
|
|
271
|
+
* Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides
|
|
272
|
+
* `{ body }` and `{ header }`, the id may be `'message-id-property'`: the
|
|
273
|
+
* AMQP `messageId` property, which the codec always writes and which survives
|
|
274
|
+
* redeliveries; a message without one is malformed.
|
|
275
|
+
*/
|
|
276
|
+
type RabbitMqJsonEnvelopeMapping = JsonEnvelopeMapping<'message-id-property'>;
|
|
277
|
+
/**
|
|
278
|
+
* A JSON wire format declared by a mapping, in both directions: for queues
|
|
279
|
+
* shared with services that wrap events in their own envelope
|
|
280
|
+
* (`{ "eventName": ..., "data": {...} }`, MassTransit) or send the bare
|
|
281
|
+
* payload. Every message also gets the AMQP properties of binary mode:
|
|
282
|
+
* `messageId` (the event id), `type`, `appId` (the source), `correlationId`,
|
|
283
|
+
* `timestamp` (seconds) and `persistent`. Event
|
|
284
|
+
* headers that are message headers are written as they are, so a name the
|
|
285
|
+
* mapping uses for another field, or one the broker reserves, is refused
|
|
286
|
+
* with {@link RabbitMqUnencodableEventError}.
|
|
287
|
+
*
|
|
288
|
+
* ```ts
|
|
289
|
+
* codec: jsonEnvelope({
|
|
290
|
+
* type: { body: 'eventName' },
|
|
291
|
+
* id: 'message-id-property',
|
|
292
|
+
* payload: { body: 'data' },
|
|
293
|
+
* })
|
|
294
|
+
* ```
|
|
295
|
+
*
|
|
296
|
+
* @throws ConfigurationError for an incomplete or self-overlapping mapping.
|
|
297
|
+
*/
|
|
298
|
+
declare function jsonEnvelope(mapping: RabbitMqJsonEnvelopeMapping): RabbitMqCodec;
|
|
299
|
+
|
|
213
300
|
/** Connection settings accepted by `amqplib.connect`, given as an object instead of a URL. */
|
|
214
301
|
interface BrokerConnectionSettings {
|
|
215
302
|
readonly protocol?: string;
|
|
@@ -246,9 +333,11 @@ interface RabbitMqTransportOptions {
|
|
|
246
333
|
readonly url?: string | BrokerConnectionSettings;
|
|
247
334
|
/**
|
|
248
335
|
* Opens one connection. Called again after every connection loss. Use it for
|
|
249
|
-
* TLS options, custom credentials or an alternative amqplib instance.
|
|
336
|
+
* TLS options, custom credentials or an alternative amqplib instance. `signal` aborts when a
|
|
337
|
+
* shutdown runs past its deadline: pass it on (`amqplib.connect(url, { signal })`) so a broker
|
|
338
|
+
* that never answers the handshake cannot hold the socket open.
|
|
250
339
|
*/
|
|
251
|
-
readonly connect?: () => Promise<AmqpConnection>;
|
|
340
|
+
readonly connect?: (options: ConnectOptions) => Promise<AmqpConnection>;
|
|
252
341
|
/** Topic exchange events are published to. Durable, created when missing. Default `'relaybus'`. */
|
|
253
342
|
readonly exchange?: string;
|
|
254
343
|
/**
|
|
@@ -317,22 +406,35 @@ interface RabbitMqTransportOptions {
|
|
|
317
406
|
/** How long `close` waits for running handlers. Default `'30s'`. */
|
|
318
407
|
readonly shutdownTimeout?: Duration;
|
|
319
408
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* Whatever
|
|
409
|
+
* The wire format, both ways: how events become messages and consumed
|
|
410
|
+
* messages become events. Default {@link cloudEventsBinary}: CloudEvents
|
|
411
|
+
* binary mode (`cloudEvents:*` headers, AMQP properties as fallback), any
|
|
412
|
+
* other message is malformed and dead-lettered. {@link cloudEventsStructured}
|
|
413
|
+
* writes structured mode and reads both, {@link jsonEnvelope} maps a JSON
|
|
414
|
+
* format of your own (an envelope with the payload inside, or the bare
|
|
415
|
+
* payload), and an object with `encode` and `decode` can do anything else.
|
|
416
|
+
* Whatever `decode` throws marks the message as malformed: it is
|
|
328
417
|
* dead-lettered, the consumer keeps running.
|
|
329
418
|
*/
|
|
419
|
+
readonly codec?: RabbitMqCodec;
|
|
420
|
+
/**
|
|
421
|
+
* How consumed messages become events; events are still written in
|
|
422
|
+
* CloudEvents binary mode.
|
|
423
|
+
*
|
|
424
|
+
* @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.
|
|
425
|
+
* Giving both `decode` and `codec` is a configuration error.
|
|
426
|
+
*/
|
|
330
427
|
readonly decode?: RabbitMqMessageDecoder;
|
|
331
428
|
/** Default: `console`. */
|
|
332
429
|
readonly logger?: RelayBusLogger;
|
|
333
430
|
/** Random source for jitter. Default `Math.random`. Intended for tests. */
|
|
334
431
|
readonly random?: () => number;
|
|
335
432
|
}
|
|
433
|
+
/** What `connect` gets for each connection it opens. */
|
|
434
|
+
interface ConnectOptions {
|
|
435
|
+
/** Aborted when a shutdown runs past its deadline; destroys a socket still connecting. */
|
|
436
|
+
readonly signal: AbortSignal;
|
|
437
|
+
}
|
|
336
438
|
|
|
337
439
|
/**
|
|
338
440
|
* RabbitMQ {@link Transport} built on amqplib.
|
|
@@ -356,9 +458,10 @@ interface RabbitMqTransportOptions {
|
|
|
356
458
|
* consumer. Events published meanwhile are rejected, and therefore retried by
|
|
357
459
|
* the outbox, rather than buffered in memory.
|
|
358
460
|
*/
|
|
359
|
-
declare class RabbitMqTransport
|
|
461
|
+
declare class RabbitMqTransport extends SubscribingTransport {
|
|
360
462
|
#private;
|
|
361
463
|
readonly name: string;
|
|
464
|
+
readonly system = "rabbitmq";
|
|
362
465
|
constructor(options: RabbitMqTransportOptions);
|
|
363
466
|
/**
|
|
364
467
|
* True while the connection is open and publishing and consuming are set up.
|
|
@@ -381,6 +484,7 @@ declare class RabbitMqTransport implements Transport {
|
|
|
381
484
|
* @throws {RabbitMqUnavailableError} not connected, channel lost, or confirm timed out
|
|
382
485
|
* @throws {RabbitMqPublishRejectedError} the broker nacked the message
|
|
383
486
|
* @throws {UnroutableMessageError} no queue is bound to `destination` (unless `allowUnroutable`)
|
|
487
|
+
* @throws whatever the `codec`'s `encode` throws, such as {@link RabbitMqUnencodableEventError}
|
|
384
488
|
*/
|
|
385
489
|
publish(envelope: EventEnvelope, destination: string): Promise<void>;
|
|
386
490
|
/**
|
|
@@ -388,42 +492,14 @@ declare class RabbitMqTransport implements Transport {
|
|
|
388
492
|
* to `onMessage`. Call it once per transport; give each subscription its own
|
|
389
493
|
* transport instance, with its own `name` and `consumerGroup`.
|
|
390
494
|
*/
|
|
391
|
-
|
|
495
|
+
protected openSubscription({ destinations, onMessage, hooks, }: TransportSubscription): Promise<void>;
|
|
392
496
|
/**
|
|
393
497
|
* Stops consuming, waits up to `shutdownTimeout` for running handlers
|
|
394
498
|
* (messages still being retried go back to the queue), then closes the
|
|
395
|
-
* channels and the connection.
|
|
499
|
+
* channels and the connection. Once `options.signal` aborts (the bus shutdown deadline passed),
|
|
500
|
+
* the connection's socket is destroyed instead of waiting for the broker.
|
|
396
501
|
*/
|
|
397
|
-
close(): Promise<void>;
|
|
502
|
+
close(options?: CloseOptions): Promise<void>;
|
|
398
503
|
}
|
|
399
504
|
|
|
400
|
-
|
|
401
|
-
* Reads one header of an incoming message, for the `type`, `id`, `key` or
|
|
402
|
-
* `source` option of {@link plainJsonDecoder}. Header names are compared
|
|
403
|
-
* exactly (AMQP header names are case-sensitive). Returns undefined when the
|
|
404
|
-
* header is absent, so the decoder falls back to its default.
|
|
405
|
-
*
|
|
406
|
-
* ```ts
|
|
407
|
-
* plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })
|
|
408
|
-
* ```
|
|
409
|
-
*/
|
|
410
|
-
declare function fromHeader(name: string): (message: {
|
|
411
|
-
readonly headers: EventHeaders;
|
|
412
|
-
}) => string | undefined;
|
|
413
|
-
/**
|
|
414
|
-
* Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for
|
|
415
|
-
* the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A
|
|
416
|
-
* string is returned as is and a safe integer as its decimal text (numeric ids
|
|
417
|
-
* are common). Anything else returns undefined so the decoder falls back to its
|
|
418
|
-
* default: a missing field, and also a fraction or an integer beyond 2^53, which
|
|
419
|
-
* JSON parsing may already have rounded, so two different ids could collide.
|
|
420
|
-
*
|
|
421
|
-
* ```ts
|
|
422
|
-
* plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })
|
|
423
|
-
* ```
|
|
424
|
-
*/
|
|
425
|
-
declare function fromPayloadField(path: string): (message: {
|
|
426
|
-
readonly payload: unknown;
|
|
427
|
-
}) => string | undefined;
|
|
428
|
-
|
|
429
|
-
export { type AmqpChannel, type AmqpConfirmChannel, type AmqpConnection, AmqpLimitExceededError, type AmqpMessage, type AmqpMessageProperties, type AmqpPublishOptions, type BrokerConnectionSettings, type DecodedEvent, MalformedMessageError, type PlainJsonDecoderOptions, type PlainJsonMessage, type RabbitMqMessageDecoder, RabbitMqPublishRejectedError, RabbitMqTransport, type RabbitMqTransportOptions, RabbitMqUnavailableError, type ReconnectOptions, type RedeliveryOptions, UnroutableMessageError, UnserializablePayloadError, decodeCloudEvent, fromHeader, fromPayloadField, plainJsonDecoder };
|
|
505
|
+
export { type AmqpChannel, type AmqpConfirmChannel, type AmqpConnection, AmqpLimitExceededError, type AmqpMessage, type AmqpMessageProperties, type AmqpPublishOptions, type BrokerConnectionSettings, type DecodedEvent, type EncodedMessage, MalformedMessageError, type PlainJsonDecoderOptions, type PlainJsonMessage, type RabbitMqCodec, type RabbitMqJsonEnvelopeMapping, type RabbitMqMessageDecoder, RabbitMqPublishRejectedError, RabbitMqTransport, type RabbitMqTransportOptions, RabbitMqUnavailableError, RabbitMqUnencodableEventError, type ReconnectOptions, type RedeliveryOptions, UnroutableMessageError, UnserializablePayloadError, cloudEventsBinary, cloudEventsStructured, decodeCloudEvent, jsonEnvelope, plainJsonDecoder };
|