@horizon-republic/nestjs-jetstream 2.3.6 → 2.4.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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ModuleMetadata, FactoryProvider, Type, Logger, OnApplicationShutdown, DynamicModule } from '@nestjs/common';
2
- import { MsgHdrs, StreamConfig, ConsumerConfig, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
2
+ import { MsgHdrs, StreamConfig, ConsumerConfig, DeliverPolicy, ReplayPolicy, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
3
3
  import { MessageHandler, Server, CustomTransportStrategy, ClientProxy, ReadPacket, WritePacket, BaseRpcContext } from '@nestjs/microservices';
4
4
  import { Observable } from 'rxjs';
5
5
 
@@ -129,6 +129,37 @@ interface StreamConsumerOverrides {
129
129
  stream?: Partial<StreamConfig>;
130
130
  consumer?: Partial<ConsumerConfig>;
131
131
  }
132
+ /**
133
+ * Configuration for ordered event consumers.
134
+ *
135
+ * Ordered consumers use Limits retention and deliver messages in strict
136
+ * sequential order with at-most-once delivery. No ack/nak/DLQ.
137
+ *
138
+ * Only a subset of consumer options applies — ordered consumers are
139
+ * ephemeral and auto-managed by nats.js.
140
+ */
141
+ interface OrderedEventOverrides {
142
+ /** Stream overrides (e.g. `max_age`, `max_bytes`). */
143
+ stream?: Partial<StreamConfig>;
144
+ /**
145
+ * Where to start reading when the consumer is (re)created.
146
+ * @default DeliverPolicy.All
147
+ */
148
+ deliverPolicy?: DeliverPolicy;
149
+ /**
150
+ * Start sequence number. Only used when `deliverPolicy` is `StartSequence`.
151
+ */
152
+ optStartSeq?: number;
153
+ /**
154
+ * Start time (ISO string). Only used when `deliverPolicy` is `StartTime`.
155
+ */
156
+ optStartTime?: string;
157
+ /**
158
+ * Replay policy for historical messages.
159
+ * @default ReplayPolicy.Instant
160
+ */
161
+ replayPolicy?: ReplayPolicy;
162
+ }
132
163
  /**
133
164
  * Root module configuration for `JetstreamModule.forRoot()`.
134
165
  *
@@ -160,6 +191,15 @@ interface JetstreamModuleOptions {
160
191
  events?: StreamConsumerOverrides;
161
192
  /** Broadcast event stream/consumer overrides. */
162
193
  broadcast?: StreamConsumerOverrides;
194
+ /**
195
+ * Ordered event consumer configuration.
196
+ *
197
+ * Ordered events use a separate stream with Limits retention and deliver
198
+ * messages in strict sequential order. Use `ordered:` prefix when publishing.
199
+ *
200
+ * @see OrderedEventOverrides
201
+ */
202
+ ordered?: OrderedEventOverrides;
163
203
  /**
164
204
  * Transport lifecycle hook handlers.
165
205
  * Unset hooks are silently ignored — no default logging.
@@ -244,8 +284,9 @@ type JetstreamModuleAsyncOptions = {
244
284
  * - `'ev'` — Workqueue events (at-least-once delivery to one consumer).
245
285
  * - `'cmd'` — RPC commands (JetStream mode only).
246
286
  * - `'broadcast'` — Broadcast events (fan-out to all consumers).
287
+ * - `'ordered'` — Ordered events (strict sequential delivery, Limits retention).
247
288
  */
248
- type StreamKind = 'ev' | 'cmd' | 'broadcast';
289
+ type StreamKind = 'ev' | 'cmd' | 'broadcast' | 'ordered';
249
290
 
250
291
  /** @internal Grouped pattern lists by stream kind, used for stream/consumer setup. */
251
292
  interface PatternsByKind {
@@ -255,6 +296,8 @@ interface PatternsByKind {
255
296
  commands: string[];
256
297
  /** Broadcast event patterns. */
257
298
  broadcasts: string[];
299
+ /** Ordered event patterns (strict sequential delivery). */
300
+ ordered: string[];
258
301
  }
259
302
 
260
303
  /**
@@ -367,6 +410,10 @@ declare class PatternRegistry {
367
410
  hasRpcHandlers(): boolean;
368
411
  /** Check if any workqueue event handlers are registered. */
369
412
  hasEventHandlers(): boolean;
413
+ /** Check if any ordered event handlers are registered. */
414
+ hasOrderedHandlers(): boolean;
415
+ /** Get fully-qualified NATS subjects for ordered handlers. */
416
+ getOrderedSubjects(): string[];
370
417
  /** Get patterns grouped by kind. */
371
418
  getPatternsByKind(): PatternsByKind;
372
419
  /** Normalize a full NATS subject back to the user-facing pattern. */
@@ -449,21 +496,14 @@ interface DeadLetterConfig {
449
496
  onDeadLetter(info: DeadLetterInfo): Promise<void>;
450
497
  }
451
498
  /**
452
- * Routes incoming event messages (workqueue and broadcast) to NestJS handlers.
499
+ * Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.
453
500
  *
454
- * Delivery semantics (at-least-once):
455
- * - Handler executes first
456
- * - Success -> ack (message consumed)
457
- * - Handler error -> nak (NATS redelivers, up to `max_deliver` times)
458
- * - Dead letter (max_deliver reached) -> onDeadLetter hook -> term or nak
459
- * - Decode error -> term (no retry for malformed payloads)
460
- * - No handler found -> term (configuration error)
501
+ * **Workqueue & Broadcast** — at-least-once delivery:
502
+ * - Success -> ack | Error -> nak (retry) | Dead letter -> term
461
503
  *
462
- * Both workqueue and broadcast use the same ack/nak semantics.
463
- * Each durable consumer tracks delivery independently, so a nak from
464
- * one broadcast consumer does not affect others.
465
- *
466
- * Handlers must be idempotent — NATS may redeliver on failure or timeout.
504
+ * **Ordered** strict sequential delivery:
505
+ * - No ack/nak/DLQ nats.js auto-acknowledges ordered consumer messages.
506
+ * - Handler errors are logged but do not affect delivery.
467
507
  */
468
508
  declare class EventRouter {
469
509
  private readonly messageProvider;
@@ -479,7 +519,7 @@ declare class EventRouter {
479
519
  * Called after consumers are ensured so the DLQ map reflects reality.
480
520
  */
481
521
  updateMaxDeliverMap(consumerMaxDelivers: Map<string, number>): void;
482
- /** Start routing event and broadcast messages to handlers. */
522
+ /** Start routing event, broadcast, and ordered messages to handlers. */
483
523
  start(): void;
484
524
  /** Stop routing and unsubscribe from all streams. */
485
525
  destroy(): void;
@@ -489,6 +529,8 @@ declare class EventRouter {
489
529
  private handle;
490
530
  /** Execute handler, then ack on success or nak/dead-letter on failure. */
491
531
  private executeHandler;
532
+ /** Handle an ordered message: decode -> execute handler -> no ack/nak. */
533
+ private handleOrdered;
492
534
  /** Check if the message has exhausted all delivery attempts. */
493
535
  private isDeadLetter;
494
536
  /** Handle a dead letter: invoke callback, then term or nak based on result. */
@@ -572,10 +614,13 @@ declare class MessageProvider {
572
614
  private readonly eventBus;
573
615
  private readonly logger;
574
616
  private readonly activeIterators;
617
+ private orderedReadyResolve;
618
+ private orderedReadyReject;
575
619
  private destroy$;
576
620
  private eventMessages$;
577
621
  private commandMessages$;
578
622
  private broadcastMessages$;
623
+ private orderedMessages$;
579
624
  constructor(connection: ConnectionProvider, eventBus: EventBus);
580
625
  /** Observable stream of workqueue event messages. */
581
626
  get events$(): Observable<JsMsg>;
@@ -583,6 +628,8 @@ declare class MessageProvider {
583
628
  get commands$(): Observable<JsMsg>;
584
629
  /** Observable stream of broadcast event messages. */
585
630
  get broadcasts$(): Observable<JsMsg>;
631
+ /** Observable stream of ordered event messages (strict sequential delivery). */
632
+ get ordered$(): Observable<JsMsg>;
586
633
  /**
587
634
  * Start consuming messages from the given consumer infos.
588
635
  *
@@ -590,6 +637,16 @@ declare class MessageProvider {
590
637
  * Call `destroy()` to stop all consumers.
591
638
  */
592
639
  start(consumers: Map<StreamKind, ConsumerInfo>): void;
640
+ /**
641
+ * Start an ordered consumer for strict sequential delivery.
642
+ *
643
+ * Unlike durable consumers, ordered consumers are ephemeral — created at
644
+ * consumption time, no durable state. nats.js handles auto-recreation.
645
+ *
646
+ * @param streamName - JetStream stream to consume from.
647
+ * @param filterSubjects - NATS subjects to filter on.
648
+ */
649
+ startOrdered(streamName: string, filterSubjects: string[], orderedConfig?: OrderedEventOverrides): Promise<void>;
593
650
  /** Stop all consumer flows and reinitialize subjects for potential restart. */
594
651
  destroy(): void;
595
652
  /** Create a self-healing consumer flow for a specific kind. */
@@ -598,6 +655,10 @@ declare class MessageProvider {
598
655
  private consumeOnce;
599
656
  /** Get the target subject for a consumer kind. */
600
657
  private getTargetSubject;
658
+ /** Create a self-healing ordered consumer flow. */
659
+ private createOrderedFlow;
660
+ /** Single iteration: create ordered consumer -> iterate messages. */
661
+ private consumeOrderedOnce;
601
662
  }
602
663
 
603
664
  /**
@@ -648,8 +709,10 @@ declare class JetstreamStrategy extends Server implements CustomTransportStrateg
648
709
  unwrap<T>(): T;
649
710
  /** Access the pattern registry (for module-level introspection). */
650
711
  getPatternRegistry(): PatternRegistry;
651
- /** Determine which JetStream stream kinds are needed. */
712
+ /** Determine which JetStream streams are needed. */
652
713
  private resolveStreamKinds;
714
+ /** Determine which stream kinds need durable consumers (ordered consumers are ephemeral). */
715
+ private resolveDurableConsumerKinds;
653
716
  /** Build max_deliver map from actual NATS consumer configs (not options). */
654
717
  private buildMaxDeliverMap;
655
718
  private isCoreRpcMode;
@@ -831,7 +894,7 @@ declare class JetstreamClient extends ClientProxy {
831
894
  private setupInbox;
832
895
  /** Route an inbox reply to the matching pending callback. */
833
896
  private routeInboxReply;
834
- /** Build event subject — workqueue or broadcast. */
897
+ /** Build event subject — workqueue, broadcast, or ordered. */
835
898
  private buildEventSubject;
836
899
  /** Build NATS headers merging custom headers with transport headers. */
837
900
  private buildHeaders;
@@ -865,13 +928,17 @@ declare class JetstreamRecord<TData = unknown> {
865
928
  readonly headers: ReadonlyMap<string, string>;
866
929
  /** Per-request RPC timeout override in ms. */
867
930
  readonly timeout?: number | undefined;
931
+ /** Custom message ID for JetStream deduplication. */
932
+ readonly messageId?: string | undefined;
868
933
  constructor(
869
934
  /** Message payload. */
870
935
  data: TData,
871
936
  /** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
872
937
  headers: ReadonlyMap<string, string>,
873
938
  /** Per-request RPC timeout override in ms. */
874
- timeout?: number | undefined);
939
+ timeout?: number | undefined,
940
+ /** Custom message ID for JetStream deduplication. */
941
+ messageId?: string | undefined);
875
942
  }
876
943
  /**
877
944
  * Fluent builder for constructing JetstreamRecord instances.
@@ -883,6 +950,7 @@ declare class JetstreamRecordBuilder<TData = unknown> {
883
950
  private data;
884
951
  private readonly headers;
885
952
  private timeout;
953
+ private messageId;
886
954
  constructor(data?: TData);
887
955
  /**
888
956
  * Set the message payload.
@@ -905,6 +973,25 @@ declare class JetstreamRecordBuilder<TData = unknown> {
905
973
  * @throws Error if any header name is reserved by the transport.
906
974
  */
907
975
  setHeaders(headers: Record<string, string>): this;
976
+ /**
977
+ * Set a custom message ID for JetStream deduplication.
978
+ *
979
+ * NATS JetStream uses this ID to detect duplicate publishes within the
980
+ * stream's `duplicate_window`. If two messages with the same ID arrive
981
+ * within the window, the second is silently dropped.
982
+ *
983
+ * When not set, a random UUID is generated automatically.
984
+ *
985
+ * @param id - Unique message identifier (e.g. order ID, idempotency key).
986
+ *
987
+ * @example
988
+ * ```typescript
989
+ * new JetstreamRecordBuilder(data)
990
+ * .setMessageId(`order-${order.id}`)
991
+ * .build();
992
+ * ```
993
+ */
994
+ setMessageId(id: string): this;
908
995
  /**
909
996
  * Set per-request RPC timeout.
910
997
  *
@@ -1090,14 +1177,8 @@ declare enum JetstreamHeader {
1090
1177
  Subject = "x-subject",
1091
1178
  /** Internal name of the service that sent the message. */
1092
1179
  CallerName = "x-caller-name",
1093
- /** User-provided request ID (pass-through, not auto-generated). */
1094
- RequestId = "x-request-id",
1095
- /** User-provided trace ID for distributed tracing (pass-through). */
1096
- TraceId = "x-trace-id",
1097
- /** User-provided span ID for distributed tracing (pass-through). */
1098
- SpanId = "x-span-id",
1099
1180
  /** Set to `'true'` on error responses so the client can distinguish success from failure. */
1100
1181
  Error = "x-error"
1101
1182
  }
1102
1183
 
1103
- export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
1184
+ export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type OrderedEventOverrides, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ModuleMetadata, FactoryProvider, Type, Logger, OnApplicationShutdown, DynamicModule } from '@nestjs/common';
2
- import { MsgHdrs, StreamConfig, ConsumerConfig, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
2
+ import { MsgHdrs, StreamConfig, ConsumerConfig, DeliverPolicy, ReplayPolicy, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
3
3
  import { MessageHandler, Server, CustomTransportStrategy, ClientProxy, ReadPacket, WritePacket, BaseRpcContext } from '@nestjs/microservices';
4
4
  import { Observable } from 'rxjs';
5
5
 
@@ -129,6 +129,37 @@ interface StreamConsumerOverrides {
129
129
  stream?: Partial<StreamConfig>;
130
130
  consumer?: Partial<ConsumerConfig>;
131
131
  }
132
+ /**
133
+ * Configuration for ordered event consumers.
134
+ *
135
+ * Ordered consumers use Limits retention and deliver messages in strict
136
+ * sequential order with at-most-once delivery. No ack/nak/DLQ.
137
+ *
138
+ * Only a subset of consumer options applies — ordered consumers are
139
+ * ephemeral and auto-managed by nats.js.
140
+ */
141
+ interface OrderedEventOverrides {
142
+ /** Stream overrides (e.g. `max_age`, `max_bytes`). */
143
+ stream?: Partial<StreamConfig>;
144
+ /**
145
+ * Where to start reading when the consumer is (re)created.
146
+ * @default DeliverPolicy.All
147
+ */
148
+ deliverPolicy?: DeliverPolicy;
149
+ /**
150
+ * Start sequence number. Only used when `deliverPolicy` is `StartSequence`.
151
+ */
152
+ optStartSeq?: number;
153
+ /**
154
+ * Start time (ISO string). Only used when `deliverPolicy` is `StartTime`.
155
+ */
156
+ optStartTime?: string;
157
+ /**
158
+ * Replay policy for historical messages.
159
+ * @default ReplayPolicy.Instant
160
+ */
161
+ replayPolicy?: ReplayPolicy;
162
+ }
132
163
  /**
133
164
  * Root module configuration for `JetstreamModule.forRoot()`.
134
165
  *
@@ -160,6 +191,15 @@ interface JetstreamModuleOptions {
160
191
  events?: StreamConsumerOverrides;
161
192
  /** Broadcast event stream/consumer overrides. */
162
193
  broadcast?: StreamConsumerOverrides;
194
+ /**
195
+ * Ordered event consumer configuration.
196
+ *
197
+ * Ordered events use a separate stream with Limits retention and deliver
198
+ * messages in strict sequential order. Use `ordered:` prefix when publishing.
199
+ *
200
+ * @see OrderedEventOverrides
201
+ */
202
+ ordered?: OrderedEventOverrides;
163
203
  /**
164
204
  * Transport lifecycle hook handlers.
165
205
  * Unset hooks are silently ignored — no default logging.
@@ -244,8 +284,9 @@ type JetstreamModuleAsyncOptions = {
244
284
  * - `'ev'` — Workqueue events (at-least-once delivery to one consumer).
245
285
  * - `'cmd'` — RPC commands (JetStream mode only).
246
286
  * - `'broadcast'` — Broadcast events (fan-out to all consumers).
287
+ * - `'ordered'` — Ordered events (strict sequential delivery, Limits retention).
247
288
  */
248
- type StreamKind = 'ev' | 'cmd' | 'broadcast';
289
+ type StreamKind = 'ev' | 'cmd' | 'broadcast' | 'ordered';
249
290
 
250
291
  /** @internal Grouped pattern lists by stream kind, used for stream/consumer setup. */
251
292
  interface PatternsByKind {
@@ -255,6 +296,8 @@ interface PatternsByKind {
255
296
  commands: string[];
256
297
  /** Broadcast event patterns. */
257
298
  broadcasts: string[];
299
+ /** Ordered event patterns (strict sequential delivery). */
300
+ ordered: string[];
258
301
  }
259
302
 
260
303
  /**
@@ -367,6 +410,10 @@ declare class PatternRegistry {
367
410
  hasRpcHandlers(): boolean;
368
411
  /** Check if any workqueue event handlers are registered. */
369
412
  hasEventHandlers(): boolean;
413
+ /** Check if any ordered event handlers are registered. */
414
+ hasOrderedHandlers(): boolean;
415
+ /** Get fully-qualified NATS subjects for ordered handlers. */
416
+ getOrderedSubjects(): string[];
370
417
  /** Get patterns grouped by kind. */
371
418
  getPatternsByKind(): PatternsByKind;
372
419
  /** Normalize a full NATS subject back to the user-facing pattern. */
@@ -449,21 +496,14 @@ interface DeadLetterConfig {
449
496
  onDeadLetter(info: DeadLetterInfo): Promise<void>;
450
497
  }
451
498
  /**
452
- * Routes incoming event messages (workqueue and broadcast) to NestJS handlers.
499
+ * Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.
453
500
  *
454
- * Delivery semantics (at-least-once):
455
- * - Handler executes first
456
- * - Success -> ack (message consumed)
457
- * - Handler error -> nak (NATS redelivers, up to `max_deliver` times)
458
- * - Dead letter (max_deliver reached) -> onDeadLetter hook -> term or nak
459
- * - Decode error -> term (no retry for malformed payloads)
460
- * - No handler found -> term (configuration error)
501
+ * **Workqueue & Broadcast** — at-least-once delivery:
502
+ * - Success -> ack | Error -> nak (retry) | Dead letter -> term
461
503
  *
462
- * Both workqueue and broadcast use the same ack/nak semantics.
463
- * Each durable consumer tracks delivery independently, so a nak from
464
- * one broadcast consumer does not affect others.
465
- *
466
- * Handlers must be idempotent — NATS may redeliver on failure or timeout.
504
+ * **Ordered** strict sequential delivery:
505
+ * - No ack/nak/DLQ nats.js auto-acknowledges ordered consumer messages.
506
+ * - Handler errors are logged but do not affect delivery.
467
507
  */
468
508
  declare class EventRouter {
469
509
  private readonly messageProvider;
@@ -479,7 +519,7 @@ declare class EventRouter {
479
519
  * Called after consumers are ensured so the DLQ map reflects reality.
480
520
  */
481
521
  updateMaxDeliverMap(consumerMaxDelivers: Map<string, number>): void;
482
- /** Start routing event and broadcast messages to handlers. */
522
+ /** Start routing event, broadcast, and ordered messages to handlers. */
483
523
  start(): void;
484
524
  /** Stop routing and unsubscribe from all streams. */
485
525
  destroy(): void;
@@ -489,6 +529,8 @@ declare class EventRouter {
489
529
  private handle;
490
530
  /** Execute handler, then ack on success or nak/dead-letter on failure. */
491
531
  private executeHandler;
532
+ /** Handle an ordered message: decode -> execute handler -> no ack/nak. */
533
+ private handleOrdered;
492
534
  /** Check if the message has exhausted all delivery attempts. */
493
535
  private isDeadLetter;
494
536
  /** Handle a dead letter: invoke callback, then term or nak based on result. */
@@ -572,10 +614,13 @@ declare class MessageProvider {
572
614
  private readonly eventBus;
573
615
  private readonly logger;
574
616
  private readonly activeIterators;
617
+ private orderedReadyResolve;
618
+ private orderedReadyReject;
575
619
  private destroy$;
576
620
  private eventMessages$;
577
621
  private commandMessages$;
578
622
  private broadcastMessages$;
623
+ private orderedMessages$;
579
624
  constructor(connection: ConnectionProvider, eventBus: EventBus);
580
625
  /** Observable stream of workqueue event messages. */
581
626
  get events$(): Observable<JsMsg>;
@@ -583,6 +628,8 @@ declare class MessageProvider {
583
628
  get commands$(): Observable<JsMsg>;
584
629
  /** Observable stream of broadcast event messages. */
585
630
  get broadcasts$(): Observable<JsMsg>;
631
+ /** Observable stream of ordered event messages (strict sequential delivery). */
632
+ get ordered$(): Observable<JsMsg>;
586
633
  /**
587
634
  * Start consuming messages from the given consumer infos.
588
635
  *
@@ -590,6 +637,16 @@ declare class MessageProvider {
590
637
  * Call `destroy()` to stop all consumers.
591
638
  */
592
639
  start(consumers: Map<StreamKind, ConsumerInfo>): void;
640
+ /**
641
+ * Start an ordered consumer for strict sequential delivery.
642
+ *
643
+ * Unlike durable consumers, ordered consumers are ephemeral — created at
644
+ * consumption time, no durable state. nats.js handles auto-recreation.
645
+ *
646
+ * @param streamName - JetStream stream to consume from.
647
+ * @param filterSubjects - NATS subjects to filter on.
648
+ */
649
+ startOrdered(streamName: string, filterSubjects: string[], orderedConfig?: OrderedEventOverrides): Promise<void>;
593
650
  /** Stop all consumer flows and reinitialize subjects for potential restart. */
594
651
  destroy(): void;
595
652
  /** Create a self-healing consumer flow for a specific kind. */
@@ -598,6 +655,10 @@ declare class MessageProvider {
598
655
  private consumeOnce;
599
656
  /** Get the target subject for a consumer kind. */
600
657
  private getTargetSubject;
658
+ /** Create a self-healing ordered consumer flow. */
659
+ private createOrderedFlow;
660
+ /** Single iteration: create ordered consumer -> iterate messages. */
661
+ private consumeOrderedOnce;
601
662
  }
602
663
 
603
664
  /**
@@ -648,8 +709,10 @@ declare class JetstreamStrategy extends Server implements CustomTransportStrateg
648
709
  unwrap<T>(): T;
649
710
  /** Access the pattern registry (for module-level introspection). */
650
711
  getPatternRegistry(): PatternRegistry;
651
- /** Determine which JetStream stream kinds are needed. */
712
+ /** Determine which JetStream streams are needed. */
652
713
  private resolveStreamKinds;
714
+ /** Determine which stream kinds need durable consumers (ordered consumers are ephemeral). */
715
+ private resolveDurableConsumerKinds;
653
716
  /** Build max_deliver map from actual NATS consumer configs (not options). */
654
717
  private buildMaxDeliverMap;
655
718
  private isCoreRpcMode;
@@ -831,7 +894,7 @@ declare class JetstreamClient extends ClientProxy {
831
894
  private setupInbox;
832
895
  /** Route an inbox reply to the matching pending callback. */
833
896
  private routeInboxReply;
834
- /** Build event subject — workqueue or broadcast. */
897
+ /** Build event subject — workqueue, broadcast, or ordered. */
835
898
  private buildEventSubject;
836
899
  /** Build NATS headers merging custom headers with transport headers. */
837
900
  private buildHeaders;
@@ -865,13 +928,17 @@ declare class JetstreamRecord<TData = unknown> {
865
928
  readonly headers: ReadonlyMap<string, string>;
866
929
  /** Per-request RPC timeout override in ms. */
867
930
  readonly timeout?: number | undefined;
931
+ /** Custom message ID for JetStream deduplication. */
932
+ readonly messageId?: string | undefined;
868
933
  constructor(
869
934
  /** Message payload. */
870
935
  data: TData,
871
936
  /** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
872
937
  headers: ReadonlyMap<string, string>,
873
938
  /** Per-request RPC timeout override in ms. */
874
- timeout?: number | undefined);
939
+ timeout?: number | undefined,
940
+ /** Custom message ID for JetStream deduplication. */
941
+ messageId?: string | undefined);
875
942
  }
876
943
  /**
877
944
  * Fluent builder for constructing JetstreamRecord instances.
@@ -883,6 +950,7 @@ declare class JetstreamRecordBuilder<TData = unknown> {
883
950
  private data;
884
951
  private readonly headers;
885
952
  private timeout;
953
+ private messageId;
886
954
  constructor(data?: TData);
887
955
  /**
888
956
  * Set the message payload.
@@ -905,6 +973,25 @@ declare class JetstreamRecordBuilder<TData = unknown> {
905
973
  * @throws Error if any header name is reserved by the transport.
906
974
  */
907
975
  setHeaders(headers: Record<string, string>): this;
976
+ /**
977
+ * Set a custom message ID for JetStream deduplication.
978
+ *
979
+ * NATS JetStream uses this ID to detect duplicate publishes within the
980
+ * stream's `duplicate_window`. If two messages with the same ID arrive
981
+ * within the window, the second is silently dropped.
982
+ *
983
+ * When not set, a random UUID is generated automatically.
984
+ *
985
+ * @param id - Unique message identifier (e.g. order ID, idempotency key).
986
+ *
987
+ * @example
988
+ * ```typescript
989
+ * new JetstreamRecordBuilder(data)
990
+ * .setMessageId(`order-${order.id}`)
991
+ * .build();
992
+ * ```
993
+ */
994
+ setMessageId(id: string): this;
908
995
  /**
909
996
  * Set per-request RPC timeout.
910
997
  *
@@ -1090,14 +1177,8 @@ declare enum JetstreamHeader {
1090
1177
  Subject = "x-subject",
1091
1178
  /** Internal name of the service that sent the message. */
1092
1179
  CallerName = "x-caller-name",
1093
- /** User-provided request ID (pass-through, not auto-generated). */
1094
- RequestId = "x-request-id",
1095
- /** User-provided trace ID for distributed tracing (pass-through). */
1096
- TraceId = "x-trace-id",
1097
- /** User-provided span ID for distributed tracing (pass-through). */
1098
- SpanId = "x-span-id",
1099
1180
  /** Set to `'true'` on error responses so the client can distinguish success from failure. */
1100
1181
  Error = "x-error"
1101
1182
  }
1102
1183
 
1103
- export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
1184
+ export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type OrderedEventOverrides, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };