@horizon-republic/nestjs-jetstream 2.9.0 → 2.10.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 +15 -2
- package/dist/index.cjs +2016 -441
- package/dist/index.d.cts +803 -389
- package/dist/index.d.ts +803 -389
- package/dist/index.js +1998 -426
- package/package.json +35 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { ModuleMetadata, FactoryProvider, Type,
|
|
2
|
-
import { MsgHdrs,
|
|
3
|
-
import { StreamConfig, ConsumerConfig, ConsumeOptions, DeliverPolicy, ReplayPolicy,
|
|
4
|
-
import {
|
|
1
|
+
import { Logger, ModuleMetadata, FactoryProvider, Type, OnApplicationShutdown, DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { MsgHdrs, NatsConnection, Status, ConnectionOptions, Msg } from '@nats-io/transport-node';
|
|
3
|
+
import { JetStreamManager, JetStreamClient, StreamConfig, ConsumerConfig, ConsumeOptions, DeliverPolicy, ReplayPolicy, ConsumerInfo, JsMsg } from '@nats-io/jetstream';
|
|
4
|
+
import { Span } from '@opentelemetry/api';
|
|
5
|
+
import { ClientProxy, ReadPacket, WritePacket, MessageHandler, Server, CustomTransportStrategy, BaseRpcContext } from '@nestjs/microservices';
|
|
5
6
|
import { Observable } from 'rxjs';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -117,6 +118,689 @@ interface JetstreamHealthStatus {
|
|
|
117
118
|
latency: number | null;
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Instrumentation scope name reported on every span the library emits.
|
|
123
|
+
* Matches the npm package name — the convention used by
|
|
124
|
+
* `@opentelemetry/instrumentation-*` and most third-party instrumentations.
|
|
125
|
+
*/
|
|
126
|
+
declare const TRACER_NAME = "@horizon-republic/nestjs-jetstream";
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Enumeration of OpenTelemetry trace kinds this library can emit.
|
|
130
|
+
*
|
|
131
|
+
* Each identifier is toggleable via `otel.traces`. Functional kinds (publish,
|
|
132
|
+
* consume, RPC client round-trip, dead letter) are enabled by default;
|
|
133
|
+
* infrastructure kinds (connection lifecycle, self-healing, provisioning,
|
|
134
|
+
* migration, shutdown) are opt-in.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* JetstreamModule.forRoot({
|
|
138
|
+
* otel: {
|
|
139
|
+
* traces: [JetstreamTrace.Publish, JetstreamTrace.Consume, JetstreamTrace.ConnectionLifecycle],
|
|
140
|
+
* },
|
|
141
|
+
* })
|
|
142
|
+
*/
|
|
143
|
+
declare enum JetstreamTrace {
|
|
144
|
+
/** `PRODUCER` span around each `emit()` / `send()` publish operation. Default: ON. */
|
|
145
|
+
Publish = "publish",
|
|
146
|
+
/**
|
|
147
|
+
* `CONSUMER` span around each message delivery to a handler. Retries
|
|
148
|
+
* produce separate spans with `messaging.nats.message.delivery_count > 1`.
|
|
149
|
+
* Default: ON.
|
|
150
|
+
*/
|
|
151
|
+
Consume = "consume",
|
|
152
|
+
/**
|
|
153
|
+
* `CLIENT` span covering a full RPC round-trip on the caller side
|
|
154
|
+
* (`client.send()` → reply received). Wraps the inner publish.
|
|
155
|
+
* Default: ON.
|
|
156
|
+
*/
|
|
157
|
+
RpcClientSend = "rpc.client.send",
|
|
158
|
+
/**
|
|
159
|
+
* `INTERNAL` span emitted when a message exhausts `maxDeliver` and is
|
|
160
|
+
* dead-lettered. Captures the duration of the `onDeadLetter` callback.
|
|
161
|
+
* Default: ON.
|
|
162
|
+
*/
|
|
163
|
+
DeadLetter = "dead_letter",
|
|
164
|
+
/**
|
|
165
|
+
* `INTERNAL` span spanning one NATS connection session. Emits events on
|
|
166
|
+
* connect, reconnect, disconnect. Default: OFF.
|
|
167
|
+
*/
|
|
168
|
+
ConnectionLifecycle = "connection.lifecycle",
|
|
169
|
+
/**
|
|
170
|
+
* `INTERNAL` span per consumer recovery attempt following a transient
|
|
171
|
+
* failure (deleted consumer, missed heartbeat). Default: OFF.
|
|
172
|
+
*/
|
|
173
|
+
SelfHealing = "self_healing",
|
|
174
|
+
/** `INTERNAL` span per stream or consumer provisioning / update at startup. Default: OFF. */
|
|
175
|
+
Provisioning = "provisioning",
|
|
176
|
+
/** `INTERNAL` span covering a destructive migration flow. Default: OFF. */
|
|
177
|
+
Migration = "migration",
|
|
178
|
+
/** `INTERNAL` span covering the graceful shutdown sequence. Default: OFF. */
|
|
179
|
+
Shutdown = "shutdown"
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The set of trace kinds enabled when `otel.traces` is not configured
|
|
183
|
+
* (or set to `'default'`). Covers message-flow operations; infrastructure
|
|
184
|
+
* spans are opt-in.
|
|
185
|
+
*/
|
|
186
|
+
declare const DEFAULT_TRACES: readonly JetstreamTrace[];
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Central event bus for transport lifecycle notifications.
|
|
190
|
+
*
|
|
191
|
+
* Dispatches events to user-provided hooks. Events without a
|
|
192
|
+
* registered hook are silently ignored — no default logging.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const bus = new EventBus(logger, {
|
|
197
|
+
* [TransportEvent.Error]: (err) => sentry.captureException(err),
|
|
198
|
+
* });
|
|
199
|
+
*
|
|
200
|
+
* bus.emit(TransportEvent.Error, new Error('timeout'), 'rpc-router');
|
|
201
|
+
* // → calls sentry
|
|
202
|
+
*
|
|
203
|
+
* bus.emit(TransportEvent.Connect, 'nats://localhost:4222');
|
|
204
|
+
* // → no-op (no hook registered)
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
declare class EventBus {
|
|
208
|
+
private readonly hooks;
|
|
209
|
+
private readonly logger;
|
|
210
|
+
constructor(logger: Logger, hooks?: Partial<TransportHooks>);
|
|
211
|
+
/**
|
|
212
|
+
* Emit a lifecycle event. Dispatches to custom hook if registered, otherwise no-op.
|
|
213
|
+
*
|
|
214
|
+
* @param event - The {@link TransportEvent} to emit.
|
|
215
|
+
* @param args - Arguments matching the hook signature for this event.
|
|
216
|
+
*/
|
|
217
|
+
emit<K extends keyof TransportHooks>(event: K, ...args: Parameters<TransportHooks[K]>): void;
|
|
218
|
+
/**
|
|
219
|
+
* Hot-path optimized emit for MessageRouted events.
|
|
220
|
+
* Avoids rest/spread overhead of the generic `emit()`.
|
|
221
|
+
*/
|
|
222
|
+
emitMessageRouted(subject: string, kind: MessageKind): void;
|
|
223
|
+
/**
|
|
224
|
+
* Check whether a hook is registered for the given event.
|
|
225
|
+
*
|
|
226
|
+
* Used by the routing hot path to elide the emit call entirely when the
|
|
227
|
+
* transport owner did not register a listener.
|
|
228
|
+
*/
|
|
229
|
+
hasHook(event: keyof TransportHooks): boolean;
|
|
230
|
+
private callHook;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Manages the lifecycle of a single NATS connection shared across the application.
|
|
235
|
+
*
|
|
236
|
+
* Provides both Promise-based and Observable-based access to the connection:
|
|
237
|
+
* - `connect()` / `getConnection()` — async/await for one-time setup
|
|
238
|
+
* - `nc$` — cached observable (shareReplay) for reactive consumers
|
|
239
|
+
* - `status$` — live connection status event stream
|
|
240
|
+
*
|
|
241
|
+
* One instance per application, created by `JetstreamModule.forRoot()`.
|
|
242
|
+
*/
|
|
243
|
+
declare class ConnectionProvider {
|
|
244
|
+
private readonly options;
|
|
245
|
+
private readonly eventBus;
|
|
246
|
+
/** Cached observable that replays the established connection to new subscribers. */
|
|
247
|
+
readonly nc$: Observable<NatsConnection>;
|
|
248
|
+
/** Live stream of connection status events (no replay). */
|
|
249
|
+
readonly status$: Observable<Status>;
|
|
250
|
+
private readonly logger;
|
|
251
|
+
private connection;
|
|
252
|
+
private connectionPromise;
|
|
253
|
+
private jsClient;
|
|
254
|
+
private jsmInstance;
|
|
255
|
+
private jsmPromise;
|
|
256
|
+
private readonly otel;
|
|
257
|
+
private readonly otelServiceName;
|
|
258
|
+
private readonly otelEndpoint;
|
|
259
|
+
private lifecycleSpan;
|
|
260
|
+
constructor(options: JetstreamModuleOptions, eventBus: EventBus);
|
|
261
|
+
/**
|
|
262
|
+
* Establish NATS connection. Idempotent — returns cached connection on subsequent calls.
|
|
263
|
+
*
|
|
264
|
+
* @throws Error if connection is refused (fail fast).
|
|
265
|
+
*/
|
|
266
|
+
getConnection(): Promise<NatsConnection>;
|
|
267
|
+
/**
|
|
268
|
+
* Get the JetStream manager. Cached after first call.
|
|
269
|
+
*
|
|
270
|
+
* @returns The JetStreamManager for stream/consumer administration.
|
|
271
|
+
*/
|
|
272
|
+
getJetStreamManager(): Promise<JetStreamManager>;
|
|
273
|
+
/**
|
|
274
|
+
* Get a cached JetStream client.
|
|
275
|
+
*
|
|
276
|
+
* Invalidated automatically on reconnect and shutdown so consumers always
|
|
277
|
+
* operate against the live connection.
|
|
278
|
+
*
|
|
279
|
+
* @returns The cached JetStreamClient.
|
|
280
|
+
* @throws Error if the connection has not been established yet.
|
|
281
|
+
*/
|
|
282
|
+
getJetStreamClient(): JetStreamClient;
|
|
283
|
+
/** Direct access to the raw NATS connection, or `null` if not yet connected. */
|
|
284
|
+
get unwrap(): NatsConnection | null;
|
|
285
|
+
/**
|
|
286
|
+
* Gracefully shut down the connection.
|
|
287
|
+
*
|
|
288
|
+
* Sequence: drain → wait for close. Falls back to force-close on error.
|
|
289
|
+
*/
|
|
290
|
+
shutdown(): Promise<void>;
|
|
291
|
+
private initJetStreamManager;
|
|
292
|
+
/** Internal: establish the physical connection with reconnect monitoring. */
|
|
293
|
+
private establish;
|
|
294
|
+
/** Handle a single `nc.status()` event, emitting hooks and span events. */
|
|
295
|
+
private handleStatusEvent;
|
|
296
|
+
/** Subscribe to connection status events and emit hooks. */
|
|
297
|
+
private monitorStatus;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* NestJS ClientProxy implementation for the JetStream transport.
|
|
302
|
+
*
|
|
303
|
+
* Supports two operational modes:
|
|
304
|
+
* - **Core mode** (default): Uses `nc.request()` for RPC, `nc.publish()` for events.
|
|
305
|
+
* - **JetStream mode**: Uses `js.publish()` for RPC commands + inbox for responses.
|
|
306
|
+
*
|
|
307
|
+
* Events always go through JetStream publish for guaranteed delivery.
|
|
308
|
+
* The mode only affects RPC (request/reply) behavior.
|
|
309
|
+
*
|
|
310
|
+
* Clients are lightweight — they share the NATS connection from `forRoot()`.
|
|
311
|
+
*/
|
|
312
|
+
declare class JetstreamClient extends ClientProxy {
|
|
313
|
+
private readonly rootOptions;
|
|
314
|
+
private readonly connection;
|
|
315
|
+
private readonly codec;
|
|
316
|
+
private readonly eventBus;
|
|
317
|
+
private readonly logger;
|
|
318
|
+
/** Target service name this client sends messages to. */
|
|
319
|
+
private readonly targetName;
|
|
320
|
+
/** Pre-cached caller name derived from rootOptions.name, computed once in constructor. */
|
|
321
|
+
private readonly callerName;
|
|
322
|
+
/**
|
|
323
|
+
* Subject prefixes of the form `{serviceName}__microservice.{kind}.` — one
|
|
324
|
+
* per stream kind this client may publish to. Built once in the constructor
|
|
325
|
+
* so producing a full subject is a single string concat with the user pattern.
|
|
326
|
+
*/
|
|
327
|
+
private readonly eventSubjectPrefix;
|
|
328
|
+
private readonly commandSubjectPrefix;
|
|
329
|
+
private readonly orderedSubjectPrefix;
|
|
330
|
+
/**
|
|
331
|
+
* RPC configuration snapshots. The values are derived from rootOptions at
|
|
332
|
+
* construction time so the publish hot path never has to re-run
|
|
333
|
+
* isCoreRpcMode / getRpcTimeout on every call.
|
|
334
|
+
*/
|
|
335
|
+
private readonly isCoreMode;
|
|
336
|
+
private readonly defaultRpcTimeout;
|
|
337
|
+
/** Resolved OpenTelemetry configuration, computed once in the constructor. */
|
|
338
|
+
private readonly otel;
|
|
339
|
+
/** Server endpoint parts used for `server.address` / `server.port` span attributes. */
|
|
340
|
+
private readonly serverEndpoint;
|
|
341
|
+
/** Shared inbox for JetStream-mode RPC responses. */
|
|
342
|
+
private inbox;
|
|
343
|
+
private inboxSubscription;
|
|
344
|
+
/** Pending JetStream-mode RPC callbacks, keyed by correlation ID. */
|
|
345
|
+
private readonly pendingMessages;
|
|
346
|
+
/** Pending JetStream-mode RPC timeouts, keyed by correlation ID. */
|
|
347
|
+
private readonly pendingTimeouts;
|
|
348
|
+
/** Subscription to connection status events for disconnect handling. */
|
|
349
|
+
private statusSubscription;
|
|
350
|
+
/**
|
|
351
|
+
* Cached readiness flag. Once `connect()` has wired the inbox and status
|
|
352
|
+
* subscription, subsequent publishes skip the `await connect()` microtask
|
|
353
|
+
* and reach for the underlying connection synchronously instead.
|
|
354
|
+
*/
|
|
355
|
+
private readyForPublish;
|
|
356
|
+
constructor(rootOptions: JetstreamModuleOptions, targetServiceName: string, connection: ConnectionProvider, codec: Codec, eventBus: EventBus);
|
|
357
|
+
/**
|
|
358
|
+
* Establish connection. Called automatically by NestJS on first use.
|
|
359
|
+
*
|
|
360
|
+
* Sets up the JetStream RPC inbox (if in JetStream mode) and subscribes
|
|
361
|
+
* to connection status events for fail-fast disconnect handling.
|
|
362
|
+
*
|
|
363
|
+
* @returns The underlying NATS connection.
|
|
364
|
+
*/
|
|
365
|
+
connect(): Promise<NatsConnection>;
|
|
366
|
+
/** Clean up resources: reject pending RPCs, unsubscribe from status events. */
|
|
367
|
+
close(): Promise<void>;
|
|
368
|
+
/**
|
|
369
|
+
* Direct access to the raw NATS connection.
|
|
370
|
+
*
|
|
371
|
+
* @throws Error if not connected.
|
|
372
|
+
*/
|
|
373
|
+
unwrap<T = NatsConnection>(): T;
|
|
374
|
+
/**
|
|
375
|
+
* Publish a fire-and-forget event to JetStream.
|
|
376
|
+
*
|
|
377
|
+
* Events are published to either the workqueue stream or broadcast stream
|
|
378
|
+
* depending on the subject prefix. When a schedule is present the message
|
|
379
|
+
* is published to a `_sch` subject within the same stream, with the target
|
|
380
|
+
* set to the original event subject.
|
|
381
|
+
*/
|
|
382
|
+
protected dispatchEvent<T = unknown>(packet: ReadPacket): Promise<T>;
|
|
383
|
+
/**
|
|
384
|
+
* Publish an RPC command and register callback for response.
|
|
385
|
+
*
|
|
386
|
+
* Core mode: uses nc.request() with timeout.
|
|
387
|
+
* JetStream mode: publishes to stream + waits for inbox response.
|
|
388
|
+
*/
|
|
389
|
+
protected publish(packet: ReadPacket, callback: (p: WritePacket) => void): () => void;
|
|
390
|
+
/** Core mode: nc.request() with timeout. */
|
|
391
|
+
private publishCoreRpc;
|
|
392
|
+
/** JetStream mode: publish to stream + wait for inbox response. */
|
|
393
|
+
private publishJetStreamRpc;
|
|
394
|
+
/** Fail-fast all pending JetStream RPC callbacks on connection loss. */
|
|
395
|
+
private handleDisconnect;
|
|
396
|
+
/** Reject all pending RPC callbacks, clear timeouts, and tear down inbox. */
|
|
397
|
+
private rejectPendingRpcs;
|
|
398
|
+
/** Setup shared inbox subscription for JetStream RPC responses. */
|
|
399
|
+
private setupInbox;
|
|
400
|
+
/** Route an inbox reply to the matching pending callback. */
|
|
401
|
+
private routeInboxReply;
|
|
402
|
+
/**
|
|
403
|
+
* Resolve a user pattern to a fully-qualified NATS subject, dispatching
|
|
404
|
+
* between the event, broadcast, and ordered prefixes.
|
|
405
|
+
*
|
|
406
|
+
* The leading-char check short-circuits the `startsWith` comparisons for
|
|
407
|
+
* patterns that cannot possibly carry a broadcast/ordered marker, which is
|
|
408
|
+
* the overwhelmingly common case.
|
|
409
|
+
*/
|
|
410
|
+
private buildEventSubject;
|
|
411
|
+
/** Build NATS headers merging custom headers with transport headers. */
|
|
412
|
+
private buildHeaders;
|
|
413
|
+
/** Extract data, headers, timeout, and schedule from raw packet data or JetstreamRecord. */
|
|
414
|
+
private extractRecordData;
|
|
415
|
+
/**
|
|
416
|
+
* Build a schedule-holder subject for NATS message scheduling.
|
|
417
|
+
*
|
|
418
|
+
* The schedule-holder subject resides in the same stream as the target but
|
|
419
|
+
* uses a separate `_sch` namespace that is NOT matched by any consumer filter.
|
|
420
|
+
* NATS holds the message and publishes it to the target subject after the delay.
|
|
421
|
+
*
|
|
422
|
+
* Examples:
|
|
423
|
+
* - `{svc}__microservice.ev.order.reminder` → `{svc}__microservice._sch.order.reminder`
|
|
424
|
+
* - `broadcast.config.updated` → `broadcast._sch.config.updated`
|
|
425
|
+
*/
|
|
426
|
+
private buildScheduleSubject;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Immutable message record for JetStream transport.
|
|
431
|
+
*
|
|
432
|
+
* Compatible with NestJS record builder pattern (like RmqRecord, NatsRecord).
|
|
433
|
+
* Pass as the second argument to `client.send()` or `client.emit()`.
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```typescript
|
|
437
|
+
* const record = new JetstreamRecordBuilder({ id: 1 })
|
|
438
|
+
* .setHeader('x-tenant', 'acme')
|
|
439
|
+
* .setTimeout(5000)
|
|
440
|
+
* .build();
|
|
441
|
+
*
|
|
442
|
+
* client.send('get.user', record);
|
|
443
|
+
* ```
|
|
444
|
+
*/
|
|
445
|
+
declare class JetstreamRecord<TData = unknown> {
|
|
446
|
+
/** Message payload. */
|
|
447
|
+
readonly data: TData;
|
|
448
|
+
/** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
|
|
449
|
+
readonly headers: ReadonlyMap<string, string>;
|
|
450
|
+
/** Per-request RPC timeout override in ms. */
|
|
451
|
+
readonly timeout?: number | undefined;
|
|
452
|
+
/** Custom message ID for JetStream deduplication. */
|
|
453
|
+
readonly messageId?: string | undefined;
|
|
454
|
+
/** Schedule options for delayed delivery. */
|
|
455
|
+
readonly schedule?: ScheduleRecordOptions | undefined;
|
|
456
|
+
/** Per-message TTL as Go duration string (e.g. "30s", "5m"). */
|
|
457
|
+
readonly ttl?: string | undefined;
|
|
458
|
+
constructor(
|
|
459
|
+
/** Message payload. */
|
|
460
|
+
data: TData,
|
|
461
|
+
/** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
|
|
462
|
+
headers: ReadonlyMap<string, string>,
|
|
463
|
+
/** Per-request RPC timeout override in ms. */
|
|
464
|
+
timeout?: number | undefined,
|
|
465
|
+
/** Custom message ID for JetStream deduplication. */
|
|
466
|
+
messageId?: string | undefined,
|
|
467
|
+
/** Schedule options for delayed delivery. */
|
|
468
|
+
schedule?: ScheduleRecordOptions | undefined,
|
|
469
|
+
/** Per-message TTL as Go duration string (e.g. "30s", "5m"). */
|
|
470
|
+
ttl?: string | undefined);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Fluent builder for constructing JetstreamRecord instances.
|
|
474
|
+
*
|
|
475
|
+
* Protected headers (`correlation-id`, `reply-to`, `error`) cannot be
|
|
476
|
+
* set by the user — attempting to do so throws an error at build time.
|
|
477
|
+
*/
|
|
478
|
+
declare class JetstreamRecordBuilder<TData = unknown> {
|
|
479
|
+
private data;
|
|
480
|
+
private readonly headers;
|
|
481
|
+
private timeout;
|
|
482
|
+
private messageId;
|
|
483
|
+
private scheduleOptions;
|
|
484
|
+
private ttlDuration;
|
|
485
|
+
constructor(data?: TData);
|
|
486
|
+
/**
|
|
487
|
+
* Set the message payload.
|
|
488
|
+
*
|
|
489
|
+
* @param data - Payload to serialize via the configured {@link Codec}.
|
|
490
|
+
*/
|
|
491
|
+
setData(data: TData): this;
|
|
492
|
+
/**
|
|
493
|
+
* Set a single custom header.
|
|
494
|
+
*
|
|
495
|
+
* @param key - Header name (e.g. `'x-tenant'`).
|
|
496
|
+
* @param value - Header value.
|
|
497
|
+
* @throws Error if the header name is reserved by the transport.
|
|
498
|
+
*/
|
|
499
|
+
setHeader(key: string, value: string): this;
|
|
500
|
+
/**
|
|
501
|
+
* Set multiple custom headers at once.
|
|
502
|
+
*
|
|
503
|
+
* @param headers - Key-value pairs to set as headers.
|
|
504
|
+
* @throws Error if any header name is reserved by the transport.
|
|
505
|
+
*/
|
|
506
|
+
setHeaders(headers: Record<string, string>): this;
|
|
507
|
+
/**
|
|
508
|
+
* Set a custom message ID for JetStream deduplication.
|
|
509
|
+
*
|
|
510
|
+
* NATS JetStream uses this ID to detect duplicate publishes within the
|
|
511
|
+
* stream's `duplicate_window`. If two messages with the same ID arrive
|
|
512
|
+
* within the window, the second is silently dropped.
|
|
513
|
+
*
|
|
514
|
+
* When not set, a random UUID is generated automatically.
|
|
515
|
+
*
|
|
516
|
+
* @param id - Unique message identifier (e.g. order ID, idempotency key).
|
|
517
|
+
*
|
|
518
|
+
* @example
|
|
519
|
+
* ```typescript
|
|
520
|
+
* new JetstreamRecordBuilder(data)
|
|
521
|
+
* .setMessageId(`order-${order.id}`)
|
|
522
|
+
* .build();
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
setMessageId(id: string): this;
|
|
526
|
+
/**
|
|
527
|
+
* Set per-request RPC timeout.
|
|
528
|
+
*
|
|
529
|
+
* @param ms - Timeout in milliseconds. Overrides the global RPC timeout for this request only.
|
|
530
|
+
*/
|
|
531
|
+
setTimeout(ms: number): this;
|
|
532
|
+
/**
|
|
533
|
+
* Schedule one-shot delayed delivery.
|
|
534
|
+
*
|
|
535
|
+
* The message is held by NATS and delivered to the event consumer
|
|
536
|
+
* at the specified time. Requires NATS >= 2.12 and `allow_msg_schedules: true`
|
|
537
|
+
* on the event stream (via `events: { stream: { allow_msg_schedules: true } }`).
|
|
538
|
+
*
|
|
539
|
+
* Only meaningful for events (`client.emit()`). If used with RPC
|
|
540
|
+
* (`client.send()`), a warning is logged and the schedule is ignored.
|
|
541
|
+
*
|
|
542
|
+
* @param date - Delivery time. Must be in the future.
|
|
543
|
+
* @throws Error if the date is not in the future.
|
|
544
|
+
*/
|
|
545
|
+
scheduleAt(date: Date): this;
|
|
546
|
+
/**
|
|
547
|
+
* Set per-message TTL (time-to-live).
|
|
548
|
+
*
|
|
549
|
+
* The message expires individually after the specified duration,
|
|
550
|
+
* independent of the stream's `max_age`. Requires NATS >= 2.11 and
|
|
551
|
+
* `allow_msg_ttl: true` on the stream.
|
|
552
|
+
*
|
|
553
|
+
* Only meaningful for events (`client.emit()`). If used with RPC
|
|
554
|
+
* (`client.send()`), a warning is logged and the TTL is ignored.
|
|
555
|
+
*
|
|
556
|
+
* @param nanos - TTL in nanoseconds. Use {@link toNanos} for human-readable values.
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```typescript
|
|
560
|
+
* import { toNanos } from '@horizon-republic/nestjs-jetstream';
|
|
561
|
+
*
|
|
562
|
+
* new JetstreamRecordBuilder(payload).ttl(toNanos(30, 'minutes')).build();
|
|
563
|
+
* new JetstreamRecordBuilder(payload).ttl(toNanos(24, 'hours')).build();
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
566
|
+
ttl(nanos: number): this;
|
|
567
|
+
/**
|
|
568
|
+
* Build the immutable {@link JetstreamRecord}.
|
|
569
|
+
*
|
|
570
|
+
* @returns A frozen record ready to pass to `client.send()` or `client.emit()`.
|
|
571
|
+
*/
|
|
572
|
+
build(): JetstreamRecord<TData>;
|
|
573
|
+
/**
|
|
574
|
+
* Validate that a header key is not reserved. NATS treats header names
|
|
575
|
+
* case-insensitively, so the check is against the lowercase form to keep
|
|
576
|
+
* `'X-Correlation-ID'`, `'x-correlation-id'`, and any other casing in
|
|
577
|
+
* lockstep. `RESERVED_HEADERS` is defined as an all-lowercase set.
|
|
578
|
+
*/
|
|
579
|
+
private validateHeaderKey;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/** Tag attached to every outgoing publish span so consumers can distinguish event / RPC / broadcast / ordered flows. */
|
|
583
|
+
declare enum PublishKind {
|
|
584
|
+
Event = "event",
|
|
585
|
+
RpcRequest = "rpc.request",
|
|
586
|
+
Broadcast = "broadcast",
|
|
587
|
+
Ordered = "ordered"
|
|
588
|
+
}
|
|
589
|
+
/** Tag attached to every incoming consume span. `Rpc` covers both Core and JetStream RPC handlers. */
|
|
590
|
+
declare enum ConsumeKind {
|
|
591
|
+
Event = "event",
|
|
592
|
+
Rpc = "rpc",
|
|
593
|
+
Broadcast = "broadcast",
|
|
594
|
+
Ordered = "ordered"
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Handler metadata for the dispatched message. `pattern` is always set;
|
|
598
|
+
* `className` / `methodName` come from NestJS reflection when available.
|
|
599
|
+
*/
|
|
600
|
+
interface HandlerMetadata {
|
|
601
|
+
readonly pattern: string;
|
|
602
|
+
readonly className?: string;
|
|
603
|
+
readonly methodName?: string;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Host / port pair surfaced as `server.address` / `server.port` span
|
|
607
|
+
* attributes. `port` is optional — OTel semconv makes it conditional on
|
|
608
|
+
* being different from the protocol default, and we'd rather emit nothing
|
|
609
|
+
* than invent a number the user never configured.
|
|
610
|
+
*/
|
|
611
|
+
interface ServerEndpoint {
|
|
612
|
+
readonly host: string;
|
|
613
|
+
readonly port?: number;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Minimum message shape the consume span helper requires. Both `JsMsg`
|
|
617
|
+
* (JetStream) and Core NATS `Msg` satisfy it structurally; JetStream-only
|
|
618
|
+
* delivery metadata (`info`) is read separately and omitted on the Core
|
|
619
|
+
* RPC path.
|
|
620
|
+
*/
|
|
621
|
+
interface ConsumeSourceMsg {
|
|
622
|
+
readonly subject: string;
|
|
623
|
+
readonly data: Uint8Array;
|
|
624
|
+
readonly headers?: MsgHdrs;
|
|
625
|
+
}
|
|
626
|
+
/** Context passed to {@link OtelOptions.publishHook} for an outgoing publish. */
|
|
627
|
+
interface JetstreamPublishContext {
|
|
628
|
+
/** Fully-resolved subject the message is being published to. */
|
|
629
|
+
readonly subject: string;
|
|
630
|
+
/** The record being published (payload, headers, builder-supplied options). */
|
|
631
|
+
readonly record: JetstreamRecord;
|
|
632
|
+
/** Classification of the outgoing operation. */
|
|
633
|
+
readonly kind: PublishKind;
|
|
634
|
+
}
|
|
635
|
+
/** Context passed to {@link OtelOptions.consumeHook} for an incoming dispatch. */
|
|
636
|
+
interface JetstreamConsumeContext {
|
|
637
|
+
/** Fully-resolved subject of the incoming message. */
|
|
638
|
+
readonly subject: string;
|
|
639
|
+
/**
|
|
640
|
+
* The incoming NATS message. JetStream messages (events, broadcast,
|
|
641
|
+
* ordered, JetStream RPC) satisfy `JsMsg`; Core RPC messages satisfy
|
|
642
|
+
* the looser {@link ConsumeSourceMsg} shape only. Narrow on `kind` to
|
|
643
|
+
* decide which fields are safe to access.
|
|
644
|
+
*/
|
|
645
|
+
readonly msg: ConsumeSourceMsg;
|
|
646
|
+
/** Handler metadata; see {@link HandlerMetadata}. */
|
|
647
|
+
readonly handlerMetadata: HandlerMetadata;
|
|
648
|
+
/** Classification of the incoming operation. */
|
|
649
|
+
readonly kind: ConsumeKind;
|
|
650
|
+
}
|
|
651
|
+
/** Context passed to {@link OtelOptions.responseHook} once an outcome is known, just before the span ends. */
|
|
652
|
+
interface JetstreamResponseContext {
|
|
653
|
+
/** Subject the operation targeted. */
|
|
654
|
+
readonly subject: string;
|
|
655
|
+
/** Wall-clock duration of the operation in milliseconds. */
|
|
656
|
+
readonly durationMs: number;
|
|
657
|
+
/** Decoded reply payload for RPC client spans when available. */
|
|
658
|
+
readonly reply?: unknown;
|
|
659
|
+
/** Error instance if the operation failed. */
|
|
660
|
+
readonly error?: Error;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Classification outcome for a thrown error. Affects span status and
|
|
664
|
+
* attributes only — reply envelopes and internal logging are unchanged.
|
|
665
|
+
*/
|
|
666
|
+
type ErrorClassification = 'expected' | 'unexpected';
|
|
667
|
+
/** Object form of {@link OtelOptions.captureBody}. */
|
|
668
|
+
interface CaptureBodyOptions {
|
|
669
|
+
/**
|
|
670
|
+
* Maximum number of bytes to capture. Payloads longer than this are
|
|
671
|
+
* truncated; a `messaging.nats.message.body.truncated` attribute is
|
|
672
|
+
* added to indicate truncation occurred.
|
|
673
|
+
*
|
|
674
|
+
* @default 4096
|
|
675
|
+
*/
|
|
676
|
+
readonly maxBytes?: number;
|
|
677
|
+
/**
|
|
678
|
+
* Only capture body for subjects matching these glob patterns. Each
|
|
679
|
+
* pattern supports `*` wildcards and an optional leading `!` for
|
|
680
|
+
* exclusion. When omitted, body capture applies to all subjects.
|
|
681
|
+
*/
|
|
682
|
+
readonly subjectAllowlist?: readonly string[];
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* OpenTelemetry configuration for `JetstreamModule.forRoot({ otel: … })`.
|
|
686
|
+
* All fields are optional; when the host app has not registered an OTel
|
|
687
|
+
* SDK, every call made by the library is a no-op regardless of config.
|
|
688
|
+
*/
|
|
689
|
+
interface OtelOptions {
|
|
690
|
+
/**
|
|
691
|
+
* Global kill switch. When `false`, no spans are emitted, no propagation
|
|
692
|
+
* is attempted, and no hooks fire.
|
|
693
|
+
*
|
|
694
|
+
* @default true
|
|
695
|
+
*/
|
|
696
|
+
readonly enabled?: boolean;
|
|
697
|
+
/**
|
|
698
|
+
* Which trace kinds to emit.
|
|
699
|
+
*
|
|
700
|
+
* - `'default'` — publish, consume, RPC client round-trip, dead letter
|
|
701
|
+
* - `'all'` — every trace kind defined in {@link JetstreamTrace}
|
|
702
|
+
* - `'none'` — emit no spans at all (useful with `enabled: true` for
|
|
703
|
+
* pure trace-context propagation without the span overhead)
|
|
704
|
+
* - `JetstreamTrace[]` — explicit selection
|
|
705
|
+
*
|
|
706
|
+
* @default 'default'
|
|
707
|
+
*/
|
|
708
|
+
readonly traces?: readonly JetstreamTrace[] | 'default' | 'all' | 'none';
|
|
709
|
+
/**
|
|
710
|
+
* Header names to capture as span attributes (`messaging.header.<name>`).
|
|
711
|
+
* Match is case-insensitive. Glob wildcards (`*`) and negation (`!prefix-*`)
|
|
712
|
+
* are supported in the per-pattern form.
|
|
713
|
+
*
|
|
714
|
+
* SECURITY / GDPR: headers may contain authentication tokens, session
|
|
715
|
+
* identifiers, or other sensitive data. Captured values are exported to
|
|
716
|
+
* the configured OTel backend. Use an explicit allowlist in production.
|
|
717
|
+
* Setting this to `true` captures every header and is intended for
|
|
718
|
+
* development environments only.
|
|
719
|
+
*
|
|
720
|
+
* Transport-internal headers (`x-correlation-id`, `x-reply-to`, `x-error`,
|
|
721
|
+
* `x-subject`, `x-caller-name`) and propagator-owned headers
|
|
722
|
+
* (`traceparent`, `tracestate`, `baggage`, `sentry-trace`, `b3`, …) are
|
|
723
|
+
* always suppressed regardless of the allowlist.
|
|
724
|
+
*
|
|
725
|
+
* @default ['x-request-id']
|
|
726
|
+
*/
|
|
727
|
+
readonly captureHeaders?: readonly string[] | boolean;
|
|
728
|
+
/**
|
|
729
|
+
* Capture the message payload as the `messaging.nats.message.body` span
|
|
730
|
+
* attribute. Defaults to `false` for privacy and cost reasons.
|
|
731
|
+
*
|
|
732
|
+
* Passing `true` captures up to 4 KiB per message. Use the object form
|
|
733
|
+
* for finer control over size and subject scope.
|
|
734
|
+
*
|
|
735
|
+
* SECURITY / GDPR: payloads commonly contain PII, credentials, financial
|
|
736
|
+
* data, or content regulated by HIPAA / PCI-DSS. Enabling body capture
|
|
737
|
+
* in production is almost always a policy violation. Prefer enabling
|
|
738
|
+
* only in development, or pair with a custom `SpanProcessor` that
|
|
739
|
+
* scrubs or drops the attribute before export.
|
|
740
|
+
*
|
|
741
|
+
* @default false
|
|
742
|
+
*/
|
|
743
|
+
readonly captureBody?: boolean | CaptureBodyOptions;
|
|
744
|
+
/**
|
|
745
|
+
* Invoked after a publish span has been started and before the actual
|
|
746
|
+
* publish call executes. Use to enrich the span with custom attributes.
|
|
747
|
+
* Must be synchronous — thrown errors are caught and logged at debug
|
|
748
|
+
* level without affecting the publish path.
|
|
749
|
+
*/
|
|
750
|
+
publishHook?(span: Span, ctx: JetstreamPublishContext): void;
|
|
751
|
+
/**
|
|
752
|
+
* Invoked after a consume span has been started and before the handler
|
|
753
|
+
* is dispatched. Use to enrich the span with custom attributes derived
|
|
754
|
+
* from the incoming message or handler metadata.
|
|
755
|
+
*/
|
|
756
|
+
consumeHook?(span: Span, ctx: JetstreamConsumeContext): void;
|
|
757
|
+
/**
|
|
758
|
+
* Invoked once an operation's outcome is known (success, error, or
|
|
759
|
+
* timeout) and the span status has been set, just before the span ends.
|
|
760
|
+
* Fires for publish, consume, and RPC client spans.
|
|
761
|
+
*/
|
|
762
|
+
responseHook?(span: Span, ctx: JetstreamResponseContext): void;
|
|
763
|
+
/**
|
|
764
|
+
* Predicate evaluated at the top of every outgoing publish. Returning
|
|
765
|
+
* `false` skips span creation for that publish; propagation of trace
|
|
766
|
+
* context through headers still occurs, so downstream consumers are
|
|
767
|
+
* unaffected. Useful for suppressing noise from health-check or
|
|
768
|
+
* internal-only subjects.
|
|
769
|
+
*/
|
|
770
|
+
shouldTracePublish?(subject: string, record: JetstreamRecord): boolean;
|
|
771
|
+
/**
|
|
772
|
+
* Predicate evaluated at the top of every incoming message delivery.
|
|
773
|
+
* Returning `false` skips span creation for that delivery; the handler
|
|
774
|
+
* still executes normally and trace context is still extracted from
|
|
775
|
+
* headers for downstream calls.
|
|
776
|
+
*/
|
|
777
|
+
shouldTraceConsume?(subject: string, msg: ConsumeSourceMsg): boolean;
|
|
778
|
+
/**
|
|
779
|
+
* Classify a thrown error as `'expected'` (business error, part of the
|
|
780
|
+
* RPC contract) or `'unexpected'` (infrastructure failure or bug). Drives
|
|
781
|
+
* OpenTelemetry span status and attributes only.
|
|
782
|
+
*
|
|
783
|
+
* - `'expected'` → span status `OK` with `jetstream.rpc.reply.has_error`
|
|
784
|
+
* and `jetstream.rpc.reply.error.code` attributes
|
|
785
|
+
* - `'unexpected'` → span status `ERROR` with `span.recordException(err)`
|
|
786
|
+
*
|
|
787
|
+
* Reply envelopes delivered to RPC clients are identical in both cases.
|
|
788
|
+
* This classification affects only the observability artifact.
|
|
789
|
+
*
|
|
790
|
+
* The default recognizes NestJS-idiomatic primitives for business errors:
|
|
791
|
+
* `RpcException` and `HttpException`. Teams with custom error hierarchies
|
|
792
|
+
* override to recognize their own types.
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* errorClassifier: (err) => {
|
|
796
|
+
* if (err instanceof MyDomainError) return 'expected';
|
|
797
|
+
* if (err?.code?.startsWith('BIZ_')) return 'expected';
|
|
798
|
+
* return 'unexpected';
|
|
799
|
+
* }
|
|
800
|
+
*/
|
|
801
|
+
errorClassifier?(err: unknown): ErrorClassification;
|
|
802
|
+
}
|
|
803
|
+
|
|
120
804
|
/**
|
|
121
805
|
* Stream config overrides exposed to users.
|
|
122
806
|
*
|
|
@@ -385,6 +1069,16 @@ interface JetstreamModuleOptions {
|
|
|
385
1069
|
* Merged with `name` and `servers` — those take precedence.
|
|
386
1070
|
*/
|
|
387
1071
|
connectionOptions?: Partial<ConnectionOptions>;
|
|
1072
|
+
/**
|
|
1073
|
+
* OpenTelemetry integration. When omitted, sensible defaults are applied:
|
|
1074
|
+
* tracing is enabled, default trace kinds are emitted, only standard
|
|
1075
|
+
* correlation headers are captured. If no OTel SDK is registered in the
|
|
1076
|
+
* consuming application, all tracer calls are no-ops — there is no
|
|
1077
|
+
* runtime cost.
|
|
1078
|
+
*
|
|
1079
|
+
* @see OtelOptions
|
|
1080
|
+
*/
|
|
1081
|
+
otel?: OtelOptions;
|
|
388
1082
|
}
|
|
389
1083
|
/** Options for `JetstreamModule.forFeature()`. */
|
|
390
1084
|
interface JetstreamFeatureOptions {
|
|
@@ -490,105 +1184,6 @@ interface RpcRouterOptions {
|
|
|
490
1184
|
ackExtension?: boolean | number;
|
|
491
1185
|
}
|
|
492
1186
|
|
|
493
|
-
/**
|
|
494
|
-
* Central event bus for transport lifecycle notifications.
|
|
495
|
-
*
|
|
496
|
-
* Dispatches events to user-provided hooks. Events without a
|
|
497
|
-
* registered hook are silently ignored — no default logging.
|
|
498
|
-
*
|
|
499
|
-
* @example
|
|
500
|
-
* ```typescript
|
|
501
|
-
* const bus = new EventBus(logger, {
|
|
502
|
-
* [TransportEvent.Error]: (err) => sentry.captureException(err),
|
|
503
|
-
* });
|
|
504
|
-
*
|
|
505
|
-
* bus.emit(TransportEvent.Error, new Error('timeout'), 'rpc-router');
|
|
506
|
-
* // → calls sentry
|
|
507
|
-
*
|
|
508
|
-
* bus.emit(TransportEvent.Connect, 'nats://localhost:4222');
|
|
509
|
-
* // → no-op (no hook registered)
|
|
510
|
-
* ```
|
|
511
|
-
*/
|
|
512
|
-
declare class EventBus {
|
|
513
|
-
private readonly hooks;
|
|
514
|
-
private readonly logger;
|
|
515
|
-
constructor(logger: Logger, hooks?: Partial<TransportHooks>);
|
|
516
|
-
/**
|
|
517
|
-
* Emit a lifecycle event. Dispatches to custom hook if registered, otherwise no-op.
|
|
518
|
-
*
|
|
519
|
-
* @param event - The {@link TransportEvent} to emit.
|
|
520
|
-
* @param args - Arguments matching the hook signature for this event.
|
|
521
|
-
*/
|
|
522
|
-
emit<K extends keyof TransportHooks>(event: K, ...args: Parameters<TransportHooks[K]>): void;
|
|
523
|
-
/**
|
|
524
|
-
* Hot-path optimized emit for MessageRouted events.
|
|
525
|
-
* Avoids rest/spread overhead of the generic `emit()`.
|
|
526
|
-
*/
|
|
527
|
-
emitMessageRouted(subject: string, kind: MessageKind): void;
|
|
528
|
-
private callHook;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/**
|
|
532
|
-
* Manages the lifecycle of a single NATS connection shared across the application.
|
|
533
|
-
*
|
|
534
|
-
* Provides both Promise-based and Observable-based access to the connection:
|
|
535
|
-
* - `connect()` / `getConnection()` — async/await for one-time setup
|
|
536
|
-
* - `nc$` — cached observable (shareReplay) for reactive consumers
|
|
537
|
-
* - `status$` — live connection status event stream
|
|
538
|
-
*
|
|
539
|
-
* One instance per application, created by `JetstreamModule.forRoot()`.
|
|
540
|
-
*/
|
|
541
|
-
declare class ConnectionProvider {
|
|
542
|
-
private readonly options;
|
|
543
|
-
private readonly eventBus;
|
|
544
|
-
/** Cached observable that replays the established connection to new subscribers. */
|
|
545
|
-
readonly nc$: Observable<NatsConnection>;
|
|
546
|
-
/** Live stream of connection status events (no replay). */
|
|
547
|
-
readonly status$: Observable<Status>;
|
|
548
|
-
private readonly logger;
|
|
549
|
-
private connection;
|
|
550
|
-
private connectionPromise;
|
|
551
|
-
private jsClient;
|
|
552
|
-
private jsmInstance;
|
|
553
|
-
private jsmPromise;
|
|
554
|
-
constructor(options: JetstreamModuleOptions, eventBus: EventBus);
|
|
555
|
-
/**
|
|
556
|
-
* Establish NATS connection. Idempotent — returns cached connection on subsequent calls.
|
|
557
|
-
*
|
|
558
|
-
* @throws Error if connection is refused (fail fast).
|
|
559
|
-
*/
|
|
560
|
-
getConnection(): Promise<NatsConnection>;
|
|
561
|
-
/**
|
|
562
|
-
* Get the JetStream manager. Cached after first call.
|
|
563
|
-
*
|
|
564
|
-
* @returns The JetStreamManager for stream/consumer administration.
|
|
565
|
-
*/
|
|
566
|
-
getJetStreamManager(): Promise<JetStreamManager>;
|
|
567
|
-
/**
|
|
568
|
-
* Get a cached JetStream client.
|
|
569
|
-
*
|
|
570
|
-
* Invalidated automatically on reconnect and shutdown so consumers always
|
|
571
|
-
* operate against the live connection.
|
|
572
|
-
*
|
|
573
|
-
* @returns The cached JetStreamClient.
|
|
574
|
-
* @throws Error if the connection has not been established yet.
|
|
575
|
-
*/
|
|
576
|
-
getJetStreamClient(): JetStreamClient;
|
|
577
|
-
/** Direct access to the raw NATS connection, or `null` if not yet connected. */
|
|
578
|
-
get unwrap(): NatsConnection | null;
|
|
579
|
-
/**
|
|
580
|
-
* Gracefully shut down the connection.
|
|
581
|
-
*
|
|
582
|
-
* Sequence: drain → wait for close. Falls back to force-close on error.
|
|
583
|
-
*/
|
|
584
|
-
shutdown(): Promise<void>;
|
|
585
|
-
private initJetStreamManager;
|
|
586
|
-
/** Internal: establish the physical connection with reconnect monitoring. */
|
|
587
|
-
private establish;
|
|
588
|
-
/** Subscribe to connection status events and emit hooks. */
|
|
589
|
-
private monitorStatus;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
1187
|
/**
|
|
593
1188
|
* Registry mapping NATS subjects to NestJS message handlers.
|
|
594
1189
|
*
|
|
@@ -651,13 +1246,15 @@ declare class PatternRegistry {
|
|
|
651
1246
|
* This is the default RPC mode — lowest latency, no persistence overhead.
|
|
652
1247
|
*/
|
|
653
1248
|
declare class CoreRpcServer {
|
|
654
|
-
private readonly options;
|
|
655
1249
|
private readonly connection;
|
|
656
1250
|
private readonly patternRegistry;
|
|
657
1251
|
private readonly codec;
|
|
658
1252
|
private readonly eventBus;
|
|
659
1253
|
private readonly logger;
|
|
660
1254
|
private subscription;
|
|
1255
|
+
private readonly otel;
|
|
1256
|
+
private readonly serviceName;
|
|
1257
|
+
private readonly serverEndpoint;
|
|
661
1258
|
constructor(options: JetstreamModuleOptions, connection: ConnectionProvider, patternRegistry: PatternRegistry, codec: Codec, eventBus: EventBus);
|
|
662
1259
|
/** Start listening for RPC requests on the command subject. */
|
|
663
1260
|
start(): Promise<void>;
|
|
@@ -684,6 +1281,9 @@ declare class StreamProvider {
|
|
|
684
1281
|
private readonly connection;
|
|
685
1282
|
private readonly logger;
|
|
686
1283
|
private readonly migration;
|
|
1284
|
+
private readonly otel;
|
|
1285
|
+
private readonly otelServiceName;
|
|
1286
|
+
private readonly otelEndpoint;
|
|
687
1287
|
constructor(options: JetstreamModuleOptions, connection: ConnectionProvider);
|
|
688
1288
|
/**
|
|
689
1289
|
* Ensure all required streams exist with correct configuration.
|
|
@@ -727,21 +1327,6 @@ declare class StreamProvider {
|
|
|
727
1327
|
private stripTransportControlled;
|
|
728
1328
|
}
|
|
729
1329
|
|
|
730
|
-
/**
|
|
731
|
-
* Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.
|
|
732
|
-
*
|
|
733
|
-
* **Workqueue & Broadcast** — at-least-once delivery:
|
|
734
|
-
* - Success -> ack | Error -> nak (retry) | Dead letter -> term
|
|
735
|
-
*
|
|
736
|
-
* **Ordered** — strict sequential delivery:
|
|
737
|
-
* - No ack/nak/DLQ — nats.js auto-acknowledges ordered consumer messages.
|
|
738
|
-
* - Handler errors are logged but do not affect delivery.
|
|
739
|
-
*
|
|
740
|
-
* **Dead-Letter Queue (DLQ) - for handling failed message deliveries**
|
|
741
|
-
* - If `options.dlq` is configured, messages that exhaust their max delivery attempts are published to a DLQ stream.
|
|
742
|
-
* - The DLQ stream name is derived from the service name (e.g., `orders__microservice_dlq-stream`).
|
|
743
|
-
* - Original message data and metadata are preserved in the DLQ message, with additional headers indicating the reason for failure.
|
|
744
|
-
*/
|
|
745
1330
|
declare class EventRouter {
|
|
746
1331
|
private readonly messageProvider;
|
|
747
1332
|
private readonly patternRegistry;
|
|
@@ -754,6 +1339,9 @@ declare class EventRouter {
|
|
|
754
1339
|
private readonly options?;
|
|
755
1340
|
private readonly logger;
|
|
756
1341
|
private readonly subscriptions;
|
|
1342
|
+
private readonly otel;
|
|
1343
|
+
private readonly serviceName;
|
|
1344
|
+
private readonly serverEndpoint;
|
|
757
1345
|
constructor(messageProvider: MessageProvider, patternRegistry: PatternRegistry, codec: Codec, eventBus: EventBus, deadLetterConfig?: DeadLetterConfig | undefined, processingConfig?: EventProcessingConfig | undefined, ackWaitMap?: Map<StreamKind, number> | undefined, connection?: ConnectionProvider | undefined, options?: JetstreamModuleOptions | undefined);
|
|
758
1346
|
/**
|
|
759
1347
|
* Update the max_deliver thresholds from actual NATS consumer configs.
|
|
@@ -764,28 +1352,15 @@ declare class EventRouter {
|
|
|
764
1352
|
start(): void;
|
|
765
1353
|
/** Stop routing and unsubscribe from all streams. */
|
|
766
1354
|
destroy(): void;
|
|
767
|
-
/** Subscribe to a message stream and route each message. */
|
|
1355
|
+
/** Subscribe to a message stream and route each message to its handler. */
|
|
768
1356
|
private subscribeToStream;
|
|
769
1357
|
private getConcurrency;
|
|
770
1358
|
private getAckExtensionConfig;
|
|
771
|
-
/**
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
private decodeMessage;
|
|
777
|
-
/** Execute handler, then ack on success or nak/dead-letter on failure. */
|
|
778
|
-
private executeHandler;
|
|
779
|
-
/** Check if the message has exhausted all delivery attempts. */
|
|
780
|
-
private isDeadLetter;
|
|
781
|
-
/** Handle a dead letter: invoke callback, then term or nak based on result. */
|
|
782
|
-
/**
|
|
783
|
-
* Fallback execution for a dead letter when DLQ is disabled, or when
|
|
784
|
-
* publishing to the DLQ stream fails (due to network or NATS errors).
|
|
785
|
-
*
|
|
786
|
-
* Triggers the user-provided `onDeadLetter` hook for logging/alerting.
|
|
787
|
-
* On success, terminates the message. On error, leaves it unacknowledged (nak)
|
|
788
|
-
* so NATS can retry the delivery on the next cycle.
|
|
1359
|
+
/**
|
|
1360
|
+
* Last-resort path for a dead letter: invoke `onDeadLetter`, then `term` on
|
|
1361
|
+
* success or `nak` on hook failure so NATS retries on the next delivery
|
|
1362
|
+
* cycle. Used when DLQ stream isn't configured, or when publishing to it
|
|
1363
|
+
* failed and we still have to surface the message somewhere observable.
|
|
789
1364
|
*/
|
|
790
1365
|
private fallbackToOnDeadLetterCallback;
|
|
791
1366
|
/**
|
|
@@ -832,17 +1407,16 @@ declare class RpcRouter {
|
|
|
832
1407
|
private resolvedAckExtensionInterval;
|
|
833
1408
|
private subscription;
|
|
834
1409
|
private cachedNc;
|
|
835
|
-
|
|
1410
|
+
private readonly otel;
|
|
1411
|
+
private readonly serviceName;
|
|
1412
|
+
private readonly serverEndpoint;
|
|
1413
|
+
constructor(messageProvider: MessageProvider, patternRegistry: PatternRegistry, connection: ConnectionProvider, codec: Codec, eventBus: EventBus, rpcOptions?: RpcRouterOptions | undefined, ackWaitMap?: Map<StreamKind, number> | undefined, options?: JetstreamModuleOptions);
|
|
836
1414
|
/** Lazily resolve the ack extension interval (needs ackWaitMap populated at runtime). */
|
|
837
1415
|
private get ackExtensionInterval();
|
|
838
1416
|
/** Start routing command messages to handlers. */
|
|
839
1417
|
start(): Promise<void>;
|
|
840
1418
|
/** Stop routing and unsubscribe. */
|
|
841
1419
|
destroy(): void;
|
|
842
|
-
/** Handle a single RPC command message with error isolation. */
|
|
843
|
-
private handleSafe;
|
|
844
|
-
/** Execute handler, publish response, settle message. */
|
|
845
|
-
private executeHandler;
|
|
846
1420
|
}
|
|
847
1421
|
|
|
848
1422
|
/**
|
|
@@ -857,6 +1431,9 @@ declare class ConsumerProvider {
|
|
|
857
1431
|
private readonly streamProvider;
|
|
858
1432
|
private readonly patternRegistry;
|
|
859
1433
|
private readonly logger;
|
|
1434
|
+
private readonly otel;
|
|
1435
|
+
private readonly otelServiceName;
|
|
1436
|
+
private readonly otelEndpoint;
|
|
860
1437
|
constructor(options: JetstreamModuleOptions, connection: ConnectionProvider, streamProvider: StreamProvider, patternRegistry: PatternRegistry);
|
|
861
1438
|
/**
|
|
862
1439
|
* Ensure consumers exist for the specified kinds.
|
|
@@ -978,7 +1555,7 @@ declare class MessageProvider {
|
|
|
978
1555
|
private createOrderedFlow;
|
|
979
1556
|
/** Shared self-healing flow: defer -> retry with exponential backoff on error/completion. */
|
|
980
1557
|
private createSelfHealingFlow;
|
|
981
|
-
/** Single iteration: create ordered consumer ->
|
|
1558
|
+
/** Single iteration: create ordered consumer -> push messages into the subject. */
|
|
982
1559
|
private consumeOrderedOnce;
|
|
983
1560
|
}
|
|
984
1561
|
|
|
@@ -1033,6 +1610,21 @@ declare class MetadataProvider {
|
|
|
1033
1610
|
private openBucket;
|
|
1034
1611
|
}
|
|
1035
1612
|
|
|
1613
|
+
/**
|
|
1614
|
+
* NATS JetStream API error codes used by the transport.
|
|
1615
|
+
*
|
|
1616
|
+
* Ref: https://github.com/nats-io/nats-server (server error definitions)
|
|
1617
|
+
* Verified on NATS 2.12.6 via integration tests (2026-04-02).
|
|
1618
|
+
*/
|
|
1619
|
+
declare enum NatsErrorCode {
|
|
1620
|
+
/** Consumer does not exist on the specified stream. */
|
|
1621
|
+
ConsumerNotFound = 10014,
|
|
1622
|
+
/** Consumer name already in use with different configuration (race condition on create). */
|
|
1623
|
+
ConsumerAlreadyExists = 10148,
|
|
1624
|
+
/** Stream does not exist. */
|
|
1625
|
+
StreamNotFound = 10059
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1036
1628
|
/**
|
|
1037
1629
|
* NestJS custom transport strategy for NATS JetStream.
|
|
1038
1630
|
*
|
|
@@ -1206,265 +1798,65 @@ declare class JetstreamModule implements OnApplicationShutdown {
|
|
|
1206
1798
|
}
|
|
1207
1799
|
|
|
1208
1800
|
/**
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1211
|
-
* Supports two operational modes:
|
|
1212
|
-
* - **Core mode** (default): Uses `nc.request()` for RPC, `nc.publish()` for events.
|
|
1213
|
-
* - **JetStream mode**: Uses `js.publish()` for RPC commands + inbox for responses.
|
|
1214
|
-
*
|
|
1215
|
-
* Events always go through JetStream publish for guaranteed delivery.
|
|
1216
|
-
* The mode only affects RPC (request/reply) behavior.
|
|
1217
|
-
*
|
|
1218
|
-
* Clients are lightweight — they share the NATS connection from `forRoot()`.
|
|
1219
|
-
*/
|
|
1220
|
-
declare class JetstreamClient extends ClientProxy {
|
|
1221
|
-
private readonly rootOptions;
|
|
1222
|
-
private readonly connection;
|
|
1223
|
-
private readonly codec;
|
|
1224
|
-
private readonly eventBus;
|
|
1225
|
-
private readonly logger;
|
|
1226
|
-
/** Target service name this client sends messages to. */
|
|
1227
|
-
private readonly targetName;
|
|
1228
|
-
/** Pre-cached caller name derived from rootOptions.name, computed once in constructor. */
|
|
1229
|
-
private readonly callerName;
|
|
1230
|
-
/** Shared inbox for JetStream-mode RPC responses. */
|
|
1231
|
-
private inbox;
|
|
1232
|
-
private inboxSubscription;
|
|
1233
|
-
/** Pending JetStream-mode RPC callbacks, keyed by correlation ID. */
|
|
1234
|
-
private readonly pendingMessages;
|
|
1235
|
-
/** Pending JetStream-mode RPC timeouts, keyed by correlation ID. */
|
|
1236
|
-
private readonly pendingTimeouts;
|
|
1237
|
-
/** Subscription to connection status events for disconnect handling. */
|
|
1238
|
-
private statusSubscription;
|
|
1239
|
-
constructor(rootOptions: JetstreamModuleOptions, targetServiceName: string, connection: ConnectionProvider, codec: Codec, eventBus: EventBus);
|
|
1240
|
-
/**
|
|
1241
|
-
* Establish connection. Called automatically by NestJS on first use.
|
|
1242
|
-
*
|
|
1243
|
-
* Sets up the JetStream RPC inbox (if in JetStream mode) and subscribes
|
|
1244
|
-
* to connection status events for fail-fast disconnect handling.
|
|
1245
|
-
*
|
|
1246
|
-
* @returns The underlying NATS connection.
|
|
1247
|
-
*/
|
|
1248
|
-
connect(): Promise<NatsConnection>;
|
|
1249
|
-
/** Clean up resources: reject pending RPCs, unsubscribe from status events. */
|
|
1250
|
-
close(): Promise<void>;
|
|
1251
|
-
/**
|
|
1252
|
-
* Direct access to the raw NATS connection.
|
|
1253
|
-
*
|
|
1254
|
-
* @throws Error if not connected.
|
|
1255
|
-
*/
|
|
1256
|
-
unwrap<T = NatsConnection>(): T;
|
|
1257
|
-
/**
|
|
1258
|
-
* Publish a fire-and-forget event to JetStream.
|
|
1259
|
-
*
|
|
1260
|
-
* Events are published to either the workqueue stream or broadcast stream
|
|
1261
|
-
* depending on the subject prefix. When a schedule is present the message
|
|
1262
|
-
* is published to a `_sch` subject within the same stream, with the target
|
|
1263
|
-
* set to the original event subject.
|
|
1264
|
-
*/
|
|
1265
|
-
protected dispatchEvent<T = unknown>(packet: ReadPacket): Promise<T>;
|
|
1266
|
-
/**
|
|
1267
|
-
* Publish an RPC command and register callback for response.
|
|
1268
|
-
*
|
|
1269
|
-
* Core mode: uses nc.request() with timeout.
|
|
1270
|
-
* JetStream mode: publishes to stream + waits for inbox response.
|
|
1271
|
-
*/
|
|
1272
|
-
protected publish(packet: ReadPacket, callback: (p: WritePacket) => void): () => void;
|
|
1273
|
-
/** Core mode: nc.request() with timeout. */
|
|
1274
|
-
private publishCoreRpc;
|
|
1275
|
-
/** JetStream mode: publish to stream + wait for inbox response. */
|
|
1276
|
-
private publishJetStreamRpc;
|
|
1277
|
-
/** Fail-fast all pending JetStream RPC callbacks on connection loss. */
|
|
1278
|
-
private handleDisconnect;
|
|
1279
|
-
/** Reject all pending RPC callbacks, clear timeouts, and tear down inbox. */
|
|
1280
|
-
private rejectPendingRpcs;
|
|
1281
|
-
/** Setup shared inbox subscription for JetStream RPC responses. */
|
|
1282
|
-
private setupInbox;
|
|
1283
|
-
/** Route an inbox reply to the matching pending callback. */
|
|
1284
|
-
private routeInboxReply;
|
|
1285
|
-
/** Build event subject — workqueue, broadcast, or ordered. */
|
|
1286
|
-
private buildEventSubject;
|
|
1287
|
-
/** Build NATS headers merging custom headers with transport headers. */
|
|
1288
|
-
private buildHeaders;
|
|
1289
|
-
/** Extract data, headers, timeout, and schedule from raw packet data or JetstreamRecord. */
|
|
1290
|
-
private extractRecordData;
|
|
1291
|
-
/**
|
|
1292
|
-
* Build a schedule-holder subject for NATS message scheduling.
|
|
1293
|
-
*
|
|
1294
|
-
* The schedule-holder subject resides in the same stream as the target but
|
|
1295
|
-
* uses a separate `_sch` namespace that is NOT matched by any consumer filter.
|
|
1296
|
-
* NATS holds the message and publishes it to the target subject after the delay.
|
|
1297
|
-
*
|
|
1298
|
-
* Examples:
|
|
1299
|
-
* - `{svc}__microservice.ev.order.reminder` → `{svc}__microservice._sch.order.reminder`
|
|
1300
|
-
* - `broadcast.config.updated` → `broadcast._sch.config.updated`
|
|
1301
|
-
*/
|
|
1302
|
-
private buildScheduleSubject;
|
|
1303
|
-
private getRpcTimeout;
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
/**
|
|
1307
|
-
* Immutable message record for JetStream transport.
|
|
1801
|
+
* Default JSON codec using native `TextEncoder`/`TextDecoder`.
|
|
1308
1802
|
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1803
|
+
* Serializes values to JSON via `JSON.stringify` and encodes the
|
|
1804
|
+
* resulting string into a `Uint8Array`. Decoding reverses the process.
|
|
1311
1805
|
*
|
|
1312
1806
|
* @example
|
|
1313
1807
|
* ```typescript
|
|
1314
|
-
* const
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
* .build();
|
|
1318
|
-
*
|
|
1319
|
-
* client.send('get.user', record);
|
|
1808
|
+
* const codec = new JsonCodec();
|
|
1809
|
+
* const bytes = codec.encode({ hello: 'world' });
|
|
1810
|
+
* const data = codec.decode(bytes); // { hello: 'world' }
|
|
1320
1811
|
* ```
|
|
1321
1812
|
*/
|
|
1322
|
-
declare class
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
/** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
|
|
1326
|
-
readonly headers: ReadonlyMap<string, string>;
|
|
1327
|
-
/** Per-request RPC timeout override in ms. */
|
|
1328
|
-
readonly timeout?: number | undefined;
|
|
1329
|
-
/** Custom message ID for JetStream deduplication. */
|
|
1330
|
-
readonly messageId?: string | undefined;
|
|
1331
|
-
/** Schedule options for delayed delivery. */
|
|
1332
|
-
readonly schedule?: ScheduleRecordOptions | undefined;
|
|
1333
|
-
/** Per-message TTL as Go duration string (e.g. "30s", "5m"). */
|
|
1334
|
-
readonly ttl?: string | undefined;
|
|
1335
|
-
constructor(
|
|
1336
|
-
/** Message payload. */
|
|
1337
|
-
data: TData,
|
|
1338
|
-
/** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
|
|
1339
|
-
headers: ReadonlyMap<string, string>,
|
|
1340
|
-
/** Per-request RPC timeout override in ms. */
|
|
1341
|
-
timeout?: number | undefined,
|
|
1342
|
-
/** Custom message ID for JetStream deduplication. */
|
|
1343
|
-
messageId?: string | undefined,
|
|
1344
|
-
/** Schedule options for delayed delivery. */
|
|
1345
|
-
schedule?: ScheduleRecordOptions | undefined,
|
|
1346
|
-
/** Per-message TTL as Go duration string (e.g. "30s", "5m"). */
|
|
1347
|
-
ttl?: string | undefined);
|
|
1813
|
+
declare class JsonCodec implements Codec {
|
|
1814
|
+
encode(data: unknown): Uint8Array;
|
|
1815
|
+
decode(data: Uint8Array): unknown;
|
|
1348
1816
|
}
|
|
1817
|
+
|
|
1349
1818
|
/**
|
|
1350
|
-
*
|
|
1819
|
+
* Minimal shape of a `msgpackr` `Packr` instance used by {@link MsgpackCodec}.
|
|
1351
1820
|
*
|
|
1352
|
-
*
|
|
1353
|
-
*
|
|
1821
|
+
* Typed locally so consumers who do not use MessagePack encoding never pay
|
|
1822
|
+
* for a `msgpackr` import.
|
|
1354
1823
|
*/
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
private timeout;
|
|
1359
|
-
private messageId;
|
|
1360
|
-
private scheduleOptions;
|
|
1361
|
-
private ttlDuration;
|
|
1362
|
-
constructor(data?: TData);
|
|
1363
|
-
/**
|
|
1364
|
-
* Set the message payload.
|
|
1365
|
-
*
|
|
1366
|
-
* @param data - Payload to serialize via the configured {@link Codec}.
|
|
1367
|
-
*/
|
|
1368
|
-
setData(data: TData): this;
|
|
1369
|
-
/**
|
|
1370
|
-
* Set a single custom header.
|
|
1371
|
-
*
|
|
1372
|
-
* @param key - Header name (e.g. `'x-tenant'`).
|
|
1373
|
-
* @param value - Header value.
|
|
1374
|
-
* @throws Error if the header name is reserved by the transport.
|
|
1375
|
-
*/
|
|
1376
|
-
setHeader(key: string, value: string): this;
|
|
1377
|
-
/**
|
|
1378
|
-
* Set multiple custom headers at once.
|
|
1379
|
-
*
|
|
1380
|
-
* @param headers - Key-value pairs to set as headers.
|
|
1381
|
-
* @throws Error if any header name is reserved by the transport.
|
|
1382
|
-
*/
|
|
1383
|
-
setHeaders(headers: Record<string, string>): this;
|
|
1384
|
-
/**
|
|
1385
|
-
* Set a custom message ID for JetStream deduplication.
|
|
1386
|
-
*
|
|
1387
|
-
* NATS JetStream uses this ID to detect duplicate publishes within the
|
|
1388
|
-
* stream's `duplicate_window`. If two messages with the same ID arrive
|
|
1389
|
-
* within the window, the second is silently dropped.
|
|
1390
|
-
*
|
|
1391
|
-
* When not set, a random UUID is generated automatically.
|
|
1392
|
-
*
|
|
1393
|
-
* @param id - Unique message identifier (e.g. order ID, idempotency key).
|
|
1394
|
-
*
|
|
1395
|
-
* @example
|
|
1396
|
-
* ```typescript
|
|
1397
|
-
* new JetstreamRecordBuilder(data)
|
|
1398
|
-
* .setMessageId(`order-${order.id}`)
|
|
1399
|
-
* .build();
|
|
1400
|
-
* ```
|
|
1401
|
-
*/
|
|
1402
|
-
setMessageId(id: string): this;
|
|
1403
|
-
/**
|
|
1404
|
-
* Set per-request RPC timeout.
|
|
1405
|
-
*
|
|
1406
|
-
* @param ms - Timeout in milliseconds. Overrides the global RPC timeout for this request only.
|
|
1407
|
-
*/
|
|
1408
|
-
setTimeout(ms: number): this;
|
|
1409
|
-
/**
|
|
1410
|
-
* Schedule one-shot delayed delivery.
|
|
1411
|
-
*
|
|
1412
|
-
* The message is held by NATS and delivered to the event consumer
|
|
1413
|
-
* at the specified time. Requires NATS >= 2.12 and `allow_msg_schedules: true`
|
|
1414
|
-
* on the event stream (via `events: { stream: { allow_msg_schedules: true } }`).
|
|
1415
|
-
*
|
|
1416
|
-
* Only meaningful for events (`client.emit()`). If used with RPC
|
|
1417
|
-
* (`client.send()`), a warning is logged and the schedule is ignored.
|
|
1418
|
-
*
|
|
1419
|
-
* @param date - Delivery time. Must be in the future.
|
|
1420
|
-
* @throws Error if the date is not in the future.
|
|
1421
|
-
*/
|
|
1422
|
-
scheduleAt(date: Date): this;
|
|
1423
|
-
/**
|
|
1424
|
-
* Set per-message TTL (time-to-live).
|
|
1425
|
-
*
|
|
1426
|
-
* The message expires individually after the specified duration,
|
|
1427
|
-
* independent of the stream's `max_age`. Requires NATS >= 2.11 and
|
|
1428
|
-
* `allow_msg_ttl: true` on the stream.
|
|
1429
|
-
*
|
|
1430
|
-
* Only meaningful for events (`client.emit()`). If used with RPC
|
|
1431
|
-
* (`client.send()`), a warning is logged and the TTL is ignored.
|
|
1432
|
-
*
|
|
1433
|
-
* @param nanos - TTL in nanoseconds. Use {@link toNanos} for human-readable values.
|
|
1434
|
-
*
|
|
1435
|
-
* @example
|
|
1436
|
-
* ```typescript
|
|
1437
|
-
* import { toNanos } from '@horizon-republic/nestjs-jetstream';
|
|
1438
|
-
*
|
|
1439
|
-
* new JetstreamRecordBuilder(payload).ttl(toNanos(30, 'minutes')).build();
|
|
1440
|
-
* new JetstreamRecordBuilder(payload).ttl(toNanos(24, 'hours')).build();
|
|
1441
|
-
* ```
|
|
1442
|
-
*/
|
|
1443
|
-
ttl(nanos: number): this;
|
|
1444
|
-
/**
|
|
1445
|
-
* Build the immutable {@link JetstreamRecord}.
|
|
1446
|
-
*
|
|
1447
|
-
* @returns A frozen record ready to pass to `client.send()` or `client.emit()`.
|
|
1448
|
-
*/
|
|
1449
|
-
build(): JetstreamRecord<TData>;
|
|
1450
|
-
/** Validate that a header key is not reserved. */
|
|
1451
|
-
private validateHeaderKey;
|
|
1824
|
+
interface PackrLike {
|
|
1825
|
+
pack(data: unknown): Uint8Array;
|
|
1826
|
+
unpack(data: Uint8Array): unknown;
|
|
1452
1827
|
}
|
|
1453
|
-
|
|
1454
1828
|
/**
|
|
1455
|
-
*
|
|
1829
|
+
* MessagePack codec backed by a caller-provided `msgpackr` `Packr` instance.
|
|
1456
1830
|
*
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1831
|
+
* Use this codec when publishing structured payloads larger than roughly
|
|
1832
|
+
* 1–2 KB — below that size the default {@link JsonCodec} wins on per-call
|
|
1833
|
+
* constant overhead. Above it, MessagePack encodes and decodes several times
|
|
1834
|
+
* faster and produces smaller wire frames. The format is cross-language, so
|
|
1835
|
+
* Node producers and non-Node consumers (Python, Go, Java, Rust, ...) stay
|
|
1836
|
+
* interoperable.
|
|
1837
|
+
*
|
|
1838
|
+
* Requires installing the optional `msgpackr` peer dependency:
|
|
1839
|
+
*
|
|
1840
|
+
* ```bash
|
|
1841
|
+
* npm install msgpackr
|
|
1842
|
+
* # or: pnpm add msgpackr
|
|
1843
|
+
* ```
|
|
1459
1844
|
*
|
|
1460
1845
|
* @example
|
|
1461
1846
|
* ```typescript
|
|
1462
|
-
*
|
|
1463
|
-
*
|
|
1464
|
-
*
|
|
1847
|
+
* import { JetstreamModule, MsgpackCodec } from '@horizon-republic/nestjs-jetstream';
|
|
1848
|
+
* import { Packr } from 'msgpackr';
|
|
1849
|
+
*
|
|
1850
|
+
* JetstreamModule.forRoot({
|
|
1851
|
+
* name: 'orders',
|
|
1852
|
+
* servers: ['nats://localhost:4222'],
|
|
1853
|
+
* codec: new MsgpackCodec(new Packr()),
|
|
1854
|
+
* });
|
|
1465
1855
|
* ```
|
|
1466
1856
|
*/
|
|
1467
|
-
declare class
|
|
1857
|
+
declare class MsgpackCodec implements Codec {
|
|
1858
|
+
private readonly packr;
|
|
1859
|
+
constructor(packr: PackrLike);
|
|
1468
1860
|
encode(data: unknown): Uint8Array;
|
|
1469
1861
|
decode(data: Uint8Array): unknown;
|
|
1470
1862
|
}
|
|
@@ -1625,8 +2017,6 @@ declare const JETSTREAM_OPTIONS: unique symbol;
|
|
|
1625
2017
|
declare const JETSTREAM_CONNECTION: unique symbol;
|
|
1626
2018
|
/** Token for the global Codec instance. */
|
|
1627
2019
|
declare const JETSTREAM_CODEC: unique symbol;
|
|
1628
|
-
/** Token for the EventBus instance. */
|
|
1629
|
-
declare const JETSTREAM_EVENT_BUS: unique symbol;
|
|
1630
2020
|
/**
|
|
1631
2021
|
* Generate the injection token for a `forFeature()` client.
|
|
1632
2022
|
*
|
|
@@ -1659,6 +2049,28 @@ type TimeUnit = 'ms' | 'seconds' | 'minutes' | 'hours' | 'days';
|
|
|
1659
2049
|
* ```
|
|
1660
2050
|
*/
|
|
1661
2051
|
declare const toNanos: (value: number, unit: TimeUnit) => number;
|
|
2052
|
+
/** Default config for workqueue event streams. */
|
|
2053
|
+
declare const DEFAULT_EVENT_STREAM_CONFIG: Partial<StreamConfig>;
|
|
2054
|
+
/** Default config for RPC command streams (jetstream mode only). */
|
|
2055
|
+
declare const DEFAULT_COMMAND_STREAM_CONFIG: Partial<StreamConfig>;
|
|
2056
|
+
/** Default config for broadcast event streams. */
|
|
2057
|
+
declare const DEFAULT_BROADCAST_STREAM_CONFIG: Partial<StreamConfig>;
|
|
2058
|
+
/** Default config for ordered event streams (Limits retention). */
|
|
2059
|
+
declare const DEFAULT_ORDERED_STREAM_CONFIG: Partial<StreamConfig>;
|
|
2060
|
+
/** Default config for dead-letter queue (DLQ) streams. */
|
|
2061
|
+
declare const DEFAULT_DLQ_STREAM_CONFIG: Partial<StreamConfig>;
|
|
2062
|
+
/** Default config for workqueue event consumers. */
|
|
2063
|
+
declare const DEFAULT_EVENT_CONSUMER_CONFIG: Partial<ConsumerConfig>;
|
|
2064
|
+
/** Default config for RPC command consumers (jetstream mode only). */
|
|
2065
|
+
declare const DEFAULT_COMMAND_CONSUMER_CONFIG: Partial<ConsumerConfig>;
|
|
2066
|
+
/** Default config for broadcast event consumers. */
|
|
2067
|
+
declare const DEFAULT_BROADCAST_CONSUMER_CONFIG: Partial<ConsumerConfig>;
|
|
2068
|
+
/** Default RPC timeout for Core mode (30 seconds). */
|
|
2069
|
+
declare const DEFAULT_RPC_TIMEOUT = 30000;
|
|
2070
|
+
/** Default RPC timeout for JetStream mode (3 minutes). */
|
|
2071
|
+
declare const DEFAULT_JETSTREAM_RPC_TIMEOUT = 180000;
|
|
2072
|
+
/** Default graceful shutdown timeout (10 seconds). */
|
|
2073
|
+
declare const DEFAULT_SHUTDOWN_TIMEOUT = 10000;
|
|
1662
2074
|
/** Default KV bucket name for handler metadata. */
|
|
1663
2075
|
declare const DEFAULT_METADATA_BUCKET = "handler_registry";
|
|
1664
2076
|
/** Default number of KV bucket replicas. */
|
|
@@ -1698,7 +2110,7 @@ declare enum JetstreamHeader {
|
|
|
1698
2110
|
Error = "x-error"
|
|
1699
2111
|
}
|
|
1700
2112
|
declare enum JetstreamDlqHeader {
|
|
1701
|
-
/** Reason for the message being sent to the DLQ
|
|
2113
|
+
/** Reason for the message being sent to the DLQ — the last handler error message. */
|
|
1702
2114
|
DeadLetterReason = "x-dead-letter-reason",
|
|
1703
2115
|
/** Original NATS subject the message was originally published to */
|
|
1704
2116
|
OriginalSubject = "x-original-subject",
|
|
@@ -1709,6 +2121,8 @@ declare enum JetstreamDlqHeader {
|
|
|
1709
2121
|
/** Number of times the message has been delivered */
|
|
1710
2122
|
DeliveryCount = "x-delivery-count"
|
|
1711
2123
|
}
|
|
2124
|
+
/** Set of header names that are reserved and cannot be set by users. */
|
|
2125
|
+
declare const RESERVED_HEADERS: Set<string>;
|
|
1712
2126
|
/**
|
|
1713
2127
|
* Build the internal service name with microservice suffix.
|
|
1714
2128
|
*
|
|
@@ -1770,4 +2184,4 @@ declare const isJetStreamRpcMode: (rpc: RpcConfig | undefined) => boolean;
|
|
|
1770
2184
|
/** Check if the RPC config specifies Core mode (default). */
|
|
1771
2185
|
declare const isCoreRpcMode: (rpc: RpcConfig | undefined) => boolean;
|
|
1772
2186
|
|
|
1773
|
-
export { type Codec, DEFAULT_METADATA_BUCKET, DEFAULT_METADATA_HISTORY, DEFAULT_METADATA_REPLICAS, DEFAULT_METADATA_TTL, type DeadLetterInfo,
|
|
2187
|
+
export { type CaptureBodyOptions, type Codec, ConsumeKind, type ConsumeSourceMsg, DEFAULT_BROADCAST_CONSUMER_CONFIG, DEFAULT_BROADCAST_STREAM_CONFIG, DEFAULT_COMMAND_CONSUMER_CONFIG, DEFAULT_COMMAND_STREAM_CONFIG, DEFAULT_DLQ_STREAM_CONFIG, DEFAULT_EVENT_CONSUMER_CONFIG, DEFAULT_EVENT_STREAM_CONFIG, DEFAULT_JETSTREAM_RPC_TIMEOUT, DEFAULT_METADATA_BUCKET, DEFAULT_METADATA_HISTORY, DEFAULT_METADATA_REPLICAS, DEFAULT_METADATA_TTL, DEFAULT_ORDERED_STREAM_CONFIG, DEFAULT_RPC_TIMEOUT, DEFAULT_SHUTDOWN_TIMEOUT, DEFAULT_TRACES, type DeadLetterInfo, type ErrorClassification, type HandlerMetadata, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamConsumeContext, JetstreamDlqHeader, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, type JetstreamPublishContext, JetstreamRecord, JetstreamRecordBuilder, type JetstreamResponseContext, JetstreamStrategy, JetstreamTrace, JsonCodec, MIN_METADATA_TTL, MessageKind, type MetadataRegistryOptions, MsgpackCodec, NatsErrorCode, type OrderedEventOverrides, type OtelOptions, PatternPrefix, PublishKind, RESERVED_HEADERS, type RpcConfig, RpcContext, type ScheduleRecordOptions, type ServerEndpoint, type StreamConfigOverrides, type StreamConsumerOverrides, StreamKind, TRACER_NAME, TransportEvent, type TransportHooks, buildBroadcastSubject, buildSubject, consumerName, dlqStreamName, getClientToken, internalName, isCoreRpcMode, isJetStreamRpcMode, metadataKey, streamName, toNanos };
|