@horizon-republic/nestjs-jetstream 2.4.1 → 2.5.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 +1 -2
- package/dist/index.cjs +21 -26
- package/dist/index.d.cts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.js +20 -25
- package/package.json +2 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -45,9 +45,8 @@ export class OrdersController {
|
|
|
45
45
|
**[Read the full documentation →](https://horizonrepublic.github.io/nestjs-jetstream/)**
|
|
46
46
|
|
|
47
47
|
- [Getting Started](https://horizonrepublic.github.io/nestjs-jetstream/docs/getting-started) — installation, module setup, first handler
|
|
48
|
-
- [Messaging Patterns](https://horizonrepublic.github.io/nestjs-jetstream/docs/category/messaging-patterns) — events, broadcast, ordered delivery, RPC
|
|
49
48
|
- [Guides](https://horizonrepublic.github.io/nestjs-jetstream/docs/guides/health-checks) — health checks, graceful shutdown, lifecycle hooks
|
|
50
|
-
- [API Reference](https://horizonrepublic.github.io/nestjs-jetstream/api) — full TypeDoc-generated API
|
|
49
|
+
- [API Reference](https://horizonrepublic.github.io/nestjs-jetstream/docs/reference/api/) — full TypeDoc-generated API
|
|
51
50
|
|
|
52
51
|
## Links
|
|
53
52
|
|
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
RpcContext: () => RpcContext,
|
|
46
46
|
TransportEvent: () => TransportEvent,
|
|
47
47
|
getClientToken: () => getClientToken,
|
|
48
|
-
|
|
48
|
+
toNanos: () => toNanos
|
|
49
49
|
});
|
|
50
50
|
module.exports = __toCommonJS(index_exports);
|
|
51
51
|
|
|
@@ -81,7 +81,14 @@ var getClientToken = (name) => name;
|
|
|
81
81
|
var KB = 1024;
|
|
82
82
|
var MB = 1024 * KB;
|
|
83
83
|
var GB = 1024 * MB;
|
|
84
|
-
var
|
|
84
|
+
var NANOS_PER = {
|
|
85
|
+
ms: 1e6,
|
|
86
|
+
seconds: 1e9,
|
|
87
|
+
minutes: 6e10,
|
|
88
|
+
hours: 36e11,
|
|
89
|
+
days: 864e11
|
|
90
|
+
};
|
|
91
|
+
var toNanos = (value, unit) => value * NANOS_PER[unit];
|
|
85
92
|
var baseStreamConfig = {
|
|
86
93
|
retention: import_nats.RetentionPolicy.Workqueue,
|
|
87
94
|
storage: import_nats.StorageType.File,
|
|
@@ -98,10 +105,8 @@ var DEFAULT_EVENT_STREAM_CONFIG = {
|
|
|
98
105
|
max_msgs_per_subject: 5e6,
|
|
99
106
|
max_msgs: 5e7,
|
|
100
107
|
max_bytes: 5 * GB,
|
|
101
|
-
max_age:
|
|
102
|
-
|
|
103
|
-
duplicate_window: nanos(2 * 60 * 1e3)
|
|
104
|
-
// 2 min
|
|
108
|
+
max_age: toNanos(7, "days"),
|
|
109
|
+
duplicate_window: toNanos(2, "minutes")
|
|
105
110
|
};
|
|
106
111
|
var DEFAULT_COMMAND_STREAM_CONFIG = {
|
|
107
112
|
...baseStreamConfig,
|
|
@@ -111,10 +116,8 @@ var DEFAULT_COMMAND_STREAM_CONFIG = {
|
|
|
111
116
|
max_msgs_per_subject: 1e5,
|
|
112
117
|
max_msgs: 1e6,
|
|
113
118
|
max_bytes: 100 * MB,
|
|
114
|
-
max_age:
|
|
115
|
-
|
|
116
|
-
duplicate_window: nanos(30 * 1e3)
|
|
117
|
-
// 30s
|
|
119
|
+
max_age: toNanos(3, "minutes"),
|
|
120
|
+
duplicate_window: toNanos(30, "seconds")
|
|
118
121
|
};
|
|
119
122
|
var DEFAULT_BROADCAST_STREAM_CONFIG = {
|
|
120
123
|
...baseStreamConfig,
|
|
@@ -125,10 +128,8 @@ var DEFAULT_BROADCAST_STREAM_CONFIG = {
|
|
|
125
128
|
max_msgs_per_subject: 1e6,
|
|
126
129
|
max_msgs: 1e7,
|
|
127
130
|
max_bytes: 2 * GB,
|
|
128
|
-
max_age:
|
|
129
|
-
|
|
130
|
-
duplicate_window: nanos(2 * 60 * 1e3)
|
|
131
|
-
// 2 min
|
|
131
|
+
max_age: toNanos(1, "days"),
|
|
132
|
+
duplicate_window: toNanos(2, "minutes")
|
|
132
133
|
};
|
|
133
134
|
var DEFAULT_ORDERED_STREAM_CONFIG = {
|
|
134
135
|
...baseStreamConfig,
|
|
@@ -139,14 +140,11 @@ var DEFAULT_ORDERED_STREAM_CONFIG = {
|
|
|
139
140
|
max_msgs_per_subject: 5e6,
|
|
140
141
|
max_msgs: 5e7,
|
|
141
142
|
max_bytes: 5 * GB,
|
|
142
|
-
max_age:
|
|
143
|
-
|
|
144
|
-
duplicate_window: nanos(2 * 60 * 1e3)
|
|
145
|
-
// 2 min
|
|
143
|
+
max_age: toNanos(1, "days"),
|
|
144
|
+
duplicate_window: toNanos(2, "minutes")
|
|
146
145
|
};
|
|
147
146
|
var DEFAULT_EVENT_CONSUMER_CONFIG = {
|
|
148
|
-
ack_wait:
|
|
149
|
-
// 10s
|
|
147
|
+
ack_wait: toNanos(10, "seconds"),
|
|
150
148
|
max_deliver: 3,
|
|
151
149
|
max_ack_pending: 100,
|
|
152
150
|
ack_policy: import_nats.AckPolicy.Explicit,
|
|
@@ -154,8 +152,7 @@ var DEFAULT_EVENT_CONSUMER_CONFIG = {
|
|
|
154
152
|
replay_policy: import_nats.ReplayPolicy.Instant
|
|
155
153
|
};
|
|
156
154
|
var DEFAULT_COMMAND_CONSUMER_CONFIG = {
|
|
157
|
-
ack_wait:
|
|
158
|
-
// 5 min
|
|
155
|
+
ack_wait: toNanos(5, "minutes"),
|
|
159
156
|
max_deliver: 1,
|
|
160
157
|
max_ack_pending: 100,
|
|
161
158
|
ack_policy: import_nats.AckPolicy.Explicit,
|
|
@@ -163,8 +160,7 @@ var DEFAULT_COMMAND_CONSUMER_CONFIG = {
|
|
|
163
160
|
replay_policy: import_nats.ReplayPolicy.Instant
|
|
164
161
|
};
|
|
165
162
|
var DEFAULT_BROADCAST_CONSUMER_CONFIG = {
|
|
166
|
-
ack_wait:
|
|
167
|
-
// 10s
|
|
163
|
+
ack_wait: toNanos(10, "seconds"),
|
|
168
164
|
max_deliver: 3,
|
|
169
165
|
max_ack_pending: 100,
|
|
170
166
|
ack_policy: import_nats.AckPolicy.Explicit,
|
|
@@ -2348,6 +2344,5 @@ JetstreamModule = __decorateClass([
|
|
|
2348
2344
|
RpcContext,
|
|
2349
2345
|
TransportEvent,
|
|
2350
2346
|
getClientToken,
|
|
2351
|
-
|
|
2347
|
+
toNanos
|
|
2352
2348
|
});
|
|
2353
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -1148,19 +1148,23 @@ declare const JETSTREAM_EVENT_BUS: unique symbol;
|
|
|
1148
1148
|
* ```
|
|
1149
1149
|
*/
|
|
1150
1150
|
declare const getClientToken: (name: string) => string;
|
|
1151
|
+
/** Supported time units for {@link toNanos}. */
|
|
1152
|
+
type TimeUnit = 'ms' | 'seconds' | 'minutes' | 'hours' | 'days';
|
|
1151
1153
|
/**
|
|
1152
|
-
* Convert
|
|
1154
|
+
* Convert a human-readable duration to nanoseconds (NATS JetStream format).
|
|
1153
1155
|
*
|
|
1154
|
-
* @param
|
|
1156
|
+
* @param value - Numeric duration value.
|
|
1157
|
+
* @param unit - Time unit to convert from.
|
|
1155
1158
|
* @returns Duration in nanoseconds.
|
|
1156
1159
|
*
|
|
1157
1160
|
* @example
|
|
1158
1161
|
* ```typescript
|
|
1159
|
-
*
|
|
1160
|
-
* {
|
|
1162
|
+
* { ack_wait: toNanos(30, 'seconds') }
|
|
1163
|
+
* { max_age: toNanos(7, 'days') }
|
|
1164
|
+
* { duplicate_window: toNanos(2, 'minutes') }
|
|
1161
1165
|
* ```
|
|
1162
1166
|
*/
|
|
1163
|
-
declare const
|
|
1167
|
+
declare const toNanos: (value: number, unit: TimeUnit) => number;
|
|
1164
1168
|
/**
|
|
1165
1169
|
* NATS headers managed by the transport.
|
|
1166
1170
|
*
|
|
@@ -1181,4 +1185,4 @@ declare enum JetstreamHeader {
|
|
|
1181
1185
|
Error = "x-error"
|
|
1182
1186
|
}
|
|
1183
1187
|
|
|
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,
|
|
1188
|
+
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, toNanos };
|
package/dist/index.d.ts
CHANGED
|
@@ -1148,19 +1148,23 @@ declare const JETSTREAM_EVENT_BUS: unique symbol;
|
|
|
1148
1148
|
* ```
|
|
1149
1149
|
*/
|
|
1150
1150
|
declare const getClientToken: (name: string) => string;
|
|
1151
|
+
/** Supported time units for {@link toNanos}. */
|
|
1152
|
+
type TimeUnit = 'ms' | 'seconds' | 'minutes' | 'hours' | 'days';
|
|
1151
1153
|
/**
|
|
1152
|
-
* Convert
|
|
1154
|
+
* Convert a human-readable duration to nanoseconds (NATS JetStream format).
|
|
1153
1155
|
*
|
|
1154
|
-
* @param
|
|
1156
|
+
* @param value - Numeric duration value.
|
|
1157
|
+
* @param unit - Time unit to convert from.
|
|
1155
1158
|
* @returns Duration in nanoseconds.
|
|
1156
1159
|
*
|
|
1157
1160
|
* @example
|
|
1158
1161
|
* ```typescript
|
|
1159
|
-
*
|
|
1160
|
-
* {
|
|
1162
|
+
* { ack_wait: toNanos(30, 'seconds') }
|
|
1163
|
+
* { max_age: toNanos(7, 'days') }
|
|
1164
|
+
* { duplicate_window: toNanos(2, 'minutes') }
|
|
1161
1165
|
* ```
|
|
1162
1166
|
*/
|
|
1163
|
-
declare const
|
|
1167
|
+
declare const toNanos: (value: number, unit: TimeUnit) => number;
|
|
1164
1168
|
/**
|
|
1165
1169
|
* NATS headers managed by the transport.
|
|
1166
1170
|
*
|
|
@@ -1181,4 +1185,4 @@ declare enum JetstreamHeader {
|
|
|
1181
1185
|
Error = "x-error"
|
|
1182
1186
|
}
|
|
1183
1187
|
|
|
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,
|
|
1188
|
+
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, toNanos };
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,14 @@ var getClientToken = (name) => name;
|
|
|
60
60
|
var KB = 1024;
|
|
61
61
|
var MB = 1024 * KB;
|
|
62
62
|
var GB = 1024 * MB;
|
|
63
|
-
var
|
|
63
|
+
var NANOS_PER = {
|
|
64
|
+
ms: 1e6,
|
|
65
|
+
seconds: 1e9,
|
|
66
|
+
minutes: 6e10,
|
|
67
|
+
hours: 36e11,
|
|
68
|
+
days: 864e11
|
|
69
|
+
};
|
|
70
|
+
var toNanos = (value, unit) => value * NANOS_PER[unit];
|
|
64
71
|
var baseStreamConfig = {
|
|
65
72
|
retention: RetentionPolicy.Workqueue,
|
|
66
73
|
storage: StorageType.File,
|
|
@@ -77,10 +84,8 @@ var DEFAULT_EVENT_STREAM_CONFIG = {
|
|
|
77
84
|
max_msgs_per_subject: 5e6,
|
|
78
85
|
max_msgs: 5e7,
|
|
79
86
|
max_bytes: 5 * GB,
|
|
80
|
-
max_age:
|
|
81
|
-
|
|
82
|
-
duplicate_window: nanos(2 * 60 * 1e3)
|
|
83
|
-
// 2 min
|
|
87
|
+
max_age: toNanos(7, "days"),
|
|
88
|
+
duplicate_window: toNanos(2, "minutes")
|
|
84
89
|
};
|
|
85
90
|
var DEFAULT_COMMAND_STREAM_CONFIG = {
|
|
86
91
|
...baseStreamConfig,
|
|
@@ -90,10 +95,8 @@ var DEFAULT_COMMAND_STREAM_CONFIG = {
|
|
|
90
95
|
max_msgs_per_subject: 1e5,
|
|
91
96
|
max_msgs: 1e6,
|
|
92
97
|
max_bytes: 100 * MB,
|
|
93
|
-
max_age:
|
|
94
|
-
|
|
95
|
-
duplicate_window: nanos(30 * 1e3)
|
|
96
|
-
// 30s
|
|
98
|
+
max_age: toNanos(3, "minutes"),
|
|
99
|
+
duplicate_window: toNanos(30, "seconds")
|
|
97
100
|
};
|
|
98
101
|
var DEFAULT_BROADCAST_STREAM_CONFIG = {
|
|
99
102
|
...baseStreamConfig,
|
|
@@ -104,10 +107,8 @@ var DEFAULT_BROADCAST_STREAM_CONFIG = {
|
|
|
104
107
|
max_msgs_per_subject: 1e6,
|
|
105
108
|
max_msgs: 1e7,
|
|
106
109
|
max_bytes: 2 * GB,
|
|
107
|
-
max_age:
|
|
108
|
-
|
|
109
|
-
duplicate_window: nanos(2 * 60 * 1e3)
|
|
110
|
-
// 2 min
|
|
110
|
+
max_age: toNanos(1, "days"),
|
|
111
|
+
duplicate_window: toNanos(2, "minutes")
|
|
111
112
|
};
|
|
112
113
|
var DEFAULT_ORDERED_STREAM_CONFIG = {
|
|
113
114
|
...baseStreamConfig,
|
|
@@ -118,14 +119,11 @@ var DEFAULT_ORDERED_STREAM_CONFIG = {
|
|
|
118
119
|
max_msgs_per_subject: 5e6,
|
|
119
120
|
max_msgs: 5e7,
|
|
120
121
|
max_bytes: 5 * GB,
|
|
121
|
-
max_age:
|
|
122
|
-
|
|
123
|
-
duplicate_window: nanos(2 * 60 * 1e3)
|
|
124
|
-
// 2 min
|
|
122
|
+
max_age: toNanos(1, "days"),
|
|
123
|
+
duplicate_window: toNanos(2, "minutes")
|
|
125
124
|
};
|
|
126
125
|
var DEFAULT_EVENT_CONSUMER_CONFIG = {
|
|
127
|
-
ack_wait:
|
|
128
|
-
// 10s
|
|
126
|
+
ack_wait: toNanos(10, "seconds"),
|
|
129
127
|
max_deliver: 3,
|
|
130
128
|
max_ack_pending: 100,
|
|
131
129
|
ack_policy: AckPolicy.Explicit,
|
|
@@ -133,8 +131,7 @@ var DEFAULT_EVENT_CONSUMER_CONFIG = {
|
|
|
133
131
|
replay_policy: ReplayPolicy.Instant
|
|
134
132
|
};
|
|
135
133
|
var DEFAULT_COMMAND_CONSUMER_CONFIG = {
|
|
136
|
-
ack_wait:
|
|
137
|
-
// 5 min
|
|
134
|
+
ack_wait: toNanos(5, "minutes"),
|
|
138
135
|
max_deliver: 1,
|
|
139
136
|
max_ack_pending: 100,
|
|
140
137
|
ack_policy: AckPolicy.Explicit,
|
|
@@ -142,8 +139,7 @@ var DEFAULT_COMMAND_CONSUMER_CONFIG = {
|
|
|
142
139
|
replay_policy: ReplayPolicy.Instant
|
|
143
140
|
};
|
|
144
141
|
var DEFAULT_BROADCAST_CONSUMER_CONFIG = {
|
|
145
|
-
ack_wait:
|
|
146
|
-
// 10s
|
|
142
|
+
ack_wait: toNanos(10, "seconds"),
|
|
147
143
|
max_deliver: 3,
|
|
148
144
|
max_ack_pending: 100,
|
|
149
145
|
ack_policy: AckPolicy.Explicit,
|
|
@@ -2348,6 +2344,5 @@ export {
|
|
|
2348
2344
|
RpcContext,
|
|
2349
2345
|
TransportEvent,
|
|
2350
2346
|
getClientToken,
|
|
2351
|
-
|
|
2347
|
+
toNanos
|
|
2352
2348
|
};
|
|
2353
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@horizon-republic/nestjs-jetstream",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "A NestJS transport for NATS with JetStream events, broadcast fan-out, and Core/JetStream RPC.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
48
48
|
"dist",
|
|
49
|
+
"!dist/*.map",
|
|
49
50
|
"README.md",
|
|
50
51
|
"LICENSE"
|
|
51
52
|
],
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/jetstream.module.ts","../src/client/jetstream.client.ts","../src/interfaces/hooks.interface.ts","../src/jetstream.constants.ts","../src/client/jetstream.record.ts","../src/codec/json.codec.ts","../src/connection/connection.provider.ts","../src/hooks/event-bus.ts","../src/health/jetstream.health-indicator.ts","../src/server/strategy.ts","../src/server/core-rpc.server.ts","../src/context/rpc.context.ts","../src/utils/serialize-error.ts","../src/utils/unwrap-result.ts","../src/server/infrastructure/stream.provider.ts","../src/server/infrastructure/consumer.provider.ts","../src/server/infrastructure/message.provider.ts","../src/server/routing/pattern-registry.ts","../src/server/routing/event.router.ts","../src/server/routing/rpc.router.ts","../src/shutdown/shutdown.manager.ts"],"sourcesContent":["// Module\nexport { JetstreamModule } from './jetstream.module';\n\n// Interfaces\nexport { TransportEvent } from './interfaces';\n\nexport type {\n Codec,\n DeadLetterInfo,\n JetstreamFeatureOptions,\n JetstreamModuleAsyncOptions,\n JetstreamModuleOptions,\n OrderedEventOverrides,\n RpcConfig,\n StreamConsumerOverrides,\n TransportHooks,\n} from './interfaces';\n\n// Client\nexport { JetstreamClient } from './client';\n\nexport { JetstreamRecord, JetstreamRecordBuilder } from './client';\n\n// Codec\nexport { JsonCodec } from './codec';\n\n// Context\nexport { RpcContext } from './context';\n\n// Health\nexport { JetstreamHealthIndicator } from './health';\n\nexport type { JetstreamHealthStatus } from './health';\n\n// Constants (selective — only what users need)\nexport {\n getClientToken,\n JetstreamHeader,\n JETSTREAM_CODEC,\n JETSTREAM_CONNECTION,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n nanos,\n} from './jetstream.constants';\n\n// Hooks\nexport { EventBus } from './hooks';\n\n// Server (for advanced use cases)\nexport { JetstreamStrategy } from './server';\n","import {\n DynamicModule,\n Global,\n Inject,\n Logger,\n Module,\n OnApplicationShutdown,\n Optional,\n Provider,\n} from '@nestjs/common';\n\nimport { JetstreamClient } from './client';\nimport { JsonCodec } from './codec';\nimport { ConnectionProvider } from './connection';\nimport { EventBus } from './hooks';\nimport { JetstreamHealthIndicator } from './health';\nimport type {\n Codec,\n JetstreamFeatureOptions,\n JetstreamModuleAsyncOptions,\n JetstreamModuleOptions,\n} from './interfaces';\nimport {\n DEFAULT_SHUTDOWN_TIMEOUT,\n getClientToken,\n JETSTREAM_CODEC,\n JETSTREAM_CONNECTION,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n} from './jetstream.constants';\nimport {\n CoreRpcServer,\n ConsumerProvider,\n EventRouter,\n JetstreamStrategy,\n MessageProvider,\n PatternRegistry,\n RpcRouter,\n StreamProvider,\n} from './server';\nimport type { DeadLetterConfig } from './server';\nimport { ShutdownManager } from './shutdown';\n\n/**\n * Root module for the NestJS JetStream transport.\n *\n * - `forRoot()` / `forRootAsync()` — registers once in AppModule.\n * Creates shared NATS connection, codec, event bus, and optionally\n * the consumer infrastructure.\n *\n * - `forFeature()` — registers in feature modules.\n * Creates a lightweight client proxy targeting a specific service.\n *\n * @example\n * ```typescript\n * // AppModule — global setup\n * @Module({\n * imports: [\n * JetstreamModule.forRoot({\n * name: 'orders',\n * servers: ['nats://localhost:4222'],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // Feature module — per-service clients\n * @Module({\n * imports: [\n * JetstreamModule.forFeature({ name: 'users' }),\n * JetstreamModule.forFeature({ name: 'payments' }),\n * ],\n * })\n * export class OrdersModule {}\n * ```\n */\n@Global()\n@Module({})\nexport class JetstreamModule implements OnApplicationShutdown {\n public constructor(\n @Optional()\n @Inject(ShutdownManager)\n private readonly shutdownManager?: ShutdownManager,\n @Optional() @Inject(JetstreamStrategy) private readonly strategy?: JetstreamStrategy | null,\n ) {}\n\n // -------------------------------------------------------------------\n // forRoot — global module registration\n // -------------------------------------------------------------------\n\n /**\n * Register the JetStream transport globally.\n *\n * Creates a shared NATS connection, codec, event bus, and optionally\n * the full consumer infrastructure (streams, consumers, routers).\n *\n * @param options Module configuration.\n * @returns Dynamic module ready to be imported.\n */\n public static forRoot(options: JetstreamModuleOptions): DynamicModule {\n const providers = this.createCoreProviders(options);\n\n return {\n module: JetstreamModule,\n global: true,\n providers,\n exports: [\n JETSTREAM_CONNECTION,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n ShutdownManager,\n JetstreamStrategy,\n JetstreamHealthIndicator,\n ],\n };\n }\n\n // -------------------------------------------------------------------\n // forRootAsync — async global module registration\n // -------------------------------------------------------------------\n\n /**\n * Register the JetStream transport globally with async configuration.\n *\n * Supports `useFactory`, `useExisting`, and `useClass` patterns\n * for loading configuration from ConfigService, environment, etc.\n *\n * @param asyncOptions Async configuration.\n * @returns Dynamic module ready to be imported.\n */\n public static forRootAsync(asyncOptions: JetstreamModuleAsyncOptions): DynamicModule {\n const asyncProviders = this.createAsyncOptionsProvider(asyncOptions);\n const coreProviders = this.createCoreDependentProviders();\n\n return {\n module: JetstreamModule,\n global: true,\n imports: asyncOptions.imports ?? [],\n providers: [...asyncProviders, ...coreProviders],\n exports: [\n JETSTREAM_CONNECTION,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n ShutdownManager,\n JetstreamStrategy,\n JetstreamHealthIndicator,\n ],\n };\n }\n\n // -------------------------------------------------------------------\n // forFeature — per-module client registration\n // -------------------------------------------------------------------\n\n /**\n * Register a lightweight client proxy for a target service.\n *\n * Reuses the shared NATS connection from `forRoot()`.\n * Import in each feature module that needs to communicate with a specific service.\n *\n * @param options Feature options with target service name.\n * @returns Dynamic module with the client provider.\n */\n public static forFeature(options: JetstreamFeatureOptions): DynamicModule {\n const clientToken = getClientToken(options.name);\n\n const clientProvider: Provider = {\n provide: clientToken,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION, JETSTREAM_CODEC, JETSTREAM_EVENT_BUS],\n useFactory: (\n rootOptions: JetstreamModuleOptions,\n connection: ConnectionProvider,\n rootCodec: Codec,\n eventBus: EventBus,\n ) => {\n const codec = options.codec ?? rootCodec;\n\n return new JetstreamClient(rootOptions, options.name, connection, codec, eventBus);\n },\n };\n\n return {\n module: JetstreamModule,\n providers: [clientProvider],\n exports: [clientToken],\n };\n }\n\n // -------------------------------------------------------------------\n // Provider factories\n // -------------------------------------------------------------------\n\n private static createCoreProviders(options: JetstreamModuleOptions): Provider[] {\n return [\n {\n provide: JETSTREAM_OPTIONS,\n useValue: options,\n },\n ...this.createCoreDependentProviders(),\n ];\n }\n\n /** Create providers that depend on JETSTREAM_OPTIONS (shared by sync and async). */\n private static createCoreDependentProviders(): Provider[] {\n return [\n // EventBus — hook system with Logger fallback\n {\n provide: JETSTREAM_EVENT_BUS,\n inject: [JETSTREAM_OPTIONS],\n useFactory: (options: JetstreamModuleOptions): EventBus => {\n const logger = new Logger('Jetstream:Module');\n\n return new EventBus(logger, options.hooks);\n },\n },\n\n // Codec — global encode/decode\n {\n provide: JETSTREAM_CODEC,\n inject: [JETSTREAM_OPTIONS],\n useFactory: (options: JetstreamModuleOptions): Codec => {\n return options.codec ?? new JsonCodec();\n },\n },\n\n // ConnectionProvider — single NATS connection\n {\n provide: JETSTREAM_CONNECTION,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_EVENT_BUS],\n useFactory: (options: JetstreamModuleOptions, eventBus: EventBus): ConnectionProvider => {\n return new ConnectionProvider(options, eventBus);\n },\n },\n\n // JetstreamHealthIndicator — health check for NATS connection\n {\n provide: JetstreamHealthIndicator,\n inject: [JETSTREAM_CONNECTION],\n useFactory: (connection: ConnectionProvider): JetstreamHealthIndicator => {\n return new JetstreamHealthIndicator(connection);\n },\n },\n\n // ShutdownManager — graceful shutdown orchestration\n {\n provide: ShutdownManager,\n inject: [JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS],\n useFactory: (\n connection: ConnectionProvider,\n eventBus: EventBus,\n options: JetstreamModuleOptions,\n ): ShutdownManager => {\n return new ShutdownManager(\n connection,\n eventBus,\n options.shutdownTimeout ?? DEFAULT_SHUTDOWN_TIMEOUT,\n );\n },\n },\n\n // ---------------------------------------------------------------\n // Consumer infrastructure — only created when consumer !== false.\n // Providers return null when consumer is disabled (publisher-only mode).\n // ---------------------------------------------------------------\n\n // PatternRegistry — subject-to-handler mapping\n {\n provide: PatternRegistry,\n inject: [JETSTREAM_OPTIONS],\n useFactory: (options: JetstreamModuleOptions): PatternRegistry | null => {\n if (options.consumer === false) return null;\n\n return new PatternRegistry(options);\n },\n },\n\n // StreamProvider — JetStream stream lifecycle\n {\n provide: StreamProvider,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n ): StreamProvider | null => {\n if (options.consumer === false) return null;\n\n return new StreamProvider(options, connection);\n },\n },\n\n // ConsumerProvider — JetStream consumer lifecycle (receives PatternRegistry for broadcast filtering)\n {\n provide: ConsumerProvider,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION, StreamProvider, PatternRegistry],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n streamProvider: StreamProvider,\n patternRegistry: PatternRegistry,\n ): ConsumerProvider | null => {\n if (options.consumer === false) return null;\n\n return new ConsumerProvider(options, connection, streamProvider, patternRegistry);\n },\n },\n\n // MessageProvider — pull-based message consumption\n {\n provide: MessageProvider,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n eventBus: EventBus,\n ): MessageProvider | null => {\n if (options.consumer === false) return null;\n\n return new MessageProvider(connection, eventBus);\n },\n },\n\n // EventRouter — routes event and broadcast messages to handlers\n {\n provide: EventRouter,\n inject: [\n JETSTREAM_OPTIONS,\n MessageProvider,\n PatternRegistry,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n messageProvider: MessageProvider,\n patternRegistry: PatternRegistry,\n codec: Codec,\n eventBus: EventBus,\n ): EventRouter | null => {\n if (options.consumer === false) return null;\n\n const deadLetterConfig: DeadLetterConfig | undefined = options.onDeadLetter\n ? {\n maxDeliverByStream: new Map(),\n onDeadLetter: options.onDeadLetter,\n }\n : undefined;\n\n return new EventRouter(\n messageProvider,\n patternRegistry,\n codec,\n eventBus,\n deadLetterConfig,\n );\n },\n },\n\n // RpcRouter — routes RPC command messages in JetStream mode\n {\n provide: RpcRouter,\n inject: [\n JETSTREAM_OPTIONS,\n MessageProvider,\n PatternRegistry,\n JETSTREAM_CONNECTION,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n messageProvider: MessageProvider,\n patternRegistry: PatternRegistry,\n connection: ConnectionProvider,\n codec: Codec,\n eventBus: EventBus,\n ): RpcRouter | null => {\n if (options.consumer === false) return null;\n\n const timeout = options.rpc?.mode === 'jetstream' ? options.rpc.timeout : undefined;\n\n return new RpcRouter(\n messageProvider,\n patternRegistry,\n connection,\n codec,\n eventBus,\n timeout,\n );\n },\n },\n\n // CoreRpcServer — RPC via NATS Core request/reply\n {\n provide: CoreRpcServer,\n inject: [\n JETSTREAM_OPTIONS,\n JETSTREAM_CONNECTION,\n PatternRegistry,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n patternRegistry: PatternRegistry,\n codec: Codec,\n eventBus: EventBus,\n ): CoreRpcServer | null => {\n if (options.consumer === false) return null;\n\n return new CoreRpcServer(options, connection, patternRegistry, codec, eventBus);\n },\n },\n\n // JetstreamStrategy — server-side transport (only when consumer enabled)\n {\n provide: JetstreamStrategy,\n inject: [\n JETSTREAM_OPTIONS,\n JETSTREAM_CONNECTION,\n PatternRegistry,\n StreamProvider,\n ConsumerProvider,\n MessageProvider,\n EventRouter,\n RpcRouter,\n CoreRpcServer,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n patternRegistry: PatternRegistry,\n streamProvider: StreamProvider,\n consumerProvider: ConsumerProvider,\n messageProvider: MessageProvider,\n eventRouter: EventRouter,\n rpcRouter: RpcRouter,\n coreRpcServer: CoreRpcServer,\n ): JetstreamStrategy | null => {\n if (options.consumer === false) return null;\n\n return new JetstreamStrategy(\n options,\n connection,\n patternRegistry,\n streamProvider,\n consumerProvider,\n messageProvider,\n eventRouter,\n rpcRouter,\n coreRpcServer,\n );\n },\n },\n ];\n }\n\n /** Create async options provider from useFactory/useExisting/useClass. */\n private static createAsyncOptionsProvider(asyncOptions: JetstreamModuleAsyncOptions): Provider[] {\n if (asyncOptions.useFactory) {\n const factory = asyncOptions.useFactory;\n\n return [\n {\n provide: JETSTREAM_OPTIONS,\n useFactory: async (...args: unknown[]): Promise<JetstreamModuleOptions> => {\n const partial = await factory(...args);\n\n return { ...partial, name: asyncOptions.name } satisfies JetstreamModuleOptions;\n },\n inject: asyncOptions.inject ?? [],\n },\n ];\n }\n\n if (asyncOptions.useExisting) {\n return [\n {\n provide: JETSTREAM_OPTIONS,\n useFactory: (config: Omit<JetstreamModuleOptions, 'name'>): JetstreamModuleOptions => ({\n ...config,\n name: asyncOptions.name,\n }),\n inject: [asyncOptions.useExisting],\n },\n ];\n }\n\n // useClass — guaranteed by the discriminated union after excluding useFactory and useExisting\n const useClass = asyncOptions.useClass;\n\n return [\n { provide: useClass, useClass },\n {\n provide: JETSTREAM_OPTIONS,\n useFactory: (config: Omit<JetstreamModuleOptions, 'name'>): JetstreamModuleOptions => ({\n ...config,\n name: asyncOptions.name,\n }),\n inject: [useClass],\n },\n ];\n }\n\n // -------------------------------------------------------------------\n // Lifecycle hooks\n // -------------------------------------------------------------------\n\n /**\n * Gracefully shut down the transport on application termination.\n */\n public async onApplicationShutdown(): Promise<void> {\n if (this.shutdownManager) {\n await this.shutdownManager.shutdown(this.strategy ?? undefined);\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { ClientProxy, ReadPacket, WritePacket } from '@nestjs/microservices';\nimport {\n createInbox,\n Events,\n headers as natsHeaders,\n Msg,\n MsgHdrs,\n NatsConnection,\n Subscription,\n} from 'nats';\nimport { Subscription as RxSubscription } from 'rxjs';\n\nimport { ConnectionProvider } from '../connection';\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport type {\n Codec,\n ExtractedRecordData,\n JetstreamModuleOptions,\n TransportHeaderOptions,\n} from '../interfaces';\nimport {\n buildBroadcastSubject,\n buildSubject,\n DEFAULT_JETSTREAM_RPC_TIMEOUT,\n DEFAULT_RPC_TIMEOUT,\n internalName,\n JetstreamHeader,\n} from '../jetstream.constants';\n\nimport { JetstreamRecord } from './jetstream.record';\n\n/**\n * NestJS ClientProxy implementation for the JetStream transport.\n *\n * Supports two operational modes:\n * - **Core mode** (default): Uses `nc.request()` for RPC, `nc.publish()` for events.\n * - **JetStream mode**: Uses `js.publish()` for RPC commands + inbox for responses.\n *\n * Events always go through JetStream publish for guaranteed delivery.\n * The mode only affects RPC (request/reply) behavior.\n *\n * Clients are lightweight — they share the NATS connection from `forRoot()`.\n */\nexport class JetstreamClient extends ClientProxy {\n private readonly logger = new Logger('Jetstream:Client');\n\n /** Target service name this client sends messages to. */\n private readonly targetName: string;\n\n /** Shared inbox for JetStream-mode RPC responses. */\n private inbox: string | null = null;\n private inboxSubscription: Subscription | null = null;\n\n /** Pending JetStream-mode RPC callbacks, keyed by correlation ID. */\n private readonly pendingMessages = new Map<string, (p: WritePacket) => void>();\n\n /** Pending JetStream-mode RPC timeouts, keyed by correlation ID. */\n private readonly pendingTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Subscription to connection status events for disconnect handling. */\n private statusSubscription: RxSubscription | null = null;\n\n public constructor(\n private readonly rootOptions: JetstreamModuleOptions,\n targetServiceName: string,\n private readonly connection: ConnectionProvider,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n ) {\n super();\n this.targetName = targetServiceName;\n }\n\n /**\n * Establish connection. Called automatically by NestJS on first use.\n *\n * Sets up the JetStream RPC inbox (if in JetStream mode) and subscribes\n * to connection status events for fail-fast disconnect handling.\n *\n * @returns The underlying NATS connection.\n */\n public async connect(): Promise<NatsConnection> {\n const nc = await this.connection.getConnection();\n\n // Setup inbox for JetStream RPC mode\n if (this.isJetStreamRpcMode() && !this.inboxSubscription) {\n this.setupInbox(nc);\n }\n\n // Subscribe to disconnect events (once)\n this.statusSubscription ??= this.connection.status$.subscribe((status) => {\n if (status.type === Events.Disconnect) {\n this.handleDisconnect();\n }\n });\n\n return nc;\n }\n\n /** Clean up resources: reject pending RPCs, unsubscribe from status events. */\n public async close(): Promise<void> {\n this.statusSubscription?.unsubscribe();\n this.statusSubscription = null;\n this.rejectPendingRpcs(new Error('Client closed'));\n }\n\n /**\n * Direct access to the raw NATS connection.\n *\n * @throws Error if not connected.\n */\n public override unwrap<T = NatsConnection>(): T {\n const nc = this.connection.unwrap;\n\n if (!nc) {\n throw new Error('Not connected — call connect() before unwrap()');\n }\n\n return nc as T;\n }\n\n /**\n * Publish a fire-and-forget event to JetStream.\n *\n * Events are published to either the workqueue stream or broadcast stream\n * depending on the subject prefix.\n */\n protected async dispatchEvent<T = unknown>(packet: ReadPacket): Promise<T> {\n const nc = await this.connect();\n const { data, hdrs, messageId } = this.extractRecordData(packet.data);\n\n // Determine if this is a broadcast event\n // Broadcast subjects start with 'broadcast:'\n const subject = this.buildEventSubject(packet.pattern);\n const msgHeaders = this.buildHeaders(hdrs, { subject });\n\n const ack = await nc.jetstream().publish(subject, this.codec.encode(data), {\n headers: msgHeaders,\n msgID: messageId ?? crypto.randomUUID(),\n });\n\n if (ack.duplicate) {\n this.logger.warn(`Duplicate event publish detected: ${subject} (seq: ${ack.seq})`);\n }\n\n return undefined as T;\n }\n\n /**\n * Publish an RPC command and register callback for response.\n *\n * Core mode: uses nc.request() with timeout.\n * JetStream mode: publishes to stream + waits for inbox response.\n */\n protected publish(packet: ReadPacket, callback: (p: WritePacket) => void): () => void {\n const subject = buildSubject(this.targetName, 'cmd', packet.pattern);\n const { data, hdrs, timeout, messageId } = this.extractRecordData(packet.data);\n\n const onUnhandled = (err: unknown): void => {\n this.logger.error('Unhandled publish error:', err);\n callback({ err: new Error('Internal transport error'), response: null, isDisposed: true });\n };\n\n // Track correlation ID for cleanup in JetStream mode\n let jetStreamCorrelationId: string | null = null;\n\n if (this.isCoreRpcMode()) {\n this.publishCoreRpc(subject, data, hdrs, timeout, callback).catch(onUnhandled);\n } else {\n jetStreamCorrelationId = crypto.randomUUID();\n this.publishJetStreamRpc(\n subject,\n data,\n hdrs,\n timeout,\n callback,\n jetStreamCorrelationId,\n messageId,\n ).catch(onUnhandled);\n }\n\n return () => {\n // Cleanup for JetStream mode pending messages\n // Core mode cleanup is handled by NATS internally\n if (jetStreamCorrelationId) {\n const timeoutId = this.pendingTimeouts.get(jetStreamCorrelationId);\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(jetStreamCorrelationId);\n }\n\n this.pendingMessages.delete(jetStreamCorrelationId);\n }\n };\n }\n\n /** Core mode: nc.request() with timeout. */\n private async publishCoreRpc(\n subject: string,\n data: unknown,\n customHeaders: Map<string, string> | null,\n timeout: number | undefined,\n callback: (p: WritePacket) => void,\n ): Promise<void> {\n try {\n const nc = await this.connect();\n const effectiveTimeout = timeout ?? this.getRpcTimeout();\n const hdrs = this.buildHeaders(customHeaders, { subject });\n\n const response = await nc.request(subject, this.codec.encode(data), {\n timeout: effectiveTimeout,\n headers: hdrs,\n });\n\n const decoded = this.codec.decode(response.data);\n\n if (response.headers?.get(JetstreamHeader.Error)) {\n callback({ err: decoded, response: null, isDisposed: true });\n } else {\n callback({ err: null, response: decoded, isDisposed: true });\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Unknown error');\n\n this.logger.error(`Core RPC error (${subject}):`, err);\n this.eventBus.emit(TransportEvent.Error, error, 'client-rpc');\n callback({ err: error, response: null, isDisposed: true });\n }\n }\n\n /** JetStream mode: publish to stream + wait for inbox response. */\n private async publishJetStreamRpc(\n subject: string,\n data: unknown,\n customHeaders: Map<string, string> | null,\n timeout: number | undefined,\n callback: (p: WritePacket) => void,\n correlationId: string = crypto.randomUUID(),\n messageId?: string,\n ): Promise<void> {\n const effectiveTimeout = timeout ?? this.getRpcTimeout();\n\n this.pendingMessages.set(correlationId, callback);\n\n const timeoutId = setTimeout(() => {\n if (!this.pendingMessages.has(correlationId)) return;\n\n this.pendingTimeouts.delete(correlationId);\n this.pendingMessages.delete(correlationId);\n this.logger.error(`JetStream RPC timeout (${effectiveTimeout}ms): ${subject}`);\n this.eventBus.emit(TransportEvent.RpcTimeout, subject, correlationId);\n callback({ err: new Error('RPC timeout'), response: null, isDisposed: true });\n }, effectiveTimeout);\n\n this.pendingTimeouts.set(correlationId, timeoutId);\n\n try {\n const nc = await this.connect();\n\n if (!this.inbox) {\n throw new Error('Inbox not initialized — JetStream RPC mode requires a connected inbox');\n }\n\n const hdrs = this.buildHeaders(customHeaders, {\n subject,\n correlationId,\n replyTo: this.inbox,\n });\n\n await nc.jetstream().publish(subject, this.codec.encode(data), {\n headers: hdrs,\n msgID: messageId ?? crypto.randomUUID(),\n });\n } catch (err) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(correlationId);\n\n if (!this.pendingMessages.has(correlationId)) return;\n\n this.pendingMessages.delete(correlationId);\n const error = err instanceof Error ? err : new Error('Unknown error');\n\n this.logger.error(`JetStream RPC publish error (${subject}):`, err);\n callback({ err: error, response: null, isDisposed: true });\n }\n }\n\n /** Fail-fast all pending JetStream RPC callbacks on connection loss. */\n private handleDisconnect(): void {\n this.rejectPendingRpcs(new Error('Connection lost'));\n\n // Reset inbox — will be recreated on next connect()\n this.inbox = null;\n }\n\n /** Reject all pending RPC callbacks, clear timeouts, and tear down inbox. */\n private rejectPendingRpcs(error: Error): void {\n for (const callback of this.pendingMessages.values()) {\n callback({ err: error, response: null, isDisposed: true });\n }\n\n for (const timeoutId of this.pendingTimeouts.values()) {\n clearTimeout(timeoutId);\n }\n\n this.pendingMessages.clear();\n this.pendingTimeouts.clear();\n this.inboxSubscription?.unsubscribe();\n this.inboxSubscription = null;\n }\n\n /** Setup shared inbox subscription for JetStream RPC responses. */\n private setupInbox(nc: NatsConnection): void {\n this.inbox = createInbox(internalName(this.rootOptions.name));\n\n this.inboxSubscription = nc.subscribe(this.inbox, {\n callback: (err, msg) => {\n if (err) {\n this.logger.error('Inbox subscription error:', err);\n return;\n }\n\n this.routeInboxReply(msg);\n },\n });\n\n this.logger.debug(`Inbox subscription: ${this.inbox}`);\n }\n\n /** Route an inbox reply to the matching pending callback. */\n private routeInboxReply(msg: Msg): void {\n const correlationId = msg.headers?.get(JetstreamHeader.CorrelationId);\n\n if (!correlationId) {\n this.logger.warn('Inbox reply without correlation-id, ignoring');\n return;\n }\n\n const callback = this.pendingMessages.get(correlationId);\n\n if (!callback) {\n this.logger.warn(`No pending handler for correlation-id: ${correlationId}`);\n return;\n }\n\n const timeoutId = this.pendingTimeouts.get(correlationId);\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(correlationId);\n }\n\n try {\n const decoded = this.codec.decode(msg.data);\n\n if (msg.headers?.get(JetstreamHeader.Error)) {\n callback({ err: decoded, response: null, isDisposed: true });\n } else {\n callback({ err: null, response: decoded, isDisposed: true });\n }\n } catch (err) {\n callback({\n err: err instanceof Error ? err : new Error('Decode error'),\n response: null,\n isDisposed: true,\n });\n } finally {\n this.pendingMessages.delete(correlationId);\n }\n }\n\n /** Build event subject — workqueue, broadcast, or ordered. */\n private buildEventSubject(pattern: string): string {\n // Convention: 'broadcast:' prefix routes to the shared broadcast stream.\n if (pattern.startsWith('broadcast:')) {\n return buildBroadcastSubject(pattern.slice('broadcast:'.length));\n }\n\n // Convention: 'ordered:' prefix routes to the ordered stream.\n if (pattern.startsWith('ordered:')) {\n return buildSubject(this.targetName, 'ordered', pattern.slice('ordered:'.length));\n }\n\n return buildSubject(this.targetName, 'ev', pattern);\n }\n\n /** Build NATS headers merging custom headers with transport headers. */\n private buildHeaders(\n customHeaders: Map<string, string> | null,\n transport: TransportHeaderOptions,\n ): MsgHdrs {\n const hdrs = natsHeaders();\n\n // Set transport headers\n hdrs.set(JetstreamHeader.Subject, transport.subject);\n hdrs.set(JetstreamHeader.CallerName, internalName(this.rootOptions.name));\n\n if (transport.correlationId) {\n hdrs.set(JetstreamHeader.CorrelationId, transport.correlationId);\n }\n\n if (transport.replyTo) {\n hdrs.set(JetstreamHeader.ReplyTo, transport.replyTo);\n }\n\n // Merge user headers (reserved headers already validated by JetstreamRecordBuilder)\n if (customHeaders) {\n for (const [key, value] of customHeaders) {\n hdrs.set(key, value);\n }\n }\n\n return hdrs;\n }\n\n /** Extract data, headers, and timeout from raw packet data or JetstreamRecord. */\n private extractRecordData(rawData: unknown): ExtractedRecordData {\n if (rawData instanceof JetstreamRecord) {\n return {\n data: rawData.data,\n hdrs: rawData.headers.size > 0 ? new Map(rawData.headers) : null,\n timeout: rawData.timeout,\n messageId: rawData.messageId,\n };\n }\n\n return { data: rawData, hdrs: null, timeout: undefined, messageId: undefined };\n }\n\n private isCoreRpcMode(): boolean {\n return !this.rootOptions.rpc || this.rootOptions.rpc.mode === 'core';\n }\n\n private isJetStreamRpcMode(): boolean {\n return this.rootOptions.rpc?.mode === 'jetstream';\n }\n\n private getRpcTimeout(): number {\n if (!this.rootOptions.rpc) return DEFAULT_RPC_TIMEOUT;\n\n const defaultTimeout = this.isJetStreamRpcMode()\n ? DEFAULT_JETSTREAM_RPC_TIMEOUT\n : DEFAULT_RPC_TIMEOUT;\n\n return this.rootOptions.rpc.timeout ?? defaultTimeout;\n }\n}\n","import type { MsgHdrs } from 'nats';\n\nexport enum TransportEvent {\n Connect = 'connect',\n Disconnect = 'disconnect',\n Reconnect = 'reconnect',\n Error = 'error',\n RpcTimeout = 'rpcTimeout',\n MessageRouted = 'messageRouted',\n ShutdownStart = 'shutdownStart',\n ShutdownComplete = 'shutdownComplete',\n DeadLetter = 'deadLetter',\n}\n\n/**\n * Hook callbacks for transport lifecycle and operational events.\n *\n * Events without a registered hook are silently ignored.\n * Register hooks via `forRoot({ hooks: { ... } })` for monitoring,\n * alerting, or custom observability integration.\n *\n * @example\n * ```typescript\n * JetstreamModule.forRoot({\n * hooks: {\n * [TransportEvent.Error]: (error, context) => sentry.captureException(error),\n * [TransportEvent.RpcTimeout]: (subject) => metrics.increment('rpc.timeout'),\n * },\n * })\n * ```\n */\nexport interface TransportHooks {\n /** Fired when NATS connection is established. */\n [TransportEvent.Connect](server: string): void;\n\n /** Fired when NATS connection is lost. */\n [TransportEvent.Disconnect](): void;\n\n /** Fired when NATS connection is re-established after a disconnect. */\n [TransportEvent.Reconnect](server: string): void;\n\n /** Fired on any transport-level error. */\n [TransportEvent.Error](error: Error, context?: string): void;\n\n /** Fired when an RPC handler exceeds its timeout. */\n [TransportEvent.RpcTimeout](subject: string, correlationId: string): void;\n\n /** Fired after a message is successfully routed to its handler. */\n [TransportEvent.MessageRouted](subject: string, kind: 'rpc' | 'event'): void;\n\n /** Fired at the start of the graceful shutdown sequence. */\n [TransportEvent.ShutdownStart](): void;\n\n /** Fired after graceful shutdown completes. */\n [TransportEvent.ShutdownComplete](): void;\n\n /** Fired when a message exhausts all delivery attempts (dead letter). */\n [TransportEvent.DeadLetter](info: DeadLetterInfo): void;\n}\n\n/**\n * Context passed to the onDeadLetter callback when a message exhausts all delivery attempts.\n */\nexport interface DeadLetterInfo {\n /** The NATS subject the message was published to. */\n subject: string;\n /** Decoded message payload. */\n data: unknown;\n /** Message headers (raw NATS MsgHdrs). */\n headers: MsgHdrs | undefined;\n /** The error that caused the last handler failure. */\n error: unknown;\n /** How many times this message was delivered. */\n deliveryCount: number;\n /** The stream this message belongs to. */\n stream: string;\n /** The stream sequence number. */\n streamSequence: number;\n /** ISO timestamp of the message (derived from msg.info.timestampNanos). */\n timestamp: string;\n}\n","import {\n AckPolicy,\n DeliverPolicy,\n DiscardPolicy,\n ReplayPolicy,\n RetentionPolicy,\n StorageType,\n StoreCompression,\n} from 'nats';\nimport type { ConsumerConfig, StreamConfig } from 'nats';\n\nimport type { StreamKind, SubjectKind } from './interfaces';\n\n// ---------------------------------------------------------------------------\n// Injection Tokens\n// ---------------------------------------------------------------------------\n\n/** Token for the resolved JetstreamModuleOptions. */\nexport const JETSTREAM_OPTIONS = Symbol('JETSTREAM_OPTIONS');\n\n/** Token for the shared ConnectionProvider instance. */\nexport const JETSTREAM_CONNECTION = Symbol('JETSTREAM_CONNECTION');\n\n/** Token for the global Codec instance. */\nexport const JETSTREAM_CODEC = Symbol('JETSTREAM_CODEC');\n\n/** Token for the EventBus instance. */\nexport const JETSTREAM_EVENT_BUS = Symbol('JETSTREAM_EVENT_BUS');\n\n/**\n * Generate the injection token for a `forFeature()` client.\n *\n * Use with `@Inject()` to inject the client created by `JetstreamModule.forFeature()`.\n *\n * @param name - The service name passed to `forFeature({ name })`.\n * @returns The DI token string.\n *\n * @example\n * ```typescript\n * @Inject(getClientToken('orders'))\n * private readonly ordersClient: JetstreamClient;\n * ```\n */\nexport const getClientToken = (name: string): string => name;\n\n// ---------------------------------------------------------------------------\n// Size & Time Helpers\n// ---------------------------------------------------------------------------\n\nconst KB = 1024;\nconst MB = 1024 * KB;\nconst GB = 1024 * MB;\n\n/**\n * Convert milliseconds to nanoseconds (NATS JetStream format).\n *\n * @param ms - Duration in milliseconds.\n * @returns Duration in nanoseconds.\n *\n * @example\n * ```typescript\n * // Set consumer ack_wait to 30 seconds\n * { ack_wait: nanos(30_000) }\n * ```\n */\nexport const nanos = (ms: number): number => ms * 1_000_000;\n\n// ---------------------------------------------------------------------------\n// Default Stream Configurations\n// ---------------------------------------------------------------------------\n\n/* eslint-disable @typescript-eslint/naming-convention -- NATS API uses snake_case property names */\n\n/** Base stream config shared by all stream types. */\nconst baseStreamConfig: Partial<StreamConfig> = {\n retention: RetentionPolicy.Workqueue,\n storage: StorageType.File,\n num_replicas: 1,\n discard: DiscardPolicy.Old,\n allow_direct: true,\n compression: StoreCompression.None,\n};\n\n/** Default config for workqueue event streams. */\nexport const DEFAULT_EVENT_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n allow_rollup_hdrs: true,\n max_consumers: 100,\n max_msg_size: 10 * MB,\n max_msgs_per_subject: 5_000_000,\n max_msgs: 50_000_000,\n max_bytes: 5 * GB,\n max_age: nanos(7 * 24 * 60 * 60 * 1000), // 7 days\n duplicate_window: nanos(2 * 60 * 1000), // 2 min\n};\n\n/** Default config for RPC command streams (jetstream mode only). */\nexport const DEFAULT_COMMAND_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n allow_rollup_hdrs: false,\n max_consumers: 50,\n max_msg_size: 5 * MB,\n max_msgs_per_subject: 100_000,\n max_msgs: 1_000_000,\n max_bytes: 100 * MB,\n max_age: nanos(3 * 60 * 1000), // 3 min\n duplicate_window: nanos(30 * 1000), // 30s\n};\n\n/** Default config for broadcast event streams. */\nexport const DEFAULT_BROADCAST_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n retention: RetentionPolicy.Limits,\n allow_rollup_hdrs: true,\n max_consumers: 200,\n max_msg_size: 10 * MB,\n max_msgs_per_subject: 1_000_000,\n max_msgs: 10_000_000,\n max_bytes: 2 * GB,\n max_age: nanos(24 * 60 * 60 * 1000), // 1 day\n duplicate_window: nanos(2 * 60 * 1000), // 2 min\n};\n\n/** Default config for ordered event streams (Limits retention). */\nexport const DEFAULT_ORDERED_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n retention: RetentionPolicy.Limits,\n allow_rollup_hdrs: false,\n max_consumers: 100,\n max_msg_size: 10 * MB,\n max_msgs_per_subject: 5_000_000,\n max_msgs: 50_000_000,\n max_bytes: 5 * GB,\n max_age: nanos(24 * 60 * 60 * 1000), // 1 day\n duplicate_window: nanos(2 * 60 * 1000), // 2 min\n};\n\n// ---------------------------------------------------------------------------\n// Default Consumer Configurations\n// ---------------------------------------------------------------------------\n\n/** Default config for workqueue event consumers. */\nexport const DEFAULT_EVENT_CONSUMER_CONFIG: Partial<ConsumerConfig> = {\n ack_wait: nanos(10 * 1000), // 10s\n max_deliver: 3,\n max_ack_pending: 100,\n ack_policy: AckPolicy.Explicit,\n deliver_policy: DeliverPolicy.All,\n replay_policy: ReplayPolicy.Instant,\n};\n\n/** Default config for RPC command consumers (jetstream mode only). */\nexport const DEFAULT_COMMAND_CONSUMER_CONFIG: Partial<ConsumerConfig> = {\n ack_wait: nanos(5 * 60 * 1000), // 5 min\n max_deliver: 1,\n max_ack_pending: 100,\n ack_policy: AckPolicy.Explicit,\n deliver_policy: DeliverPolicy.All,\n replay_policy: ReplayPolicy.Instant,\n};\n\n/** Default config for broadcast event consumers. */\nexport const DEFAULT_BROADCAST_CONSUMER_CONFIG: Partial<ConsumerConfig> = {\n ack_wait: nanos(10 * 1000), // 10s\n max_deliver: 3,\n max_ack_pending: 100,\n ack_policy: AckPolicy.Explicit,\n deliver_policy: DeliverPolicy.All,\n replay_policy: ReplayPolicy.Instant,\n};\n\n/* eslint-enable @typescript-eslint/naming-convention */\n\n// ---------------------------------------------------------------------------\n// Default Module Options\n// ---------------------------------------------------------------------------\n\n/** Default RPC timeout for Core mode (30 seconds). */\nexport const DEFAULT_RPC_TIMEOUT = 30_000;\n\n/** Default RPC timeout for JetStream mode (3 minutes). */\nexport const DEFAULT_JETSTREAM_RPC_TIMEOUT = 180_000;\n\n/** Default graceful shutdown timeout (10 seconds). */\nexport const DEFAULT_SHUTDOWN_TIMEOUT = 10_000;\n\n// ---------------------------------------------------------------------------\n// Reserved Headers\n// ---------------------------------------------------------------------------\n\n/**\n * NATS headers managed by the transport.\n *\n * These headers are set automatically on outbound messages.\n * Some are reserved ({@link RESERVED_HEADERS}) and cannot be overwritten\n * via `JetstreamRecordBuilder.setHeader()`.\n */\nexport enum JetstreamHeader {\n /** Unique ID linking an RPC request to its response. */\n CorrelationId = 'x-correlation-id',\n /** Inbox subject where the RPC response should be published. */\n ReplyTo = 'x-reply-to',\n /** Original subject the message was published to. */\n Subject = 'x-subject',\n /** Internal name of the service that sent the message. */\n CallerName = 'x-caller-name',\n /** Set to `'true'` on error responses so the client can distinguish success from failure. */\n Error = 'x-error',\n}\n\n/** Set of header names that are reserved and cannot be set by users. */\nexport const RESERVED_HEADERS = new Set<string>([\n JetstreamHeader.CorrelationId,\n JetstreamHeader.ReplyTo,\n JetstreamHeader.Error,\n]);\n\n// ---------------------------------------------------------------------------\n// Naming Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build the internal service name with microservice suffix.\n *\n * @param name - Service name from `forRoot({ name })`.\n * @returns `{name}__microservice`\n */\nexport const internalName = (name: string): string => `${name}__microservice`;\n\n/**\n * Build a fully-qualified NATS subject for workqueue events, RPC commands, or ordered events.\n *\n * @param serviceName - Target service name.\n * @param kind - Subject kind (`'ev'`, `'cmd'`, or `'ordered'`).\n * @param pattern - The message pattern (e.g. `'user.created'`).\n * @returns `{serviceName}__microservice.{kind}.{pattern}`\n */\nexport const buildSubject = (serviceName: string, kind: SubjectKind, pattern: string): string =>\n `${internalName(serviceName)}.${kind}.${pattern}`;\n\n/**\n * Build a broadcast subject.\n *\n * @param pattern - The message pattern (e.g. `'config.updated'`).\n * @returns `broadcast.{pattern}`\n */\nexport const buildBroadcastSubject = (pattern: string): string => `broadcast.${pattern}`;\n\n/**\n * Build the JetStream stream name for a given service and kind.\n *\n * @param serviceName - Service name from `forRoot({ name })`.\n * @param kind - Stream kind (`'ev'`, `'cmd'`, or `'broadcast'`).\n * @returns Stream name (e.g. `orders__microservice_ev-stream` or `broadcast-stream`).\n */\nexport const streamName = (serviceName: string, kind: StreamKind): string => {\n if (kind === 'broadcast') return 'broadcast-stream';\n return `${internalName(serviceName)}_${kind}-stream`;\n};\n\n/**\n * Build the JetStream consumer name for a given service and kind.\n *\n * @param serviceName - Service name from `forRoot({ name })`.\n * @param kind - Stream kind (`'ev'`, `'cmd'`, or `'broadcast'`).\n * @returns Consumer name (e.g. `orders__microservice_ev-consumer`).\n */\nexport const consumerName = (serviceName: string, kind: StreamKind): string => {\n if (kind === 'broadcast') return `${internalName(serviceName)}_broadcast-consumer`;\n return `${internalName(serviceName)}_${kind}-consumer`;\n};\n","import { RESERVED_HEADERS } from '../jetstream.constants';\n\n/**\n * Immutable message record for JetStream transport.\n *\n * Compatible with NestJS record builder pattern (like RmqRecord, NatsRecord).\n * Pass as the second argument to `client.send()` or `client.emit()`.\n *\n * @example\n * ```typescript\n * const record = new JetstreamRecordBuilder({ id: 1 })\n * .setHeader('x-tenant', 'acme')\n * .setTimeout(5000)\n * .build();\n *\n * client.send('get.user', record);\n * ```\n */\nexport class JetstreamRecord<TData = unknown> {\n public constructor(\n /** Message payload. */\n public readonly data: TData,\n /** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */\n public readonly headers: ReadonlyMap<string, string>,\n /** Per-request RPC timeout override in ms. */\n public readonly timeout?: number,\n /** Custom message ID for JetStream deduplication. */\n public readonly messageId?: string,\n ) {}\n}\n\n/**\n * Fluent builder for constructing JetstreamRecord instances.\n *\n * Protected headers (`correlation-id`, `reply-to`, `error`) cannot be\n * set by the user — attempting to do so throws an error at build time.\n */\nexport class JetstreamRecordBuilder<TData = unknown> {\n private data: TData | undefined;\n private readonly headers = new Map<string, string>();\n private timeout: number | undefined;\n private messageId: string | undefined;\n\n public constructor(data?: TData) {\n this.data = data;\n }\n\n /**\n * Set the message payload.\n *\n * @param data - Payload to serialize via the configured {@link Codec}.\n */\n public setData(data: TData): this {\n this.data = data;\n return this;\n }\n\n /**\n * Set a single custom header.\n *\n * @param key - Header name (e.g. `'x-tenant'`).\n * @param value - Header value.\n * @throws Error if the header name is reserved by the transport.\n */\n public setHeader(key: string, value: string): this {\n this.validateHeaderKey(key);\n this.headers.set(key, value);\n return this;\n }\n\n /**\n * Set multiple custom headers at once.\n *\n * @param headers - Key-value pairs to set as headers.\n * @throws Error if any header name is reserved by the transport.\n */\n public setHeaders(headers: Record<string, string>): this {\n for (const [key, value] of Object.entries(headers)) {\n this.setHeader(key, value);\n }\n\n return this;\n }\n\n /**\n * Set a custom message ID for JetStream deduplication.\n *\n * NATS JetStream uses this ID to detect duplicate publishes within the\n * stream's `duplicate_window`. If two messages with the same ID arrive\n * within the window, the second is silently dropped.\n *\n * When not set, a random UUID is generated automatically.\n *\n * @param id - Unique message identifier (e.g. order ID, idempotency key).\n *\n * @example\n * ```typescript\n * new JetstreamRecordBuilder(data)\n * .setMessageId(`order-${order.id}`)\n * .build();\n * ```\n */\n public setMessageId(id: string): this {\n this.messageId = id;\n return this;\n }\n\n /**\n * Set per-request RPC timeout.\n *\n * @param ms - Timeout in milliseconds. Overrides the global RPC timeout for this request only.\n */\n public setTimeout(ms: number): this {\n this.timeout = ms;\n return this;\n }\n\n /**\n * Build the immutable {@link JetstreamRecord}.\n *\n * @returns A frozen record ready to pass to `client.send()` or `client.emit()`.\n */\n public build(): JetstreamRecord<TData> {\n return new JetstreamRecord(\n this.data as TData,\n new Map(this.headers),\n this.timeout,\n this.messageId,\n );\n }\n\n /** Validate that a header key is not reserved. */\n private validateHeaderKey(key: string): void {\n if (RESERVED_HEADERS.has(key)) {\n throw new Error(\n `Header \"${key}\" is reserved by the JetStream transport and cannot be set manually. ` +\n `Reserved headers: ${[...RESERVED_HEADERS].join(', ')}`,\n );\n }\n }\n}\n","import { JSONCodec as NatsJSONCodec } from 'nats';\n\nimport type { Codec } from '../interfaces';\n\n/**\n * Default JSON codec wrapping the nats.js JSONCodec.\n *\n * Serializes to/from JSON using the native NATS implementation\n * which handles `TextEncoder`/`TextDecoder` internally.\n *\n * @example\n * ```typescript\n * const codec = new JsonCodec();\n * const bytes = codec.encode({ hello: 'world' });\n * const data = codec.decode(bytes); // { hello: 'world' }\n * ```\n */\nexport class JsonCodec implements Codec {\n private readonly inner = NatsJSONCodec();\n\n public encode(data: unknown): Uint8Array {\n return this.inner.encode(data);\n }\n\n public decode(data: Uint8Array): unknown {\n return this.inner.decode(data);\n }\n}\n","import { Logger } from '@nestjs/common';\nimport {\n connect,\n ConnectionOptions,\n DebugEvents,\n Events,\n JetStreamManager,\n NatsConnection,\n NatsError,\n Status,\n} from 'nats';\nimport { defer, from, Observable, share, shareReplay, switchMap } from 'rxjs';\n\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport type { JetstreamModuleOptions } from '../interfaces';\nimport { internalName } from '../jetstream.constants';\n\n/**\n * Manages the lifecycle of a single NATS connection shared across the application.\n *\n * Provides both Promise-based and Observable-based access to the connection:\n * - `connect()` / `getConnection()` — async/await for one-time setup\n * - `nc$` — cached observable (shareReplay) for reactive consumers\n * - `status$` — live connection status event stream\n *\n * One instance per application, created by `JetstreamModule.forRoot()`.\n */\nexport class ConnectionProvider {\n /** Cached observable that replays the established connection to new subscribers. */\n public readonly nc$: Observable<NatsConnection>;\n\n /** Live stream of connection status events (no replay). */\n public readonly status$: Observable<Status>;\n\n private readonly logger = new Logger('Jetstream:Connection');\n\n private connection: NatsConnection | null = null;\n private connectionPromise: Promise<NatsConnection> | null = null;\n private jsmInstance: JetStreamManager | null = null;\n private jsmPromise: Promise<JetStreamManager> | null = null;\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly eventBus: EventBus,\n ) {\n // Lazy observable — connects on first subscription, caches for all future subscribers\n this.nc$ = defer(() => this.getConnection()).pipe(\n shareReplay({ bufferSize: 1, refCount: false }),\n );\n\n this.status$ = this.nc$.pipe(\n switchMap((nc) => from(nc.status())),\n share(),\n );\n }\n\n /**\n * Establish NATS connection. Idempotent — returns cached connection on subsequent calls.\n *\n * @throws Error if connection is refused (fail fast).\n */\n public async getConnection(): Promise<NatsConnection> {\n if (this.connection && !this.connection.isClosed()) {\n return this.connection;\n }\n\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n this.connectionPromise = this.establish().catch((err) => {\n this.connectionPromise = null;\n throw err;\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Get the JetStream manager. Cached after first call.\n *\n * @returns The JetStreamManager for stream/consumer administration.\n */\n public async getJetStreamManager(): Promise<JetStreamManager> {\n if (this.jsmInstance) return this.jsmInstance;\n if (this.jsmPromise) return this.jsmPromise;\n\n this.jsmPromise = (async (): Promise<JetStreamManager> => {\n const nc = await this.getConnection();\n\n this.jsmInstance = await nc.jetstreamManager();\n this.logger.log('JetStream manager initialized');\n return this.jsmInstance;\n })().finally(() => {\n this.jsmPromise = null;\n });\n\n return this.jsmPromise;\n }\n\n /** Direct access to the raw NATS connection, or `null` if not yet connected. */\n public get unwrap(): NatsConnection | null {\n return this.connection;\n }\n\n /**\n * Gracefully shut down the connection.\n *\n * Sequence: drain → wait for close. Falls back to force-close on error.\n */\n public async shutdown(): Promise<void> {\n // Wait for in-flight connection to settle so it doesn't escape shutdown\n if (this.connectionPromise) {\n try {\n await this.connectionPromise;\n } catch {\n // Connection failed — nothing to shut down\n }\n }\n\n if (!this.connection || this.connection.isClosed()) return;\n\n try {\n await this.connection.drain();\n await this.connection.closed();\n } catch {\n try {\n await this.connection.close();\n } catch {\n // Best-effort — connection may already be gone\n }\n } finally {\n this.connection = null;\n this.connectionPromise = null;\n this.jsmInstance = null;\n this.jsmPromise = null;\n }\n }\n\n /** Internal: establish the physical connection with reconnect monitoring. */\n private async establish(): Promise<NatsConnection> {\n const name = internalName(this.options.name);\n\n try {\n const nc = await connect({\n ...this.options.connectionOptions,\n servers: this.options.servers,\n name,\n } as ConnectionOptions);\n\n this.connection = nc;\n this.logger.log(`NATS connection established: ${nc.getServer()}`);\n this.eventBus.emit(TransportEvent.Connect, nc.getServer());\n\n this.monitorStatus(nc);\n\n return nc;\n } catch (err) {\n if (err instanceof NatsError && err.code === 'CONNECTION_REFUSED') {\n throw new Error(`NATS connection refused: ${this.options.servers.join(', ')}`);\n }\n\n throw err;\n }\n }\n\n /** Subscribe to connection status events and emit hooks. */\n private monitorStatus(nc: NatsConnection): void {\n (async (): Promise<void> => {\n for await (const status of nc.status()) {\n switch (status.type) {\n case Events.Disconnect:\n this.eventBus.emit(TransportEvent.Disconnect);\n break;\n case Events.Reconnect:\n this.jsmInstance = null;\n this.jsmPromise = null;\n this.eventBus.emit(TransportEvent.Reconnect, nc.getServer());\n break;\n case Events.Error:\n this.eventBus.emit(TransportEvent.Error, new Error(String(status.data)), 'connection');\n break;\n case Events.Update:\n case Events.LDM:\n case DebugEvents.Reconnecting:\n case DebugEvents.PingTimer:\n case DebugEvents.StaleConnection:\n case DebugEvents.ClientInitiatedReconnect:\n break;\n }\n }\n })().catch((err) => {\n this.logger.error('Status monitor error', err);\n });\n }\n}\n","import { Logger } from '@nestjs/common';\n\nimport type { TransportHooks } from '../interfaces';\n\n/**\n * Central event bus for transport lifecycle notifications.\n *\n * Dispatches events to user-provided hooks. Events without a\n * registered hook are silently ignored — no default logging.\n *\n * @example\n * ```typescript\n * const bus = new EventBus(logger, {\n * [TransportEvent.Error]: (err) => sentry.captureException(err),\n * });\n *\n * bus.emit(TransportEvent.Error, new Error('timeout'), 'rpc-router');\n * // → calls sentry\n *\n * bus.emit(TransportEvent.Connect, 'nats://localhost:4222');\n * // → no-op (no hook registered)\n * ```\n */\nexport class EventBus {\n private readonly hooks: Partial<TransportHooks>;\n private readonly logger: Logger;\n\n public constructor(logger: Logger, hooks?: Partial<TransportHooks>) {\n this.logger = logger;\n this.hooks = hooks ?? {};\n }\n\n /**\n * Emit a lifecycle event. Dispatches to custom hook if registered, otherwise no-op.\n *\n * @param event - The {@link TransportEvent} to emit.\n * @param args - Arguments matching the hook signature for this event.\n */\n public emit<K extends keyof TransportHooks>(\n event: K,\n ...args: Parameters<TransportHooks[K]>\n ): void {\n const hook = this.hooks[event];\n\n if (!hook) return;\n\n try {\n const result = (hook as (...a: unknown[]) => unknown)(...args);\n\n // Catch async hook rejections that would otherwise go to unhandledRejection\n if (result && typeof (result as Promise<unknown>).catch === 'function') {\n (result as Promise<unknown>).catch((err: unknown) => {\n this.logger.error(\n `Async hook \"${event}\" rejected: ${err instanceof Error ? err.message : err}`,\n );\n });\n }\n } catch (err) {\n this.logger.error(\n `Hook \"${event}\" threw an error: ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\n\nimport { ConnectionProvider } from '../connection';\n\n/**\n * Health status returned by {@link JetstreamHealthIndicator.check}.\n */\nexport interface JetstreamHealthStatus {\n /** Whether the NATS connection is alive. */\n connected: boolean;\n /** NATS server URL, or `null` if not connected. */\n server: string | null;\n /** Round-trip latency in ms, or `null` if disconnected. */\n latency: number | null;\n}\n\n/**\n * Health indicator result compatible with @nestjs/terminus.\n *\n * Follows the Terminus convention: returns status object on success,\n * throws on failure. Works with Terminus out of the box — no wrapper needed:\n *\n * @example\n * ```typescript\n * // With Terminus\n * this.health.check([() => this.jetstream.isHealthy()])\n *\n * // Standalone\n * const status = await this.jetstream.check();\n * ```\n */\n@Injectable()\nexport class JetstreamHealthIndicator {\n private readonly logger = new Logger('Jetstream:Health');\n\n public constructor(private readonly connection: ConnectionProvider) {}\n\n /**\n * Plain health status check.\n *\n * Returns the current connection status without throwing.\n * Use this for custom health endpoints or monitoring integrations.\n *\n * @returns Connection status with server URL and RTT latency.\n */\n public async check(): Promise<JetstreamHealthStatus> {\n const nc = this.connection.unwrap;\n\n if (!nc || nc.isClosed()) {\n return { connected: false, server: null, latency: null };\n }\n\n try {\n const start = performance.now();\n\n await nc.rtt();\n\n const latency = Math.round(performance.now() - start);\n\n return { connected: true, server: nc.getServer(), latency };\n } catch (err) {\n this.logger.warn(`Health check failed: ${err instanceof Error ? err.message : err}`);\n return { connected: false, server: nc.getServer(), latency: null };\n }\n }\n\n /**\n * Terminus-compatible health check.\n *\n * Returns `{ [key]: { status: 'up', ... } }` on success.\n * Throws an error with `{ [key]: { status: 'down', ... } }` on failure.\n *\n * @param key - Health indicator key (default: `'jetstream'`).\n * @returns Object with status, server, and latency under the given key.\n * @throws Error with `{ [key]: { status: 'down' } }` when disconnected.\n */\n public async isHealthy(key = 'jetstream'): Promise<Record<string, Record<string, unknown>>> {\n const status = await this.check();\n\n const details: Record<string, unknown> = {\n status: status.connected ? 'up' : 'down',\n server: status.server,\n latency: status.latency,\n };\n\n if (!status.connected) {\n throw Object.assign(new Error('Jetstream health check failed'), {\n [key]: details,\n });\n }\n\n return { [key]: details };\n }\n}\n","import { CustomTransportStrategy, Server } from '@nestjs/microservices';\nimport type { ConsumerInfo } from 'nats';\n\nimport { ConnectionProvider } from '../connection';\nimport type { JetstreamModuleOptions, StreamKind } from '../interfaces';\n\nimport { CoreRpcServer } from './core-rpc.server';\nimport { ConsumerProvider, MessageProvider, StreamProvider } from './infrastructure';\nimport { EventRouter, PatternRegistry, RpcRouter } from './routing';\n\n/**\n * NestJS custom transport strategy for NATS JetStream.\n *\n * Coordinates all server-side providers:\n * 1. Registers handlers from NestJS into PatternRegistry\n * 2. Creates required streams and consumers\n * 3. Starts message consumption and routing\n * 4. Handles Core or JetStream RPC based on configuration\n *\n * All dependencies are injected via the NestJS DI container.\n */\nexport class JetstreamStrategy extends Server implements CustomTransportStrategy {\n public readonly transportId = Symbol('jetstream-transport');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private readonly listeners = new Map<string, Function[]>();\n private started = false;\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly streamProvider: StreamProvider,\n private readonly consumerProvider: ConsumerProvider,\n private readonly messageProvider: MessageProvider,\n private readonly eventRouter: EventRouter,\n private readonly rpcRouter: RpcRouter,\n private readonly coreRpcServer: CoreRpcServer,\n ) {\n super();\n }\n\n /**\n * Start the transport: register handlers, create infrastructure, begin consumption.\n *\n * Called by NestJS when `connectMicroservice()` is used, or internally by the module.\n */\n public async listen(callback: () => void): Promise<void> {\n if (this.started) {\n this.logger.warn('listen() called more than once — ignoring');\n\n return;\n }\n\n this.started = true;\n\n // 1. Register all NestJS handlers\n this.patternRegistry.registerHandlers(this.getHandlers());\n\n // 2. Determine which streams and durable consumers are needed\n const streamKinds = this.resolveStreamKinds();\n const durableKinds = this.resolveDurableConsumerKinds();\n\n if (streamKinds.length > 0) {\n // 3. Ensure streams exist\n await this.streamProvider.ensureStreams(streamKinds);\n\n // 4. Ensure durable consumers exist (ordered consumers are ephemeral — skip)\n if (durableKinds.length > 0) {\n const consumers = await this.consumerProvider.ensureConsumers(durableKinds);\n\n // 5. Update DLQ thresholds from actual NATS consumer configs\n this.eventRouter.updateMaxDeliverMap(this.buildMaxDeliverMap(consumers));\n\n // 6. Start durable message consumption\n this.messageProvider.start(consumers);\n }\n\n // 7. Start ordered consumer if handlers are registered\n if (this.patternRegistry.hasOrderedHandlers()) {\n const orderedStreamName = this.streamProvider.getStreamName('ordered');\n\n await this.messageProvider.startOrdered(\n orderedStreamName,\n this.patternRegistry.getOrderedSubjects(),\n this.options.ordered,\n );\n }\n\n // 8. Start event router if any event-type handlers exist\n if (\n this.patternRegistry.hasEventHandlers() ||\n this.patternRegistry.hasBroadcastHandlers() ||\n this.patternRegistry.hasOrderedHandlers()\n ) {\n this.eventRouter.start();\n }\n\n // 9. Start RPC router if JetStream mode\n if (this.isJetStreamRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n this.rpcRouter.start();\n }\n }\n\n // 10. Start Core RPC server if core mode\n if (this.isCoreRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n await this.coreRpcServer.start();\n }\n\n callback();\n }\n\n /** Stop all consumers, routers, and subscriptions. Called during shutdown. */\n public close(): void {\n this.eventRouter.destroy();\n this.rpcRouter.destroy();\n this.coreRpcServer.stop();\n this.messageProvider.destroy();\n this.started = false;\n }\n\n /**\n * Register event listener (required by Server base class).\n *\n * Stores callbacks for client use. Primary lifecycle events\n * are routed through EventBus.\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n public on(event: string, callback: Function): void {\n const existing = this.listeners.get(event) ?? [];\n\n existing.push(callback);\n this.listeners.set(event, existing);\n }\n\n /**\n * Unwrap the underlying NATS connection.\n *\n * @throws Error if the transport has not started.\n */\n public unwrap<T>(): T {\n const nc = this.connection.unwrap;\n\n if (!nc) {\n throw new Error('Not connected — transport has not started');\n }\n\n return nc as T;\n }\n\n /** Access the pattern registry (for module-level introspection). */\n public getPatternRegistry(): PatternRegistry {\n return this.patternRegistry;\n }\n\n /** Determine which JetStream streams are needed. */\n private resolveStreamKinds(): StreamKind[] {\n const kinds: StreamKind[] = [];\n\n if (this.patternRegistry.hasEventHandlers()) {\n kinds.push('ev');\n }\n\n if (this.patternRegistry.hasOrderedHandlers()) {\n kinds.push('ordered');\n }\n\n if (this.isJetStreamRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n kinds.push('cmd');\n }\n\n if (this.patternRegistry.hasBroadcastHandlers()) {\n kinds.push('broadcast');\n }\n\n return kinds;\n }\n\n /** Determine which stream kinds need durable consumers (ordered consumers are ephemeral). */\n private resolveDurableConsumerKinds(): StreamKind[] {\n const kinds: StreamKind[] = [];\n\n if (this.patternRegistry.hasEventHandlers()) {\n kinds.push('ev');\n }\n\n if (this.isJetStreamRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n kinds.push('cmd');\n }\n\n if (this.patternRegistry.hasBroadcastHandlers()) {\n kinds.push('broadcast');\n }\n\n return kinds;\n }\n\n /** Build max_deliver map from actual NATS consumer configs (not options). */\n private buildMaxDeliverMap(consumers: Map<StreamKind, ConsumerInfo>): Map<string, number> {\n const map = new Map<string, number>();\n\n for (const [, info] of consumers) {\n const stream = info.stream_name;\n const maxDeliver = info.config.max_deliver;\n\n if (stream && maxDeliver !== undefined && maxDeliver > 0) {\n map.set(stream, maxDeliver);\n }\n }\n\n return map;\n }\n\n private isCoreRpcMode(): boolean {\n return !this.options.rpc || this.options.rpc.mode === 'core';\n }\n\n private isJetStreamRpcMode(): boolean {\n return this.options.rpc?.mode === 'jetstream';\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { headers as natsHeaders, Msg, Subscription } from 'nats';\n\nimport { ConnectionProvider } from '../connection';\nimport { RpcContext } from '../context';\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport type { Codec, JetstreamModuleOptions } from '../interfaces';\nimport { internalName, JetstreamHeader } from '../jetstream.constants';\nimport { serializeError, unwrapResult } from '../utils';\n\nimport { PatternRegistry } from './routing/pattern-registry';\n\n/**\n * Handles RPC via NATS Core request/reply pattern.\n *\n * Subscribes to `{service}.cmd.>` with a queue group for load balancing.\n * Each request is processed and replied to directly via `msg.respond()`.\n *\n * This is the default RPC mode — lowest latency, no persistence overhead.\n */\nexport class CoreRpcServer {\n private readonly logger = new Logger('Jetstream:CoreRpc');\n private subscription: Subscription | null = null;\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n ) {}\n\n /** Start listening for RPC requests on the command subject. */\n public async start(): Promise<void> {\n const nc = await this.connection.getConnection();\n const serviceName = internalName(this.options.name);\n const subject = `${serviceName}.cmd.>`;\n const queue = `${serviceName}_cmd_queue`;\n\n this.subscription = nc.subscribe(subject, {\n queue,\n callback: (err, msg) => {\n if (err) {\n this.logger.error('Core RPC subscription error:', err);\n return;\n }\n\n this.handleRequest(msg).catch((err) => {\n this.logger.error('Unhandled request error:', err);\n });\n },\n });\n\n this.logger.log(`Core RPC listening: ${subject} (queue: ${queue})`);\n }\n\n /** Stop listening and clean up the subscription. */\n public stop(): void {\n if (this.subscription) {\n this.subscription.unsubscribe();\n this.subscription = null;\n }\n }\n\n /** Handle an incoming Core NATS request. */\n private async handleRequest(msg: Msg): Promise<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n this.logger.warn(`No handler for Core RPC: ${msg.subject}`);\n this.respondWithError(msg, new Error(`No handler for subject: ${msg.subject}`));\n return;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'rpc');\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n this.logger.error(`Decode error for Core RPC ${msg.subject}:`, err);\n this.respondWithError(msg, err);\n return;\n }\n\n const ctx = new RpcContext([msg]);\n\n try {\n const result = await unwrapResult(handler(data, ctx));\n\n msg.respond(this.codec.encode(result));\n } catch (err) {\n this.logger.error(`Handler error for Core RPC ${msg.subject}:`, err);\n this.respondWithError(msg, err);\n }\n }\n\n /** Send an error response back to the caller with x-error header. */\n private respondWithError(msg: Msg, error: unknown): void {\n try {\n const hdrs = natsHeaders();\n\n hdrs.set(JetstreamHeader.Error, 'true');\n msg.respond(this.codec.encode(serializeError(error)), { headers: hdrs });\n } catch {\n this.logger.error('Failed to encode error response');\n }\n }\n}\n","import { BaseRpcContext } from '@nestjs/microservices';\nimport { JsMsg, MsgHdrs, Msg } from 'nats';\n\ntype NatsMessage = JsMsg | Msg;\n\n/**\n * Execution context for RPC and event handlers.\n *\n * Provides convenient accessors for the NATS message, subject,\n * and headers without needing to interact with the raw message directly.\n *\n * @example\n * ```typescript\n * @MessagePattern('get.user')\n * getUser(data: GetUserDto, @Ctx() ctx: RpcContext) {\n * const traceId = ctx.getHeader('x-trace-id');\n * const subject = ctx.getSubject();\n * return this.userService.findOne(data.id);\n * }\n * ```\n */\nexport class RpcContext extends BaseRpcContext<[NatsMessage]> {\n /**\n * Get the underlying NATS message.\n *\n * @returns `JsMsg` for JetStream handlers, `Msg` for Core RPC handlers.\n */\n public getMessage(): NatsMessage {\n return this.args[0];\n }\n\n /** @returns The NATS subject this message was published to. */\n public getSubject(): string {\n return this.args[0].subject;\n }\n\n /** @returns All NATS message headers, or `undefined` if none are present. */\n public getHeaders(): MsgHdrs | undefined {\n return this.args[0].headers;\n }\n\n /**\n * Get a single header value by key.\n *\n * @param key - Header name (e.g. `'x-trace-id'`).\n * @returns Header value, or `undefined` if the header is missing.\n */\n public getHeader(key: string): string | undefined {\n return this.args[0].headers?.get(key);\n }\n\n /**\n * Type guard: returns `true` when the message is a JetStream message.\n *\n * Narrows `getMessage()` return type to `JsMsg`, giving access to\n * `ack()`, `nak()`, `term()`, and delivery metadata.\n */\n public isJetStream(): this is RpcContext & { getMessage(): JsMsg } {\n return 'ack' in this.args[0];\n }\n}\n","import { RpcException } from '@nestjs/microservices';\n\n/**\n * Serialize an error for transport over NATS.\n *\n * Handles three cases:\n * 1. `RpcException` — unwraps via `getError()` to preserve the full payload.\n * 2. Generic `Error` — extracts `{ message }` to avoid `\"[object Object]\"`.\n * 3. Plain object — passed through as-is (already unwrapped by NestJS filters).\n *\n * @param err - The error to serialize.\n * @returns A JSON-safe representation of the error.\n */\nexport const serializeError = (err: unknown): unknown => {\n if (err instanceof RpcException) return err.getError();\n if (err instanceof Error) return { message: err.message };\n\n return err;\n};\n","import { isObservable, Observable, Subscription } from 'rxjs';\n\n/**\n * Unwrap a handler result that may be a Promise, Observable, or nested combination.\n *\n * NestJS-wrapped handlers may return `Promise<Observable>` (e.g. when exception\n * filters convert errors to `throwError()` Observables). This function handles:\n *\n * - `Observable` — subscribe immediately (no await — preserves sync emissions)\n * - `Promise<Observable>` — await Promise, then subscribe\n * - `Promise<value>` — await\n * - Plain value — return as-is\n *\n * @param result - The raw handler return value.\n * @returns The resolved value after unwrapping all layers.\n */\nexport const unwrapResult = async (result: unknown): Promise<unknown> => {\n // Direct Observable — subscribe immediately (no microtask yield)\n if (isObservable(result)) {\n return subscribeToFirst(result as Observable<unknown>);\n }\n\n // Await Promise, then check if it resolved to an Observable\n // (NestJS-wrapped handlers return Promise<Observable> when exception filters fire)\n const resolved = await result;\n\n if (isObservable(resolved)) {\n return subscribeToFirst(resolved as Observable<unknown>);\n }\n\n return resolved;\n};\n\n/** Subscribe to an Observable and resolve with its first emitted value. */\nconst subscribeToFirst = (obs: Observable<unknown>): Promise<unknown> =>\n new Promise((resolve, reject) => {\n let done = false;\n let subscription: Subscription | null = null;\n\n subscription = obs.subscribe({\n next: (val: unknown) => {\n if (!done) {\n done = true;\n resolve(val);\n // Unsubscribe if subscribe() has already returned; otherwise deferred below\n subscription?.unsubscribe();\n }\n },\n error: reject,\n complete: () => {\n if (!done) resolve(undefined);\n },\n });\n\n // Handle synchronous emission: next fired before subscribe() returned\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- mutated in sync callback above\n if (done) {\n subscription.unsubscribe();\n }\n });\n","import { Logger } from '@nestjs/common';\nimport { NatsError, StreamConfig, StreamInfo } from 'nats';\n\nimport { ConnectionProvider } from '../../connection';\nimport type { JetstreamModuleOptions, StreamKind } from '../../interfaces';\nimport {\n DEFAULT_BROADCAST_STREAM_CONFIG,\n DEFAULT_COMMAND_STREAM_CONFIG,\n DEFAULT_EVENT_STREAM_CONFIG,\n DEFAULT_ORDERED_STREAM_CONFIG,\n internalName,\n streamName,\n} from '../../jetstream.constants';\n\n/** JetStream API error code for missing streams. */\nconst STREAM_NOT_FOUND = 10059;\n\n/**\n * Manages JetStream stream lifecycle: creation, updates, and idempotent ensures.\n *\n * Creates up to three stream types depending on configuration:\n * - **Event stream** — workqueue events (always, when consumer enabled)\n * - **Command stream** — RPC commands (only in jetstream RPC mode)\n * - **Broadcast stream** — fan-out events (only if broadcast handlers exist)\n *\n * All operations are idempotent: safe to call on every startup and reconnection.\n */\nexport class StreamProvider {\n private readonly logger = new Logger('Jetstream:Stream');\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n ) {}\n\n /**\n * Ensure all required streams exist with correct configuration.\n *\n * @param kinds Which stream kinds to create. Determined by the module based\n * on RPC mode and registered handler patterns.\n */\n public async ensureStreams(kinds: StreamKind[]): Promise<void> {\n const jsm = await this.connection.getJetStreamManager();\n\n await Promise.all(kinds.map((kind) => this.ensureStream(jsm, kind)));\n }\n\n /** Get the stream name for a given kind. */\n public getStreamName(kind: StreamKind): string {\n return streamName(this.options.name, kind);\n }\n\n /** Get the subjects pattern for a given kind. */\n public getSubjects(kind: StreamKind): string[] {\n const name = internalName(this.options.name);\n\n switch (kind) {\n case 'ev':\n return [`${name}.ev.>`];\n case 'cmd':\n return [`${name}.cmd.>`];\n case 'broadcast':\n return ['broadcast.>'];\n case 'ordered':\n return [`${name}.ordered.>`];\n }\n }\n\n /** Ensure a single stream exists, creating or updating as needed. */\n private async ensureStream(\n jsm: Awaited<ReturnType<ConnectionProvider['getJetStreamManager']>>,\n kind: StreamKind,\n ): Promise<StreamInfo> {\n const config = this.buildConfig(kind);\n\n this.logger.log(`Ensuring stream: ${config.name}`);\n\n try {\n // Try to get existing stream info\n await jsm.streams.info(config.name);\n // Stream exists — update config\n this.logger.debug(`Stream exists, updating: ${config.name}`);\n return await jsm.streams.update(config.name, config);\n } catch (err) {\n if (err instanceof NatsError && err.api_error?.err_code === STREAM_NOT_FOUND) {\n this.logger.log(`Creating stream: ${config.name}`);\n return await jsm.streams.add(config as StreamConfig);\n }\n\n throw err;\n }\n }\n\n /** Build the full stream config by merging defaults with user overrides. */\n private buildConfig(\n kind: StreamKind,\n ): Partial<StreamConfig> & { name: string; subjects: string[] } {\n const name = this.getStreamName(kind);\n const subjects = this.getSubjects(kind);\n const description = `JetStream ${kind} stream for ${this.options.name}`;\n\n const defaults = this.getDefaults(kind);\n const overrides = this.getOverrides(kind);\n\n return {\n ...defaults,\n ...overrides,\n name,\n subjects,\n description,\n };\n }\n\n /** Get default config for a stream kind. */\n private getDefaults(kind: StreamKind): Partial<StreamConfig> {\n switch (kind) {\n case 'ev':\n return DEFAULT_EVENT_STREAM_CONFIG;\n case 'cmd':\n return DEFAULT_COMMAND_STREAM_CONFIG;\n case 'broadcast':\n return DEFAULT_BROADCAST_STREAM_CONFIG;\n case 'ordered':\n return DEFAULT_ORDERED_STREAM_CONFIG;\n }\n }\n\n /** Get user-provided overrides for a stream kind. */\n private getOverrides(kind: StreamKind): Partial<StreamConfig> {\n switch (kind) {\n case 'ev':\n return this.options.events?.stream ?? {};\n case 'cmd':\n return this.options.rpc?.mode === 'jetstream' ? (this.options.rpc.stream ?? {}) : {};\n case 'broadcast':\n return this.options.broadcast?.stream ?? {};\n case 'ordered':\n return this.options.ordered?.stream ?? {};\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { ConsumerConfig, ConsumerInfo, NatsError } from 'nats';\n\nimport { ConnectionProvider } from '../../connection';\nimport type { JetstreamModuleOptions, StreamKind } from '../../interfaces';\nimport {\n consumerName,\n DEFAULT_BROADCAST_CONSUMER_CONFIG,\n DEFAULT_COMMAND_CONSUMER_CONFIG,\n DEFAULT_EVENT_CONSUMER_CONFIG,\n internalName,\n} from '../../jetstream.constants';\nimport { PatternRegistry } from '../routing';\n\nimport { StreamProvider } from './stream.provider';\n\n/** JetStream API error code for missing consumers. */\nconst CONSUMER_NOT_FOUND = 10014;\n\n/**\n * Manages JetStream consumer lifecycle: creation and idempotent ensures.\n *\n * Creates durable pull-based consumers that survive restarts.\n * Consumer configuration is merged from defaults and user overrides.\n */\nexport class ConsumerProvider {\n private readonly logger = new Logger('Jetstream:Consumer');\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n private readonly streamProvider: StreamProvider,\n private readonly patternRegistry: PatternRegistry,\n ) {}\n\n /**\n * Ensure consumers exist for the specified kinds.\n *\n * @returns Map of kind -> ConsumerInfo for downstream use.\n */\n public async ensureConsumers(kinds: StreamKind[]): Promise<Map<StreamKind, ConsumerInfo>> {\n const jsm = await this.connection.getJetStreamManager();\n const results = new Map<StreamKind, ConsumerInfo>();\n\n await Promise.all(\n kinds.map(async (kind) => {\n const info = await this.ensureConsumer(jsm, kind);\n\n results.set(kind, info);\n }),\n );\n\n return results;\n }\n\n /** Get the consumer name for a given kind. */\n public getConsumerName(kind: StreamKind): string {\n return consumerName(this.options.name, kind);\n }\n\n /** Ensure a single consumer exists, creating if needed. */\n private async ensureConsumer(\n jsm: Awaited<ReturnType<ConnectionProvider['getJetStreamManager']>>,\n kind: StreamKind,\n ): Promise<ConsumerInfo> {\n const stream = this.streamProvider.getStreamName(kind);\n const config = this.buildConfig(kind);\n const name = config.durable_name;\n\n this.logger.log(`Ensuring consumer: ${name} on stream: ${stream}`);\n\n try {\n await jsm.consumers.info(stream, name);\n this.logger.debug(`Consumer exists, updating: ${name}`);\n return await jsm.consumers.update(stream, name, config);\n } catch (err) {\n if (err instanceof NatsError && err.api_error?.err_code === CONSUMER_NOT_FOUND) {\n this.logger.log(`Creating consumer: ${name}`);\n return await jsm.consumers.add(stream, config);\n }\n\n throw err;\n }\n }\n\n /** Build consumer config by merging defaults with user overrides. */\n // eslint-disable-next-line @typescript-eslint/naming-convention -- NATS API uses snake_case\n private buildConfig(kind: StreamKind): Partial<ConsumerConfig> & { durable_name: string } {\n const name = this.getConsumerName(kind);\n const serviceName = internalName(this.options.name);\n\n const defaults = this.getDefaults(kind);\n const overrides = this.getOverrides(kind);\n\n /* eslint-disable @typescript-eslint/naming-convention -- NATS API uses snake_case */\n if (kind === 'broadcast') {\n const broadcastPatterns = this.patternRegistry.getBroadcastPatterns();\n\n if (broadcastPatterns.length === 0) {\n throw new Error('Broadcast consumer requested but no broadcast patterns are registered');\n }\n\n if (broadcastPatterns.length === 1) {\n return {\n ...defaults,\n ...overrides,\n name,\n durable_name: name,\n filter_subject: broadcastPatterns[0],\n };\n }\n\n return {\n ...defaults,\n ...overrides,\n name,\n durable_name: name,\n filter_subjects: broadcastPatterns,\n };\n }\n\n // Build filter_subject based on kind\n const filter_subject = kind === 'ev' ? `${serviceName}.ev.>` : `${serviceName}.cmd.>`;\n\n return {\n ...defaults,\n ...overrides,\n name,\n durable_name: name,\n filter_subject,\n };\n /* eslint-enable @typescript-eslint/naming-convention */\n }\n\n /** Get default config for a consumer kind. */\n private getDefaults(kind: StreamKind): Partial<ConsumerConfig> {\n switch (kind) {\n case 'ev':\n return DEFAULT_EVENT_CONSUMER_CONFIG;\n case 'cmd':\n return DEFAULT_COMMAND_CONSUMER_CONFIG;\n case 'broadcast':\n return DEFAULT_BROADCAST_CONSUMER_CONFIG;\n case 'ordered':\n throw new Error('Ordered consumers are ephemeral and should not use durable config');\n }\n }\n\n /** Get user-provided overrides for a consumer kind. */\n private getOverrides(kind: StreamKind): Partial<ConsumerConfig> {\n switch (kind) {\n case 'ev':\n return this.options.events?.consumer ?? {};\n case 'cmd':\n return this.options.rpc?.mode === 'jetstream' ? (this.options.rpc.consumer ?? {}) : {};\n case 'broadcast':\n return this.options.broadcast?.consumer ?? {};\n case 'ordered':\n throw new Error('Ordered consumers are ephemeral and should not use durable config');\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { Consumer, ConsumerInfo, ConsumerMessages, DeliverPolicy, JsMsg } from 'nats';\nimport type { OrderedConsumerOptions } from 'nats';\nimport {\n catchError,\n defer,\n EMPTY,\n merge,\n Observable,\n repeat,\n Subject,\n takeUntil,\n tap,\n timer,\n} from 'rxjs';\n\nimport { ConnectionProvider } from '../../connection';\nimport { EventBus } from '../../hooks';\nimport type { OrderedEventOverrides, StreamKind } from '../../interfaces';\nimport { TransportEvent } from '../../interfaces';\n\n/**\n * Manages pull-based message consumption from JetStream consumers.\n *\n * Uses `defer()` + `repeat()` pattern for self-healing: when the async\n * iterator completes (e.g., NATS restart), the consumer automatically\n * re-establishes after a short delay.\n *\n * Emits messages to kind-specific RxJS subjects for downstream routing.\n */\nexport class MessageProvider {\n private readonly logger = new Logger('Jetstream:Message');\n private readonly activeIterators = new Set<ConsumerMessages>();\n private orderedReadyResolve: (() => void) | null = null;\n private orderedReadyReject: ((err: unknown) => void) | null = null;\n\n private destroy$ = new Subject<void>();\n private eventMessages$ = new Subject<JsMsg>();\n private commandMessages$ = new Subject<JsMsg>();\n private broadcastMessages$ = new Subject<JsMsg>();\n private orderedMessages$ = new Subject<JsMsg>();\n\n public constructor(\n private readonly connection: ConnectionProvider,\n private readonly eventBus: EventBus,\n ) {}\n\n /** Observable stream of workqueue event messages. */\n public get events$(): Observable<JsMsg> {\n return this.eventMessages$.asObservable();\n }\n\n /** Observable stream of RPC command messages (jetstream mode). */\n public get commands$(): Observable<JsMsg> {\n return this.commandMessages$.asObservable();\n }\n\n /** Observable stream of broadcast event messages. */\n public get broadcasts$(): Observable<JsMsg> {\n return this.broadcastMessages$.asObservable();\n }\n\n /** Observable stream of ordered event messages (strict sequential delivery). */\n public get ordered$(): Observable<JsMsg> {\n return this.orderedMessages$.asObservable();\n }\n\n /**\n * Start consuming messages from the given consumer infos.\n *\n * Each consumer gets an independent self-healing flow.\n * Call `destroy()` to stop all consumers.\n */\n public start(consumers: Map<StreamKind, ConsumerInfo>): void {\n const flows: Observable<void>[] = [];\n\n for (const [kind, info] of consumers) {\n flows.push(this.createFlow(kind, info));\n }\n\n if (flows.length > 0) {\n merge(...flows)\n .pipe(takeUntil(this.destroy$))\n .subscribe();\n }\n }\n\n /**\n * Start an ordered consumer for strict sequential delivery.\n *\n * Unlike durable consumers, ordered consumers are ephemeral — created at\n * consumption time, no durable state. nats.js handles auto-recreation.\n *\n * @param streamName - JetStream stream to consume from.\n * @param filterSubjects - NATS subjects to filter on.\n */\n public async startOrdered(\n streamName: string,\n filterSubjects: string[],\n orderedConfig?: OrderedEventOverrides,\n ): Promise<void> {\n const consumerOpts: Partial<OrderedConsumerOptions> = { filterSubjects };\n\n // Workaround: in nats.js (v2.29.x), explicitly passing DeliverPolicy.All to an\n // ordered consumer leaves opt_start_seq in the config, causing consume() to hang.\n // Omitting deliver_policy lets nats.js use its internal default (same All behavior).\n // See: nats.js/lib/jetstream/consumer.js, OrderedPullConsumerImpl.resetConsumer()\n if (\n orderedConfig?.deliverPolicy !== undefined &&\n orderedConfig.deliverPolicy !== DeliverPolicy.All\n ) {\n consumerOpts.deliver_policy = orderedConfig.deliverPolicy;\n }\n\n if (orderedConfig?.optStartSeq !== undefined) {\n consumerOpts.opt_start_seq = orderedConfig.optStartSeq;\n }\n\n if (orderedConfig?.optStartTime !== undefined) {\n consumerOpts.opt_start_time = orderedConfig.optStartTime;\n }\n\n if (orderedConfig?.replayPolicy !== undefined) {\n consumerOpts.replay_policy = orderedConfig.replayPolicy;\n }\n\n // Resolve/reject when the ordered consumer connects or fails on first attempt\n const ready = new Promise<void>((resolve, reject) => {\n this.orderedReadyResolve = resolve;\n this.orderedReadyReject = reject;\n });\n\n const flow = this.createOrderedFlow(streamName, consumerOpts);\n\n flow.pipe(takeUntil(this.destroy$)).subscribe();\n\n return ready;\n }\n\n /** Stop all consumer flows and reinitialize subjects for potential restart. */\n public destroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n\n for (const messages of this.activeIterators) {\n messages.stop();\n }\n\n this.activeIterators.clear();\n\n this.eventMessages$.complete();\n this.commandMessages$.complete();\n this.broadcastMessages$.complete();\n this.orderedMessages$.complete();\n\n // Reinitialize subjects so start() can be called again after destroy()\n this.destroy$ = new Subject<void>();\n this.eventMessages$ = new Subject<JsMsg>();\n this.commandMessages$ = new Subject<JsMsg>();\n this.broadcastMessages$ = new Subject<JsMsg>();\n this.orderedMessages$ = new Subject<JsMsg>();\n }\n\n /** Create a self-healing consumer flow for a specific kind. */\n private createFlow(kind: StreamKind, info: ConsumerInfo): Observable<void> {\n const target$ = this.getTargetSubject(kind);\n let consecutiveFailures = 0;\n let lastRunFailed = false;\n\n return defer(() => this.consumeOnce(info, target$)).pipe(\n tap(() => {\n lastRunFailed = false;\n }),\n catchError((err) => {\n consecutiveFailures++;\n lastRunFailed = true;\n this.logger.error(`Consumer ${info.name} error, will restart:`, err);\n this.eventBus.emit(\n TransportEvent.Error,\n err instanceof Error ? err : new Error(String(err)),\n 'message-provider',\n );\n return EMPTY;\n }),\n repeat({\n delay: () => {\n if (!lastRunFailed) {\n consecutiveFailures = 0;\n }\n\n const delay = Math.min(100 * Math.pow(2, consecutiveFailures), 30_000);\n\n this.logger.warn(`Consumer ${info.name} stream ended, restarting in ${delay}ms...`);\n return timer(delay);\n },\n }),\n takeUntil(this.destroy$),\n );\n }\n\n /** Single iteration: get consumer -> pull messages -> emit to subject. */\n private async consumeOnce(info: ConsumerInfo, target$: Subject<JsMsg>): Promise<void> {\n const js = (await this.connection.getConnection()).jetstream();\n const consumer: Consumer = await js.consumers.get(info.stream_name, info.name);\n const messages = await consumer.consume();\n\n this.activeIterators.add(messages);\n\n try {\n for await (const msg of messages) {\n target$.next(msg);\n }\n } finally {\n this.activeIterators.delete(messages);\n }\n }\n\n /** Get the target subject for a consumer kind. */\n private getTargetSubject(kind: StreamKind): Subject<JsMsg> {\n switch (kind) {\n case 'ev':\n return this.eventMessages$;\n case 'cmd':\n return this.commandMessages$;\n case 'broadcast':\n return this.broadcastMessages$;\n case 'ordered':\n return this.orderedMessages$;\n }\n }\n\n /** Create a self-healing ordered consumer flow. */\n private createOrderedFlow(\n streamName: string,\n consumerOpts: Partial<OrderedConsumerOptions>,\n ): Observable<void> {\n let consecutiveFailures = 0;\n let lastRunFailed = false;\n\n return defer(() => this.consumeOrderedOnce(streamName, consumerOpts)).pipe(\n tap(() => {\n lastRunFailed = false;\n }),\n catchError((err) => {\n consecutiveFailures++;\n lastRunFailed = true;\n this.logger.error('Ordered consumer error, will restart:', err);\n this.eventBus.emit(\n TransportEvent.Error,\n err instanceof Error ? err : new Error(String(err)),\n 'message-provider',\n );\n\n // Fail fast on first error so listen() propagates the failure.\n // Subsequent errors (after retry) are handled by the self-healing loop.\n if (this.orderedReadyReject) {\n this.orderedReadyReject(err);\n this.orderedReadyReject = null;\n this.orderedReadyResolve = null;\n }\n\n return EMPTY;\n }),\n repeat({\n delay: () => {\n if (!lastRunFailed) {\n consecutiveFailures = 0;\n }\n\n const delay = Math.min(100 * Math.pow(2, consecutiveFailures), 30_000);\n\n this.logger.warn(`Ordered consumer stream ended, restarting in ${delay}ms...`);\n return timer(delay);\n },\n }),\n );\n }\n\n /** Single iteration: create ordered consumer -> iterate messages. */\n private async consumeOrderedOnce(\n streamName: string,\n consumerOpts: Partial<OrderedConsumerOptions>,\n ): Promise<void> {\n const js = (await this.connection.getConnection()).jetstream();\n const consumer = await js.consumers.get(streamName, consumerOpts);\n const messages = await consumer.consume();\n\n // Signal that the ordered consumer is ready to receive messages\n if (this.orderedReadyResolve) {\n this.orderedReadyResolve();\n this.orderedReadyResolve = null;\n this.orderedReadyReject = null;\n }\n\n this.activeIterators.add(messages);\n\n try {\n for await (const msg of messages) {\n this.orderedMessages$.next(msg);\n }\n } finally {\n this.activeIterators.delete(messages);\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { MessageHandler } from '@nestjs/microservices';\n\nimport type { JetstreamModuleOptions, PatternsByKind, RegisteredHandler } from '../../interfaces';\nimport { buildBroadcastSubject, buildSubject, internalName } from '../../jetstream.constants';\n\n/**\n * Registry mapping NATS subjects to NestJS message handlers.\n *\n * Handles subject normalization and categorization:\n * - Detects broadcast handlers via `extras.broadcast` metadata\n * - Normalizes full NATS subjects back to user-facing patterns\n * - Provides lists of patterns by category for stream/consumer setup\n */\nexport class PatternRegistry {\n private readonly logger = new Logger('Jetstream:PatternRegistry');\n private readonly registry = new Map<string, RegisteredHandler>();\n\n public constructor(private readonly options: JetstreamModuleOptions) {}\n\n /**\n * Register all handlers from the NestJS strategy.\n *\n * @param handlers Map of pattern -> MessageHandler from `Server.getHandlers()`.\n */\n public registerHandlers(handlers: Map<string, MessageHandler>): void {\n const serviceName = this.options.name;\n\n for (const [pattern, handler] of handlers) {\n const extras = handler.extras as Record<string, unknown> | undefined;\n const isEvent = handler.isEventHandler ?? false;\n const isBroadcast = !!extras?.broadcast;\n const isOrdered = !!extras?.ordered;\n\n if (isBroadcast && isOrdered) {\n throw new Error(\n `Handler \"${pattern}\" cannot be both broadcast and ordered. Use one or the other.`,\n );\n }\n\n // Build the full NATS subject this handler should receive\n let fullSubject: string;\n\n if (isBroadcast) {\n fullSubject = buildBroadcastSubject(pattern);\n } else if (isOrdered) {\n fullSubject = buildSubject(serviceName, 'ordered', pattern);\n } else if (isEvent) {\n fullSubject = buildSubject(serviceName, 'ev', pattern);\n } else {\n fullSubject = buildSubject(serviceName, 'cmd', pattern);\n }\n\n this.registry.set(fullSubject, {\n handler,\n pattern,\n isEvent: isEvent && !isOrdered,\n isBroadcast,\n isOrdered,\n });\n\n let kind: string;\n\n if (isBroadcast) {\n kind = 'broadcast';\n } else if (isOrdered) {\n kind = 'ordered';\n } else if (isEvent) {\n kind = 'event';\n } else {\n kind = 'rpc';\n }\n\n this.logger.debug(`Registered ${kind}: ${pattern} -> ${fullSubject}`);\n }\n\n this.logSummary();\n }\n\n /** Find handler for a full NATS subject. */\n public getHandler(subject: string): MessageHandler | null {\n return this.registry.get(subject)?.handler ?? null;\n }\n\n /** Get all registered broadcast patterns (for consumer filter_subject setup). */\n public getBroadcastPatterns(): string[] {\n return Array.from(this.registry.values())\n .filter((r) => r.isBroadcast)\n .map((r) => `broadcast.${r.pattern}`);\n }\n\n /** Check if any broadcast handlers are registered. */\n public hasBroadcastHandlers(): boolean {\n return Array.from(this.registry.values()).some((r) => r.isBroadcast);\n }\n\n /** Check if any RPC (command) handlers are registered. */\n public hasRpcHandlers(): boolean {\n return Array.from(this.registry.values()).some(\n (r) => !r.isEvent && !r.isBroadcast && !r.isOrdered,\n );\n }\n\n /** Check if any workqueue event handlers are registered. */\n public hasEventHandlers(): boolean {\n return Array.from(this.registry.values()).some((r) => r.isEvent && !r.isBroadcast);\n }\n\n /** Check if any ordered event handlers are registered. */\n public hasOrderedHandlers(): boolean {\n return Array.from(this.registry.values()).some((r) => r.isOrdered);\n }\n\n /** Get fully-qualified NATS subjects for ordered handlers. */\n public getOrderedSubjects(): string[] {\n const name = internalName(this.options.name);\n\n return Array.from(this.registry.values())\n .filter((r) => r.isOrdered)\n .map((r) => `${name}.ordered.${r.pattern}`);\n }\n\n /** Get patterns grouped by kind. */\n public getPatternsByKind(): PatternsByKind {\n const events: string[] = [];\n const commands: string[] = [];\n const broadcasts: string[] = [];\n const ordered: string[] = [];\n\n for (const entry of this.registry.values()) {\n if (entry.isBroadcast) broadcasts.push(entry.pattern);\n else if (entry.isOrdered) ordered.push(entry.pattern);\n else if (entry.isEvent) events.push(entry.pattern);\n else commands.push(entry.pattern);\n }\n\n return { events, commands, broadcasts, ordered };\n }\n\n /** Normalize a full NATS subject back to the user-facing pattern. */\n public normalizeSubject(subject: string): string {\n const name = internalName(this.options.name);\n const prefixes = [`${name}.cmd.`, `${name}.ev.`, `${name}.ordered.`, 'broadcast.'];\n\n for (const prefix of prefixes) {\n if (subject.startsWith(prefix)) {\n return subject.slice(prefix.length);\n }\n }\n\n return subject;\n }\n\n /** Log a summary of all registered handlers. */\n private logSummary(): void {\n const { events, commands, broadcasts, ordered } = this.getPatternsByKind();\n\n const parts = [\n `${commands.length} RPC`,\n `${events.length} events`,\n `${broadcasts.length} broadcasts`,\n ];\n\n if (ordered.length > 0) {\n parts.push(`${ordered.length} ordered`);\n }\n\n this.logger.log(`Registered handlers: ${parts.join(', ')}`);\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { JsMsg } from 'nats';\nimport {\n catchError,\n concatMap,\n defer,\n EMPTY,\n from,\n mergeMap,\n Observable,\n Subscription,\n} from 'rxjs';\n\nimport { RpcContext } from '../../context';\nimport { EventBus } from '../../hooks';\nimport { TransportEvent } from '../../interfaces';\nimport type { Codec, DeadLetterInfo } from '../../interfaces';\nimport { unwrapResult } from '../../utils';\n\nimport { MessageProvider } from '../infrastructure';\nimport { PatternRegistry } from './pattern-registry';\n\n/** Options for dead letter queue handling. */\nexport interface DeadLetterConfig {\n /**\n * Map of stream name -> max_deliver value.\n * Used to detect when a message from a given stream has exhausted all delivery attempts.\n */\n maxDeliverByStream: Map<string, number>;\n /** Async callback invoked when a message exhausts all deliveries. */\n onDeadLetter(info: DeadLetterInfo): Promise<void>;\n}\n\n/**\n * Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.\n *\n * **Workqueue & Broadcast** — at-least-once delivery:\n * - Success -> ack | Error -> nak (retry) | Dead letter -> term\n *\n * **Ordered** — strict sequential delivery:\n * - No ack/nak/DLQ — nats.js auto-acknowledges ordered consumer messages.\n * - Handler errors are logged but do not affect delivery.\n */\nexport class EventRouter {\n private readonly logger = new Logger('Jetstream:EventRouter');\n private readonly subscriptions: Subscription[] = [];\n\n public constructor(\n private readonly messageProvider: MessageProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n private readonly deadLetterConfig?: DeadLetterConfig,\n ) {}\n\n /**\n * Update the max_deliver thresholds from actual NATS consumer configs.\n * Called after consumers are ensured so the DLQ map reflects reality.\n */\n public updateMaxDeliverMap(consumerMaxDelivers: Map<string, number>): void {\n if (!this.deadLetterConfig) return;\n this.deadLetterConfig.maxDeliverByStream = consumerMaxDelivers;\n }\n\n /** Start routing event, broadcast, and ordered messages to handlers. */\n public start(): void {\n this.subscribeToStream(this.messageProvider.events$, 'workqueue');\n this.subscribeToStream(this.messageProvider.broadcasts$, 'broadcast');\n\n if (this.patternRegistry.hasOrderedHandlers()) {\n this.subscribeToStream(this.messageProvider.ordered$, 'ordered', true);\n }\n }\n\n /** Stop routing and unsubscribe from all streams. */\n public destroy(): void {\n for (const sub of this.subscriptions) {\n sub.unsubscribe();\n }\n\n this.subscriptions.length = 0;\n }\n\n /** Subscribe to a message stream and route each message. */\n private subscribeToStream(stream$: Observable<JsMsg>, label: string, isOrdered = false): void {\n const route = (msg: JsMsg): Observable<void> =>\n defer(() => (isOrdered ? this.handleOrdered(msg) : this.handle(msg))).pipe(\n catchError((err) => {\n this.logger.error(`Unexpected error in ${label} event router`, err);\n return EMPTY;\n }),\n );\n\n // Ordered streams use concatMap for strict sequential processing;\n // workqueue/broadcast use mergeMap for parallel handler execution.\n const subscription = stream$.pipe(isOrdered ? concatMap(route) : mergeMap(route)).subscribe();\n\n this.subscriptions.push(subscription);\n }\n\n /** Handle a single event message: decode -> execute handler -> ack/nak. */\n private handle(msg: JsMsg): Observable<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n msg.term(`No handler for event: ${msg.subject}`);\n this.logger.error(`No handler for event subject: ${msg.subject}`);\n return EMPTY;\n }\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n msg.term('Decode error');\n this.logger.error(`Decode error for ${msg.subject}:`, err);\n return EMPTY;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'event');\n\n const ctx = new RpcContext([msg]);\n\n return from(this.executeHandler(handler, data, ctx, msg));\n }\n\n /** Execute handler, then ack on success or nak/dead-letter on failure. */\n private async executeHandler(\n handler: (data: unknown, ctx: RpcContext) => Promise<unknown>,\n data: unknown,\n ctx: RpcContext,\n msg: JsMsg,\n ): Promise<void> {\n try {\n await unwrapResult(handler(data, ctx));\n msg.ack();\n } catch (err) {\n this.logger.error(`Event handler error (${msg.subject}):`, err);\n\n if (this.isDeadLetter(msg)) {\n await this.handleDeadLetter(msg, data, err);\n } else {\n msg.nak();\n }\n }\n }\n\n /** Handle an ordered message: decode -> execute handler -> no ack/nak. */\n private handleOrdered(msg: JsMsg): Observable<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n this.logger.error(`No handler for ordered subject: ${msg.subject}`);\n return EMPTY;\n }\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n this.logger.error(`Decode error for ordered ${msg.subject}:`, err);\n return EMPTY;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'event');\n\n const ctx = new RpcContext([msg]);\n\n return from(\n unwrapResult(handler(data, ctx)).catch((err: unknown) => {\n this.logger.error(`Ordered handler error (${msg.subject}):`, err);\n }),\n ) as Observable<void>;\n }\n\n /** Check if the message has exhausted all delivery attempts. */\n private isDeadLetter(msg: JsMsg): boolean {\n if (!this.deadLetterConfig) return false;\n\n const maxDeliver = this.deadLetterConfig.maxDeliverByStream.get(msg.info.stream);\n\n if (maxDeliver === undefined || maxDeliver <= 0) return false;\n\n return msg.info.deliveryCount >= maxDeliver;\n }\n\n /** Handle a dead letter: invoke callback, then term or nak based on result. */\n private async handleDeadLetter(msg: JsMsg, data: unknown, error: unknown): Promise<void> {\n const info: DeadLetterInfo = {\n subject: msg.subject,\n data,\n headers: msg.headers,\n error,\n deliveryCount: msg.info.deliveryCount,\n stream: msg.info.stream,\n streamSequence: msg.info.streamSequence,\n timestamp: new Date(msg.info.timestampNanos / 1_000_000).toISOString(),\n };\n\n this.eventBus.emit(TransportEvent.DeadLetter, info);\n\n if (!this.deadLetterConfig) return;\n\n try {\n await this.deadLetterConfig.onDeadLetter(info);\n msg.term('Dead letter processed');\n } catch (hookErr) {\n this.logger.error(`onDeadLetter callback failed for ${msg.subject}, nak for retry:`, hookErr);\n msg.nak();\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { MessageHandler } from '@nestjs/microservices';\nimport { headers, JsMsg } from 'nats';\nimport { catchError, defer, EMPTY, from, mergeMap, Observable, Subscription } from 'rxjs';\n\nimport { ConnectionProvider } from '../../connection';\nimport { RpcContext } from '../../context';\nimport { EventBus } from '../../hooks';\nimport { TransportEvent } from '../../interfaces';\nimport type { Codec } from '../../interfaces';\nimport { DEFAULT_JETSTREAM_RPC_TIMEOUT, JetstreamHeader } from '../../jetstream.constants';\nimport { serializeError, unwrapResult } from '../../utils';\n\nimport { MessageProvider } from '../infrastructure';\nimport { PatternRegistry } from './pattern-registry';\n\n/**\n * Routes RPC command messages in JetStream mode.\n *\n * Delivery semantics:\n * - Handler must complete within timeout (default: 3 min)\n * - Success -> ack -> publish response to ReplyTo (publish failure does not affect ack)\n * - Handler error -> publish error to ReplyTo -> term (no redelivery)\n * - Timeout -> no response -> term\n * - No handler / decode error -> term immediately\n *\n * Nak is never used for RPC — prevents duplicate side effects.\n */\nexport class RpcRouter {\n private readonly logger = new Logger('Jetstream:RpcRouter');\n private readonly timeout: number;\n private subscription: Subscription | null = null;\n\n public constructor(\n private readonly messageProvider: MessageProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly connection: ConnectionProvider,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n timeout?: number,\n ) {\n this.timeout = timeout ?? DEFAULT_JETSTREAM_RPC_TIMEOUT;\n }\n\n /** Start routing command messages to handlers. */\n public start(): void {\n this.subscription = this.messageProvider.commands$\n .pipe(\n mergeMap((msg) =>\n defer(() => this.handle(msg)).pipe(\n catchError((err) => {\n this.logger.error('Unexpected error in RPC router', err);\n return EMPTY;\n }),\n ),\n ),\n )\n .subscribe();\n }\n\n /** Stop routing and unsubscribe. */\n public destroy(): void {\n this.subscription?.unsubscribe();\n this.subscription = null;\n }\n\n /** Handle a single RPC command message. */\n private handle(msg: JsMsg): Observable<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n msg.term(`No handler for RPC: ${msg.subject}`);\n this.logger.error(`No handler for RPC subject: ${msg.subject}`);\n return EMPTY;\n }\n\n const replyTo = msg.headers?.get(JetstreamHeader.ReplyTo);\n const correlationId = msg.headers?.get(JetstreamHeader.CorrelationId);\n\n if (!replyTo || !correlationId) {\n msg.term('Missing required headers (reply-to or correlation-id)');\n this.logger.error(`Missing headers for RPC: ${msg.subject}`);\n return EMPTY;\n }\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n msg.term('Decode error');\n this.logger.error(`Decode error for RPC ${msg.subject}:`, err);\n return EMPTY;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'rpc');\n\n return from(this.executeHandler(handler, data, msg, replyTo, correlationId));\n }\n\n /** Execute handler, publish response, settle message. */\n private async executeHandler(\n handler: MessageHandler,\n data: unknown,\n msg: JsMsg,\n replyTo: string,\n correlationId: string,\n ): Promise<void> {\n const nc = await this.connection.getConnection();\n const ctx = new RpcContext([msg]);\n\n const hdrs = headers();\n\n hdrs.set(JetstreamHeader.CorrelationId, correlationId);\n\n let settled = false;\n\n // Race handler against timeout\n const timeoutId = setTimeout(() => {\n if (settled) return;\n settled = true;\n this.logger.error(`RPC timeout (${this.timeout}ms): ${msg.subject}`);\n this.eventBus.emit(TransportEvent.RpcTimeout, msg.subject, correlationId);\n msg.term('Handler timeout');\n }, this.timeout);\n\n try {\n const result = await unwrapResult(handler(data, ctx));\n\n // settled may be set by the setTimeout callback above (async race)\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n\n // Ack first — handler succeeded, message is processed regardless of\n // whether we can deliver the response back to the caller.\n msg.ack();\n\n try {\n nc.publish(replyTo, this.codec.encode(result), { headers: hdrs });\n } catch (publishErr) {\n this.logger.error(`Failed to publish RPC response for ${msg.subject}`, publishErr);\n }\n } catch (err) {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n\n // Publish error response with x-error header\n try {\n hdrs.set(JetstreamHeader.Error, 'true');\n nc.publish(replyTo, this.codec.encode(serializeError(err)), { headers: hdrs });\n } catch (encodeErr) {\n this.logger.error(`Failed to encode RPC error for ${msg.subject}`, encodeErr);\n }\n\n msg.term(`Handler error: ${msg.subject}`);\n }\n }\n}\n","import { Logger } from '@nestjs/common';\n\nimport { ConnectionProvider } from '../connection';\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport { JetstreamStrategy } from '../server/strategy';\n\n/**\n * Orchestrates graceful transport shutdown.\n *\n * Shutdown sequence:\n * 1. Emit onShutdownStart hook\n * 2. Stop accepting new messages (close subscriptions, stop consumers)\n * 3. Wait for in-flight handlers to complete (up to timeout)\n * 4. Drain and close NATS connection\n * 5. Emit onShutdownComplete hook\n */\nexport class ShutdownManager {\n private readonly logger = new Logger('Jetstream:Shutdown');\n\n public constructor(\n private readonly connection: ConnectionProvider,\n private readonly eventBus: EventBus,\n private readonly timeout: number,\n ) {}\n\n /**\n * Execute the full shutdown sequence.\n *\n * @param strategy Optional strategy to close (stops consumers and subscriptions).\n */\n public async shutdown(strategy?: JetstreamStrategy): Promise<void> {\n this.eventBus.emit(TransportEvent.ShutdownStart);\n this.logger.log(`Graceful shutdown started (timeout: ${this.timeout}ms)`);\n\n // 1. Stop accepting new messages (close subscriptions, stop consumers)\n strategy?.close();\n\n // 2. Drain and close NATS connection.\n // NATS drain() waits for in-flight messages and pending subscriptions,\n // then closes the connection. We add a timeout as a safety net.\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n await Promise.race([\n this.connection.shutdown(),\n new Promise<void>((resolve) => {\n timeoutId = setTimeout(resolve, this.timeout);\n }),\n ]);\n } finally {\n clearTimeout(timeoutId);\n }\n\n this.eventBus.emit(TransportEvent.ShutdownComplete);\n this.logger.log('Graceful shutdown complete');\n }\n}\n"],"mappings":"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","names":["import_common","import_nats","TransportEvent","JetstreamHeader","headers","natsHeaders","import_nats","NatsJSONCodec","import_common","import_nats","import_common","import_microservices","import_common","import_nats","import_microservices","import_microservices","import_rxjs","err","natsHeaders","import_common","import_nats","import_common","import_nats","import_common","import_nats","import_rxjs","streamName","import_common","import_common","import_rxjs","import_common","import_nats","import_rxjs","import_common"]}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jetstream.module.ts","../src/client/jetstream.client.ts","../src/interfaces/hooks.interface.ts","../src/jetstream.constants.ts","../src/client/jetstream.record.ts","../src/codec/json.codec.ts","../src/connection/connection.provider.ts","../src/hooks/event-bus.ts","../src/health/jetstream.health-indicator.ts","../src/server/strategy.ts","../src/server/core-rpc.server.ts","../src/context/rpc.context.ts","../src/utils/serialize-error.ts","../src/utils/unwrap-result.ts","../src/server/infrastructure/stream.provider.ts","../src/server/infrastructure/consumer.provider.ts","../src/server/infrastructure/message.provider.ts","../src/server/routing/pattern-registry.ts","../src/server/routing/event.router.ts","../src/server/routing/rpc.router.ts","../src/shutdown/shutdown.manager.ts"],"sourcesContent":["import {\n DynamicModule,\n Global,\n Inject,\n Logger,\n Module,\n OnApplicationShutdown,\n Optional,\n Provider,\n} from '@nestjs/common';\n\nimport { JetstreamClient } from './client';\nimport { JsonCodec } from './codec';\nimport { ConnectionProvider } from './connection';\nimport { EventBus } from './hooks';\nimport { JetstreamHealthIndicator } from './health';\nimport type {\n Codec,\n JetstreamFeatureOptions,\n JetstreamModuleAsyncOptions,\n JetstreamModuleOptions,\n} from './interfaces';\nimport {\n DEFAULT_SHUTDOWN_TIMEOUT,\n getClientToken,\n JETSTREAM_CODEC,\n JETSTREAM_CONNECTION,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n} from './jetstream.constants';\nimport {\n CoreRpcServer,\n ConsumerProvider,\n EventRouter,\n JetstreamStrategy,\n MessageProvider,\n PatternRegistry,\n RpcRouter,\n StreamProvider,\n} from './server';\nimport type { DeadLetterConfig } from './server';\nimport { ShutdownManager } from './shutdown';\n\n/**\n * Root module for the NestJS JetStream transport.\n *\n * - `forRoot()` / `forRootAsync()` — registers once in AppModule.\n * Creates shared NATS connection, codec, event bus, and optionally\n * the consumer infrastructure.\n *\n * - `forFeature()` — registers in feature modules.\n * Creates a lightweight client proxy targeting a specific service.\n *\n * @example\n * ```typescript\n * // AppModule — global setup\n * @Module({\n * imports: [\n * JetstreamModule.forRoot({\n * name: 'orders',\n * servers: ['nats://localhost:4222'],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // Feature module — per-service clients\n * @Module({\n * imports: [\n * JetstreamModule.forFeature({ name: 'users' }),\n * JetstreamModule.forFeature({ name: 'payments' }),\n * ],\n * })\n * export class OrdersModule {}\n * ```\n */\n@Global()\n@Module({})\nexport class JetstreamModule implements OnApplicationShutdown {\n public constructor(\n @Optional()\n @Inject(ShutdownManager)\n private readonly shutdownManager?: ShutdownManager,\n @Optional() @Inject(JetstreamStrategy) private readonly strategy?: JetstreamStrategy | null,\n ) {}\n\n // -------------------------------------------------------------------\n // forRoot — global module registration\n // -------------------------------------------------------------------\n\n /**\n * Register the JetStream transport globally.\n *\n * Creates a shared NATS connection, codec, event bus, and optionally\n * the full consumer infrastructure (streams, consumers, routers).\n *\n * @param options Module configuration.\n * @returns Dynamic module ready to be imported.\n */\n public static forRoot(options: JetstreamModuleOptions): DynamicModule {\n const providers = this.createCoreProviders(options);\n\n return {\n module: JetstreamModule,\n global: true,\n providers,\n exports: [\n JETSTREAM_CONNECTION,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n ShutdownManager,\n JetstreamStrategy,\n JetstreamHealthIndicator,\n ],\n };\n }\n\n // -------------------------------------------------------------------\n // forRootAsync — async global module registration\n // -------------------------------------------------------------------\n\n /**\n * Register the JetStream transport globally with async configuration.\n *\n * Supports `useFactory`, `useExisting`, and `useClass` patterns\n * for loading configuration from ConfigService, environment, etc.\n *\n * @param asyncOptions Async configuration.\n * @returns Dynamic module ready to be imported.\n */\n public static forRootAsync(asyncOptions: JetstreamModuleAsyncOptions): DynamicModule {\n const asyncProviders = this.createAsyncOptionsProvider(asyncOptions);\n const coreProviders = this.createCoreDependentProviders();\n\n return {\n module: JetstreamModule,\n global: true,\n imports: asyncOptions.imports ?? [],\n providers: [...asyncProviders, ...coreProviders],\n exports: [\n JETSTREAM_CONNECTION,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n JETSTREAM_OPTIONS,\n ShutdownManager,\n JetstreamStrategy,\n JetstreamHealthIndicator,\n ],\n };\n }\n\n // -------------------------------------------------------------------\n // forFeature — per-module client registration\n // -------------------------------------------------------------------\n\n /**\n * Register a lightweight client proxy for a target service.\n *\n * Reuses the shared NATS connection from `forRoot()`.\n * Import in each feature module that needs to communicate with a specific service.\n *\n * @param options Feature options with target service name.\n * @returns Dynamic module with the client provider.\n */\n public static forFeature(options: JetstreamFeatureOptions): DynamicModule {\n const clientToken = getClientToken(options.name);\n\n const clientProvider: Provider = {\n provide: clientToken,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION, JETSTREAM_CODEC, JETSTREAM_EVENT_BUS],\n useFactory: (\n rootOptions: JetstreamModuleOptions,\n connection: ConnectionProvider,\n rootCodec: Codec,\n eventBus: EventBus,\n ) => {\n const codec = options.codec ?? rootCodec;\n\n return new JetstreamClient(rootOptions, options.name, connection, codec, eventBus);\n },\n };\n\n return {\n module: JetstreamModule,\n providers: [clientProvider],\n exports: [clientToken],\n };\n }\n\n // -------------------------------------------------------------------\n // Provider factories\n // -------------------------------------------------------------------\n\n private static createCoreProviders(options: JetstreamModuleOptions): Provider[] {\n return [\n {\n provide: JETSTREAM_OPTIONS,\n useValue: options,\n },\n ...this.createCoreDependentProviders(),\n ];\n }\n\n /** Create providers that depend on JETSTREAM_OPTIONS (shared by sync and async). */\n private static createCoreDependentProviders(): Provider[] {\n return [\n // EventBus — hook system with Logger fallback\n {\n provide: JETSTREAM_EVENT_BUS,\n inject: [JETSTREAM_OPTIONS],\n useFactory: (options: JetstreamModuleOptions): EventBus => {\n const logger = new Logger('Jetstream:Module');\n\n return new EventBus(logger, options.hooks);\n },\n },\n\n // Codec — global encode/decode\n {\n provide: JETSTREAM_CODEC,\n inject: [JETSTREAM_OPTIONS],\n useFactory: (options: JetstreamModuleOptions): Codec => {\n return options.codec ?? new JsonCodec();\n },\n },\n\n // ConnectionProvider — single NATS connection\n {\n provide: JETSTREAM_CONNECTION,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_EVENT_BUS],\n useFactory: (options: JetstreamModuleOptions, eventBus: EventBus): ConnectionProvider => {\n return new ConnectionProvider(options, eventBus);\n },\n },\n\n // JetstreamHealthIndicator — health check for NATS connection\n {\n provide: JetstreamHealthIndicator,\n inject: [JETSTREAM_CONNECTION],\n useFactory: (connection: ConnectionProvider): JetstreamHealthIndicator => {\n return new JetstreamHealthIndicator(connection);\n },\n },\n\n // ShutdownManager — graceful shutdown orchestration\n {\n provide: ShutdownManager,\n inject: [JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS],\n useFactory: (\n connection: ConnectionProvider,\n eventBus: EventBus,\n options: JetstreamModuleOptions,\n ): ShutdownManager => {\n return new ShutdownManager(\n connection,\n eventBus,\n options.shutdownTimeout ?? DEFAULT_SHUTDOWN_TIMEOUT,\n );\n },\n },\n\n // ---------------------------------------------------------------\n // Consumer infrastructure — only created when consumer !== false.\n // Providers return null when consumer is disabled (publisher-only mode).\n // ---------------------------------------------------------------\n\n // PatternRegistry — subject-to-handler mapping\n {\n provide: PatternRegistry,\n inject: [JETSTREAM_OPTIONS],\n useFactory: (options: JetstreamModuleOptions): PatternRegistry | null => {\n if (options.consumer === false) return null;\n\n return new PatternRegistry(options);\n },\n },\n\n // StreamProvider — JetStream stream lifecycle\n {\n provide: StreamProvider,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n ): StreamProvider | null => {\n if (options.consumer === false) return null;\n\n return new StreamProvider(options, connection);\n },\n },\n\n // ConsumerProvider — JetStream consumer lifecycle (receives PatternRegistry for broadcast filtering)\n {\n provide: ConsumerProvider,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION, StreamProvider, PatternRegistry],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n streamProvider: StreamProvider,\n patternRegistry: PatternRegistry,\n ): ConsumerProvider | null => {\n if (options.consumer === false) return null;\n\n return new ConsumerProvider(options, connection, streamProvider, patternRegistry);\n },\n },\n\n // MessageProvider — pull-based message consumption\n {\n provide: MessageProvider,\n inject: [JETSTREAM_OPTIONS, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n eventBus: EventBus,\n ): MessageProvider | null => {\n if (options.consumer === false) return null;\n\n return new MessageProvider(connection, eventBus);\n },\n },\n\n // EventRouter — routes event and broadcast messages to handlers\n {\n provide: EventRouter,\n inject: [\n JETSTREAM_OPTIONS,\n MessageProvider,\n PatternRegistry,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n messageProvider: MessageProvider,\n patternRegistry: PatternRegistry,\n codec: Codec,\n eventBus: EventBus,\n ): EventRouter | null => {\n if (options.consumer === false) return null;\n\n const deadLetterConfig: DeadLetterConfig | undefined = options.onDeadLetter\n ? {\n maxDeliverByStream: new Map(),\n onDeadLetter: options.onDeadLetter,\n }\n : undefined;\n\n return new EventRouter(\n messageProvider,\n patternRegistry,\n codec,\n eventBus,\n deadLetterConfig,\n );\n },\n },\n\n // RpcRouter — routes RPC command messages in JetStream mode\n {\n provide: RpcRouter,\n inject: [\n JETSTREAM_OPTIONS,\n MessageProvider,\n PatternRegistry,\n JETSTREAM_CONNECTION,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n messageProvider: MessageProvider,\n patternRegistry: PatternRegistry,\n connection: ConnectionProvider,\n codec: Codec,\n eventBus: EventBus,\n ): RpcRouter | null => {\n if (options.consumer === false) return null;\n\n const timeout = options.rpc?.mode === 'jetstream' ? options.rpc.timeout : undefined;\n\n return new RpcRouter(\n messageProvider,\n patternRegistry,\n connection,\n codec,\n eventBus,\n timeout,\n );\n },\n },\n\n // CoreRpcServer — RPC via NATS Core request/reply\n {\n provide: CoreRpcServer,\n inject: [\n JETSTREAM_OPTIONS,\n JETSTREAM_CONNECTION,\n PatternRegistry,\n JETSTREAM_CODEC,\n JETSTREAM_EVENT_BUS,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n patternRegistry: PatternRegistry,\n codec: Codec,\n eventBus: EventBus,\n ): CoreRpcServer | null => {\n if (options.consumer === false) return null;\n\n return new CoreRpcServer(options, connection, patternRegistry, codec, eventBus);\n },\n },\n\n // JetstreamStrategy — server-side transport (only when consumer enabled)\n {\n provide: JetstreamStrategy,\n inject: [\n JETSTREAM_OPTIONS,\n JETSTREAM_CONNECTION,\n PatternRegistry,\n StreamProvider,\n ConsumerProvider,\n MessageProvider,\n EventRouter,\n RpcRouter,\n CoreRpcServer,\n ],\n useFactory: (\n options: JetstreamModuleOptions,\n connection: ConnectionProvider,\n patternRegistry: PatternRegistry,\n streamProvider: StreamProvider,\n consumerProvider: ConsumerProvider,\n messageProvider: MessageProvider,\n eventRouter: EventRouter,\n rpcRouter: RpcRouter,\n coreRpcServer: CoreRpcServer,\n ): JetstreamStrategy | null => {\n if (options.consumer === false) return null;\n\n return new JetstreamStrategy(\n options,\n connection,\n patternRegistry,\n streamProvider,\n consumerProvider,\n messageProvider,\n eventRouter,\n rpcRouter,\n coreRpcServer,\n );\n },\n },\n ];\n }\n\n /** Create async options provider from useFactory/useExisting/useClass. */\n private static createAsyncOptionsProvider(asyncOptions: JetstreamModuleAsyncOptions): Provider[] {\n if (asyncOptions.useFactory) {\n const factory = asyncOptions.useFactory;\n\n return [\n {\n provide: JETSTREAM_OPTIONS,\n useFactory: async (...args: unknown[]): Promise<JetstreamModuleOptions> => {\n const partial = await factory(...args);\n\n return { ...partial, name: asyncOptions.name } satisfies JetstreamModuleOptions;\n },\n inject: asyncOptions.inject ?? [],\n },\n ];\n }\n\n if (asyncOptions.useExisting) {\n return [\n {\n provide: JETSTREAM_OPTIONS,\n useFactory: (config: Omit<JetstreamModuleOptions, 'name'>): JetstreamModuleOptions => ({\n ...config,\n name: asyncOptions.name,\n }),\n inject: [asyncOptions.useExisting],\n },\n ];\n }\n\n // useClass — guaranteed by the discriminated union after excluding useFactory and useExisting\n const useClass = asyncOptions.useClass;\n\n return [\n { provide: useClass, useClass },\n {\n provide: JETSTREAM_OPTIONS,\n useFactory: (config: Omit<JetstreamModuleOptions, 'name'>): JetstreamModuleOptions => ({\n ...config,\n name: asyncOptions.name,\n }),\n inject: [useClass],\n },\n ];\n }\n\n // -------------------------------------------------------------------\n // Lifecycle hooks\n // -------------------------------------------------------------------\n\n /**\n * Gracefully shut down the transport on application termination.\n */\n public async onApplicationShutdown(): Promise<void> {\n if (this.shutdownManager) {\n await this.shutdownManager.shutdown(this.strategy ?? undefined);\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { ClientProxy, ReadPacket, WritePacket } from '@nestjs/microservices';\nimport {\n createInbox,\n Events,\n headers as natsHeaders,\n Msg,\n MsgHdrs,\n NatsConnection,\n Subscription,\n} from 'nats';\nimport { Subscription as RxSubscription } from 'rxjs';\n\nimport { ConnectionProvider } from '../connection';\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport type {\n Codec,\n ExtractedRecordData,\n JetstreamModuleOptions,\n TransportHeaderOptions,\n} from '../interfaces';\nimport {\n buildBroadcastSubject,\n buildSubject,\n DEFAULT_JETSTREAM_RPC_TIMEOUT,\n DEFAULT_RPC_TIMEOUT,\n internalName,\n JetstreamHeader,\n} from '../jetstream.constants';\n\nimport { JetstreamRecord } from './jetstream.record';\n\n/**\n * NestJS ClientProxy implementation for the JetStream transport.\n *\n * Supports two operational modes:\n * - **Core mode** (default): Uses `nc.request()` for RPC, `nc.publish()` for events.\n * - **JetStream mode**: Uses `js.publish()` for RPC commands + inbox for responses.\n *\n * Events always go through JetStream publish for guaranteed delivery.\n * The mode only affects RPC (request/reply) behavior.\n *\n * Clients are lightweight — they share the NATS connection from `forRoot()`.\n */\nexport class JetstreamClient extends ClientProxy {\n private readonly logger = new Logger('Jetstream:Client');\n\n /** Target service name this client sends messages to. */\n private readonly targetName: string;\n\n /** Shared inbox for JetStream-mode RPC responses. */\n private inbox: string | null = null;\n private inboxSubscription: Subscription | null = null;\n\n /** Pending JetStream-mode RPC callbacks, keyed by correlation ID. */\n private readonly pendingMessages = new Map<string, (p: WritePacket) => void>();\n\n /** Pending JetStream-mode RPC timeouts, keyed by correlation ID. */\n private readonly pendingTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Subscription to connection status events for disconnect handling. */\n private statusSubscription: RxSubscription | null = null;\n\n public constructor(\n private readonly rootOptions: JetstreamModuleOptions,\n targetServiceName: string,\n private readonly connection: ConnectionProvider,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n ) {\n super();\n this.targetName = targetServiceName;\n }\n\n /**\n * Establish connection. Called automatically by NestJS on first use.\n *\n * Sets up the JetStream RPC inbox (if in JetStream mode) and subscribes\n * to connection status events for fail-fast disconnect handling.\n *\n * @returns The underlying NATS connection.\n */\n public async connect(): Promise<NatsConnection> {\n const nc = await this.connection.getConnection();\n\n // Setup inbox for JetStream RPC mode\n if (this.isJetStreamRpcMode() && !this.inboxSubscription) {\n this.setupInbox(nc);\n }\n\n // Subscribe to disconnect events (once)\n this.statusSubscription ??= this.connection.status$.subscribe((status) => {\n if (status.type === Events.Disconnect) {\n this.handleDisconnect();\n }\n });\n\n return nc;\n }\n\n /** Clean up resources: reject pending RPCs, unsubscribe from status events. */\n public async close(): Promise<void> {\n this.statusSubscription?.unsubscribe();\n this.statusSubscription = null;\n this.rejectPendingRpcs(new Error('Client closed'));\n }\n\n /**\n * Direct access to the raw NATS connection.\n *\n * @throws Error if not connected.\n */\n public override unwrap<T = NatsConnection>(): T {\n const nc = this.connection.unwrap;\n\n if (!nc) {\n throw new Error('Not connected — call connect() before unwrap()');\n }\n\n return nc as T;\n }\n\n /**\n * Publish a fire-and-forget event to JetStream.\n *\n * Events are published to either the workqueue stream or broadcast stream\n * depending on the subject prefix.\n */\n protected async dispatchEvent<T = unknown>(packet: ReadPacket): Promise<T> {\n const nc = await this.connect();\n const { data, hdrs, messageId } = this.extractRecordData(packet.data);\n\n // Determine if this is a broadcast event\n // Broadcast subjects start with 'broadcast:'\n const subject = this.buildEventSubject(packet.pattern);\n const msgHeaders = this.buildHeaders(hdrs, { subject });\n\n const ack = await nc.jetstream().publish(subject, this.codec.encode(data), {\n headers: msgHeaders,\n msgID: messageId ?? crypto.randomUUID(),\n });\n\n if (ack.duplicate) {\n this.logger.warn(`Duplicate event publish detected: ${subject} (seq: ${ack.seq})`);\n }\n\n return undefined as T;\n }\n\n /**\n * Publish an RPC command and register callback for response.\n *\n * Core mode: uses nc.request() with timeout.\n * JetStream mode: publishes to stream + waits for inbox response.\n */\n protected publish(packet: ReadPacket, callback: (p: WritePacket) => void): () => void {\n const subject = buildSubject(this.targetName, 'cmd', packet.pattern);\n const { data, hdrs, timeout, messageId } = this.extractRecordData(packet.data);\n\n const onUnhandled = (err: unknown): void => {\n this.logger.error('Unhandled publish error:', err);\n callback({ err: new Error('Internal transport error'), response: null, isDisposed: true });\n };\n\n // Track correlation ID for cleanup in JetStream mode\n let jetStreamCorrelationId: string | null = null;\n\n if (this.isCoreRpcMode()) {\n this.publishCoreRpc(subject, data, hdrs, timeout, callback).catch(onUnhandled);\n } else {\n jetStreamCorrelationId = crypto.randomUUID();\n this.publishJetStreamRpc(\n subject,\n data,\n hdrs,\n timeout,\n callback,\n jetStreamCorrelationId,\n messageId,\n ).catch(onUnhandled);\n }\n\n return () => {\n // Cleanup for JetStream mode pending messages\n // Core mode cleanup is handled by NATS internally\n if (jetStreamCorrelationId) {\n const timeoutId = this.pendingTimeouts.get(jetStreamCorrelationId);\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(jetStreamCorrelationId);\n }\n\n this.pendingMessages.delete(jetStreamCorrelationId);\n }\n };\n }\n\n /** Core mode: nc.request() with timeout. */\n private async publishCoreRpc(\n subject: string,\n data: unknown,\n customHeaders: Map<string, string> | null,\n timeout: number | undefined,\n callback: (p: WritePacket) => void,\n ): Promise<void> {\n try {\n const nc = await this.connect();\n const effectiveTimeout = timeout ?? this.getRpcTimeout();\n const hdrs = this.buildHeaders(customHeaders, { subject });\n\n const response = await nc.request(subject, this.codec.encode(data), {\n timeout: effectiveTimeout,\n headers: hdrs,\n });\n\n const decoded = this.codec.decode(response.data);\n\n if (response.headers?.get(JetstreamHeader.Error)) {\n callback({ err: decoded, response: null, isDisposed: true });\n } else {\n callback({ err: null, response: decoded, isDisposed: true });\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Unknown error');\n\n this.logger.error(`Core RPC error (${subject}):`, err);\n this.eventBus.emit(TransportEvent.Error, error, 'client-rpc');\n callback({ err: error, response: null, isDisposed: true });\n }\n }\n\n /** JetStream mode: publish to stream + wait for inbox response. */\n private async publishJetStreamRpc(\n subject: string,\n data: unknown,\n customHeaders: Map<string, string> | null,\n timeout: number | undefined,\n callback: (p: WritePacket) => void,\n correlationId: string = crypto.randomUUID(),\n messageId?: string,\n ): Promise<void> {\n const effectiveTimeout = timeout ?? this.getRpcTimeout();\n\n this.pendingMessages.set(correlationId, callback);\n\n const timeoutId = setTimeout(() => {\n if (!this.pendingMessages.has(correlationId)) return;\n\n this.pendingTimeouts.delete(correlationId);\n this.pendingMessages.delete(correlationId);\n this.logger.error(`JetStream RPC timeout (${effectiveTimeout}ms): ${subject}`);\n this.eventBus.emit(TransportEvent.RpcTimeout, subject, correlationId);\n callback({ err: new Error('RPC timeout'), response: null, isDisposed: true });\n }, effectiveTimeout);\n\n this.pendingTimeouts.set(correlationId, timeoutId);\n\n try {\n const nc = await this.connect();\n\n if (!this.inbox) {\n throw new Error('Inbox not initialized — JetStream RPC mode requires a connected inbox');\n }\n\n const hdrs = this.buildHeaders(customHeaders, {\n subject,\n correlationId,\n replyTo: this.inbox,\n });\n\n await nc.jetstream().publish(subject, this.codec.encode(data), {\n headers: hdrs,\n msgID: messageId ?? crypto.randomUUID(),\n });\n } catch (err) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(correlationId);\n\n if (!this.pendingMessages.has(correlationId)) return;\n\n this.pendingMessages.delete(correlationId);\n const error = err instanceof Error ? err : new Error('Unknown error');\n\n this.logger.error(`JetStream RPC publish error (${subject}):`, err);\n callback({ err: error, response: null, isDisposed: true });\n }\n }\n\n /** Fail-fast all pending JetStream RPC callbacks on connection loss. */\n private handleDisconnect(): void {\n this.rejectPendingRpcs(new Error('Connection lost'));\n\n // Reset inbox — will be recreated on next connect()\n this.inbox = null;\n }\n\n /** Reject all pending RPC callbacks, clear timeouts, and tear down inbox. */\n private rejectPendingRpcs(error: Error): void {\n for (const callback of this.pendingMessages.values()) {\n callback({ err: error, response: null, isDisposed: true });\n }\n\n for (const timeoutId of this.pendingTimeouts.values()) {\n clearTimeout(timeoutId);\n }\n\n this.pendingMessages.clear();\n this.pendingTimeouts.clear();\n this.inboxSubscription?.unsubscribe();\n this.inboxSubscription = null;\n }\n\n /** Setup shared inbox subscription for JetStream RPC responses. */\n private setupInbox(nc: NatsConnection): void {\n this.inbox = createInbox(internalName(this.rootOptions.name));\n\n this.inboxSubscription = nc.subscribe(this.inbox, {\n callback: (err, msg) => {\n if (err) {\n this.logger.error('Inbox subscription error:', err);\n return;\n }\n\n this.routeInboxReply(msg);\n },\n });\n\n this.logger.debug(`Inbox subscription: ${this.inbox}`);\n }\n\n /** Route an inbox reply to the matching pending callback. */\n private routeInboxReply(msg: Msg): void {\n const correlationId = msg.headers?.get(JetstreamHeader.CorrelationId);\n\n if (!correlationId) {\n this.logger.warn('Inbox reply without correlation-id, ignoring');\n return;\n }\n\n const callback = this.pendingMessages.get(correlationId);\n\n if (!callback) {\n this.logger.warn(`No pending handler for correlation-id: ${correlationId}`);\n return;\n }\n\n const timeoutId = this.pendingTimeouts.get(correlationId);\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(correlationId);\n }\n\n try {\n const decoded = this.codec.decode(msg.data);\n\n if (msg.headers?.get(JetstreamHeader.Error)) {\n callback({ err: decoded, response: null, isDisposed: true });\n } else {\n callback({ err: null, response: decoded, isDisposed: true });\n }\n } catch (err) {\n callback({\n err: err instanceof Error ? err : new Error('Decode error'),\n response: null,\n isDisposed: true,\n });\n } finally {\n this.pendingMessages.delete(correlationId);\n }\n }\n\n /** Build event subject — workqueue, broadcast, or ordered. */\n private buildEventSubject(pattern: string): string {\n // Convention: 'broadcast:' prefix routes to the shared broadcast stream.\n if (pattern.startsWith('broadcast:')) {\n return buildBroadcastSubject(pattern.slice('broadcast:'.length));\n }\n\n // Convention: 'ordered:' prefix routes to the ordered stream.\n if (pattern.startsWith('ordered:')) {\n return buildSubject(this.targetName, 'ordered', pattern.slice('ordered:'.length));\n }\n\n return buildSubject(this.targetName, 'ev', pattern);\n }\n\n /** Build NATS headers merging custom headers with transport headers. */\n private buildHeaders(\n customHeaders: Map<string, string> | null,\n transport: TransportHeaderOptions,\n ): MsgHdrs {\n const hdrs = natsHeaders();\n\n // Set transport headers\n hdrs.set(JetstreamHeader.Subject, transport.subject);\n hdrs.set(JetstreamHeader.CallerName, internalName(this.rootOptions.name));\n\n if (transport.correlationId) {\n hdrs.set(JetstreamHeader.CorrelationId, transport.correlationId);\n }\n\n if (transport.replyTo) {\n hdrs.set(JetstreamHeader.ReplyTo, transport.replyTo);\n }\n\n // Merge user headers (reserved headers already validated by JetstreamRecordBuilder)\n if (customHeaders) {\n for (const [key, value] of customHeaders) {\n hdrs.set(key, value);\n }\n }\n\n return hdrs;\n }\n\n /** Extract data, headers, and timeout from raw packet data or JetstreamRecord. */\n private extractRecordData(rawData: unknown): ExtractedRecordData {\n if (rawData instanceof JetstreamRecord) {\n return {\n data: rawData.data,\n hdrs: rawData.headers.size > 0 ? new Map(rawData.headers) : null,\n timeout: rawData.timeout,\n messageId: rawData.messageId,\n };\n }\n\n return { data: rawData, hdrs: null, timeout: undefined, messageId: undefined };\n }\n\n private isCoreRpcMode(): boolean {\n return !this.rootOptions.rpc || this.rootOptions.rpc.mode === 'core';\n }\n\n private isJetStreamRpcMode(): boolean {\n return this.rootOptions.rpc?.mode === 'jetstream';\n }\n\n private getRpcTimeout(): number {\n if (!this.rootOptions.rpc) return DEFAULT_RPC_TIMEOUT;\n\n const defaultTimeout = this.isJetStreamRpcMode()\n ? DEFAULT_JETSTREAM_RPC_TIMEOUT\n : DEFAULT_RPC_TIMEOUT;\n\n return this.rootOptions.rpc.timeout ?? defaultTimeout;\n }\n}\n","import type { MsgHdrs } from 'nats';\n\nexport enum TransportEvent {\n Connect = 'connect',\n Disconnect = 'disconnect',\n Reconnect = 'reconnect',\n Error = 'error',\n RpcTimeout = 'rpcTimeout',\n MessageRouted = 'messageRouted',\n ShutdownStart = 'shutdownStart',\n ShutdownComplete = 'shutdownComplete',\n DeadLetter = 'deadLetter',\n}\n\n/**\n * Hook callbacks for transport lifecycle and operational events.\n *\n * Events without a registered hook are silently ignored.\n * Register hooks via `forRoot({ hooks: { ... } })` for monitoring,\n * alerting, or custom observability integration.\n *\n * @example\n * ```typescript\n * JetstreamModule.forRoot({\n * hooks: {\n * [TransportEvent.Error]: (error, context) => sentry.captureException(error),\n * [TransportEvent.RpcTimeout]: (subject) => metrics.increment('rpc.timeout'),\n * },\n * })\n * ```\n */\nexport interface TransportHooks {\n /** Fired when NATS connection is established. */\n [TransportEvent.Connect](server: string): void;\n\n /** Fired when NATS connection is lost. */\n [TransportEvent.Disconnect](): void;\n\n /** Fired when NATS connection is re-established after a disconnect. */\n [TransportEvent.Reconnect](server: string): void;\n\n /** Fired on any transport-level error. */\n [TransportEvent.Error](error: Error, context?: string): void;\n\n /** Fired when an RPC handler exceeds its timeout. */\n [TransportEvent.RpcTimeout](subject: string, correlationId: string): void;\n\n /** Fired after a message is successfully routed to its handler. */\n [TransportEvent.MessageRouted](subject: string, kind: 'rpc' | 'event'): void;\n\n /** Fired at the start of the graceful shutdown sequence. */\n [TransportEvent.ShutdownStart](): void;\n\n /** Fired after graceful shutdown completes. */\n [TransportEvent.ShutdownComplete](): void;\n\n /** Fired when a message exhausts all delivery attempts (dead letter). */\n [TransportEvent.DeadLetter](info: DeadLetterInfo): void;\n}\n\n/**\n * Context passed to the onDeadLetter callback when a message exhausts all delivery attempts.\n */\nexport interface DeadLetterInfo {\n /** The NATS subject the message was published to. */\n subject: string;\n /** Decoded message payload. */\n data: unknown;\n /** Message headers (raw NATS MsgHdrs). */\n headers: MsgHdrs | undefined;\n /** The error that caused the last handler failure. */\n error: unknown;\n /** How many times this message was delivered. */\n deliveryCount: number;\n /** The stream this message belongs to. */\n stream: string;\n /** The stream sequence number. */\n streamSequence: number;\n /** ISO timestamp of the message (derived from msg.info.timestampNanos). */\n timestamp: string;\n}\n","import {\n AckPolicy,\n DeliverPolicy,\n DiscardPolicy,\n ReplayPolicy,\n RetentionPolicy,\n StorageType,\n StoreCompression,\n} from 'nats';\nimport type { ConsumerConfig, StreamConfig } from 'nats';\n\nimport type { StreamKind, SubjectKind } from './interfaces';\n\n// ---------------------------------------------------------------------------\n// Injection Tokens\n// ---------------------------------------------------------------------------\n\n/** Token for the resolved JetstreamModuleOptions. */\nexport const JETSTREAM_OPTIONS = Symbol('JETSTREAM_OPTIONS');\n\n/** Token for the shared ConnectionProvider instance. */\nexport const JETSTREAM_CONNECTION = Symbol('JETSTREAM_CONNECTION');\n\n/** Token for the global Codec instance. */\nexport const JETSTREAM_CODEC = Symbol('JETSTREAM_CODEC');\n\n/** Token for the EventBus instance. */\nexport const JETSTREAM_EVENT_BUS = Symbol('JETSTREAM_EVENT_BUS');\n\n/**\n * Generate the injection token for a `forFeature()` client.\n *\n * Use with `@Inject()` to inject the client created by `JetstreamModule.forFeature()`.\n *\n * @param name - The service name passed to `forFeature({ name })`.\n * @returns The DI token string.\n *\n * @example\n * ```typescript\n * @Inject(getClientToken('orders'))\n * private readonly ordersClient: JetstreamClient;\n * ```\n */\nexport const getClientToken = (name: string): string => name;\n\n// ---------------------------------------------------------------------------\n// Size & Time Helpers\n// ---------------------------------------------------------------------------\n\nconst KB = 1024;\nconst MB = 1024 * KB;\nconst GB = 1024 * MB;\n\n/**\n * Convert milliseconds to nanoseconds (NATS JetStream format).\n *\n * @param ms - Duration in milliseconds.\n * @returns Duration in nanoseconds.\n *\n * @example\n * ```typescript\n * // Set consumer ack_wait to 30 seconds\n * { ack_wait: nanos(30_000) }\n * ```\n */\nexport const nanos = (ms: number): number => ms * 1_000_000;\n\n// ---------------------------------------------------------------------------\n// Default Stream Configurations\n// ---------------------------------------------------------------------------\n\n/* eslint-disable @typescript-eslint/naming-convention -- NATS API uses snake_case property names */\n\n/** Base stream config shared by all stream types. */\nconst baseStreamConfig: Partial<StreamConfig> = {\n retention: RetentionPolicy.Workqueue,\n storage: StorageType.File,\n num_replicas: 1,\n discard: DiscardPolicy.Old,\n allow_direct: true,\n compression: StoreCompression.None,\n};\n\n/** Default config for workqueue event streams. */\nexport const DEFAULT_EVENT_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n allow_rollup_hdrs: true,\n max_consumers: 100,\n max_msg_size: 10 * MB,\n max_msgs_per_subject: 5_000_000,\n max_msgs: 50_000_000,\n max_bytes: 5 * GB,\n max_age: nanos(7 * 24 * 60 * 60 * 1000), // 7 days\n duplicate_window: nanos(2 * 60 * 1000), // 2 min\n};\n\n/** Default config for RPC command streams (jetstream mode only). */\nexport const DEFAULT_COMMAND_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n allow_rollup_hdrs: false,\n max_consumers: 50,\n max_msg_size: 5 * MB,\n max_msgs_per_subject: 100_000,\n max_msgs: 1_000_000,\n max_bytes: 100 * MB,\n max_age: nanos(3 * 60 * 1000), // 3 min\n duplicate_window: nanos(30 * 1000), // 30s\n};\n\n/** Default config for broadcast event streams. */\nexport const DEFAULT_BROADCAST_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n retention: RetentionPolicy.Limits,\n allow_rollup_hdrs: true,\n max_consumers: 200,\n max_msg_size: 10 * MB,\n max_msgs_per_subject: 1_000_000,\n max_msgs: 10_000_000,\n max_bytes: 2 * GB,\n max_age: nanos(24 * 60 * 60 * 1000), // 1 day\n duplicate_window: nanos(2 * 60 * 1000), // 2 min\n};\n\n/** Default config for ordered event streams (Limits retention). */\nexport const DEFAULT_ORDERED_STREAM_CONFIG: Partial<StreamConfig> = {\n ...baseStreamConfig,\n retention: RetentionPolicy.Limits,\n allow_rollup_hdrs: false,\n max_consumers: 100,\n max_msg_size: 10 * MB,\n max_msgs_per_subject: 5_000_000,\n max_msgs: 50_000_000,\n max_bytes: 5 * GB,\n max_age: nanos(24 * 60 * 60 * 1000), // 1 day\n duplicate_window: nanos(2 * 60 * 1000), // 2 min\n};\n\n// ---------------------------------------------------------------------------\n// Default Consumer Configurations\n// ---------------------------------------------------------------------------\n\n/** Default config for workqueue event consumers. */\nexport const DEFAULT_EVENT_CONSUMER_CONFIG: Partial<ConsumerConfig> = {\n ack_wait: nanos(10 * 1000), // 10s\n max_deliver: 3,\n max_ack_pending: 100,\n ack_policy: AckPolicy.Explicit,\n deliver_policy: DeliverPolicy.All,\n replay_policy: ReplayPolicy.Instant,\n};\n\n/** Default config for RPC command consumers (jetstream mode only). */\nexport const DEFAULT_COMMAND_CONSUMER_CONFIG: Partial<ConsumerConfig> = {\n ack_wait: nanos(5 * 60 * 1000), // 5 min\n max_deliver: 1,\n max_ack_pending: 100,\n ack_policy: AckPolicy.Explicit,\n deliver_policy: DeliverPolicy.All,\n replay_policy: ReplayPolicy.Instant,\n};\n\n/** Default config for broadcast event consumers. */\nexport const DEFAULT_BROADCAST_CONSUMER_CONFIG: Partial<ConsumerConfig> = {\n ack_wait: nanos(10 * 1000), // 10s\n max_deliver: 3,\n max_ack_pending: 100,\n ack_policy: AckPolicy.Explicit,\n deliver_policy: DeliverPolicy.All,\n replay_policy: ReplayPolicy.Instant,\n};\n\n/* eslint-enable @typescript-eslint/naming-convention */\n\n// ---------------------------------------------------------------------------\n// Default Module Options\n// ---------------------------------------------------------------------------\n\n/** Default RPC timeout for Core mode (30 seconds). */\nexport const DEFAULT_RPC_TIMEOUT = 30_000;\n\n/** Default RPC timeout for JetStream mode (3 minutes). */\nexport const DEFAULT_JETSTREAM_RPC_TIMEOUT = 180_000;\n\n/** Default graceful shutdown timeout (10 seconds). */\nexport const DEFAULT_SHUTDOWN_TIMEOUT = 10_000;\n\n// ---------------------------------------------------------------------------\n// Reserved Headers\n// ---------------------------------------------------------------------------\n\n/**\n * NATS headers managed by the transport.\n *\n * These headers are set automatically on outbound messages.\n * Some are reserved ({@link RESERVED_HEADERS}) and cannot be overwritten\n * via `JetstreamRecordBuilder.setHeader()`.\n */\nexport enum JetstreamHeader {\n /** Unique ID linking an RPC request to its response. */\n CorrelationId = 'x-correlation-id',\n /** Inbox subject where the RPC response should be published. */\n ReplyTo = 'x-reply-to',\n /** Original subject the message was published to. */\n Subject = 'x-subject',\n /** Internal name of the service that sent the message. */\n CallerName = 'x-caller-name',\n /** Set to `'true'` on error responses so the client can distinguish success from failure. */\n Error = 'x-error',\n}\n\n/** Set of header names that are reserved and cannot be set by users. */\nexport const RESERVED_HEADERS = new Set<string>([\n JetstreamHeader.CorrelationId,\n JetstreamHeader.ReplyTo,\n JetstreamHeader.Error,\n]);\n\n// ---------------------------------------------------------------------------\n// Naming Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build the internal service name with microservice suffix.\n *\n * @param name - Service name from `forRoot({ name })`.\n * @returns `{name}__microservice`\n */\nexport const internalName = (name: string): string => `${name}__microservice`;\n\n/**\n * Build a fully-qualified NATS subject for workqueue events, RPC commands, or ordered events.\n *\n * @param serviceName - Target service name.\n * @param kind - Subject kind (`'ev'`, `'cmd'`, or `'ordered'`).\n * @param pattern - The message pattern (e.g. `'user.created'`).\n * @returns `{serviceName}__microservice.{kind}.{pattern}`\n */\nexport const buildSubject = (serviceName: string, kind: SubjectKind, pattern: string): string =>\n `${internalName(serviceName)}.${kind}.${pattern}`;\n\n/**\n * Build a broadcast subject.\n *\n * @param pattern - The message pattern (e.g. `'config.updated'`).\n * @returns `broadcast.{pattern}`\n */\nexport const buildBroadcastSubject = (pattern: string): string => `broadcast.${pattern}`;\n\n/**\n * Build the JetStream stream name for a given service and kind.\n *\n * @param serviceName - Service name from `forRoot({ name })`.\n * @param kind - Stream kind (`'ev'`, `'cmd'`, or `'broadcast'`).\n * @returns Stream name (e.g. `orders__microservice_ev-stream` or `broadcast-stream`).\n */\nexport const streamName = (serviceName: string, kind: StreamKind): string => {\n if (kind === 'broadcast') return 'broadcast-stream';\n return `${internalName(serviceName)}_${kind}-stream`;\n};\n\n/**\n * Build the JetStream consumer name for a given service and kind.\n *\n * @param serviceName - Service name from `forRoot({ name })`.\n * @param kind - Stream kind (`'ev'`, `'cmd'`, or `'broadcast'`).\n * @returns Consumer name (e.g. `orders__microservice_ev-consumer`).\n */\nexport const consumerName = (serviceName: string, kind: StreamKind): string => {\n if (kind === 'broadcast') return `${internalName(serviceName)}_broadcast-consumer`;\n return `${internalName(serviceName)}_${kind}-consumer`;\n};\n","import { RESERVED_HEADERS } from '../jetstream.constants';\n\n/**\n * Immutable message record for JetStream transport.\n *\n * Compatible with NestJS record builder pattern (like RmqRecord, NatsRecord).\n * Pass as the second argument to `client.send()` or `client.emit()`.\n *\n * @example\n * ```typescript\n * const record = new JetstreamRecordBuilder({ id: 1 })\n * .setHeader('x-tenant', 'acme')\n * .setTimeout(5000)\n * .build();\n *\n * client.send('get.user', record);\n * ```\n */\nexport class JetstreamRecord<TData = unknown> {\n public constructor(\n /** Message payload. */\n public readonly data: TData,\n /** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */\n public readonly headers: ReadonlyMap<string, string>,\n /** Per-request RPC timeout override in ms. */\n public readonly timeout?: number,\n /** Custom message ID for JetStream deduplication. */\n public readonly messageId?: string,\n ) {}\n}\n\n/**\n * Fluent builder for constructing JetstreamRecord instances.\n *\n * Protected headers (`correlation-id`, `reply-to`, `error`) cannot be\n * set by the user — attempting to do so throws an error at build time.\n */\nexport class JetstreamRecordBuilder<TData = unknown> {\n private data: TData | undefined;\n private readonly headers = new Map<string, string>();\n private timeout: number | undefined;\n private messageId: string | undefined;\n\n public constructor(data?: TData) {\n this.data = data;\n }\n\n /**\n * Set the message payload.\n *\n * @param data - Payload to serialize via the configured {@link Codec}.\n */\n public setData(data: TData): this {\n this.data = data;\n return this;\n }\n\n /**\n * Set a single custom header.\n *\n * @param key - Header name (e.g. `'x-tenant'`).\n * @param value - Header value.\n * @throws Error if the header name is reserved by the transport.\n */\n public setHeader(key: string, value: string): this {\n this.validateHeaderKey(key);\n this.headers.set(key, value);\n return this;\n }\n\n /**\n * Set multiple custom headers at once.\n *\n * @param headers - Key-value pairs to set as headers.\n * @throws Error if any header name is reserved by the transport.\n */\n public setHeaders(headers: Record<string, string>): this {\n for (const [key, value] of Object.entries(headers)) {\n this.setHeader(key, value);\n }\n\n return this;\n }\n\n /**\n * Set a custom message ID for JetStream deduplication.\n *\n * NATS JetStream uses this ID to detect duplicate publishes within the\n * stream's `duplicate_window`. If two messages with the same ID arrive\n * within the window, the second is silently dropped.\n *\n * When not set, a random UUID is generated automatically.\n *\n * @param id - Unique message identifier (e.g. order ID, idempotency key).\n *\n * @example\n * ```typescript\n * new JetstreamRecordBuilder(data)\n * .setMessageId(`order-${order.id}`)\n * .build();\n * ```\n */\n public setMessageId(id: string): this {\n this.messageId = id;\n return this;\n }\n\n /**\n * Set per-request RPC timeout.\n *\n * @param ms - Timeout in milliseconds. Overrides the global RPC timeout for this request only.\n */\n public setTimeout(ms: number): this {\n this.timeout = ms;\n return this;\n }\n\n /**\n * Build the immutable {@link JetstreamRecord}.\n *\n * @returns A frozen record ready to pass to `client.send()` or `client.emit()`.\n */\n public build(): JetstreamRecord<TData> {\n return new JetstreamRecord(\n this.data as TData,\n new Map(this.headers),\n this.timeout,\n this.messageId,\n );\n }\n\n /** Validate that a header key is not reserved. */\n private validateHeaderKey(key: string): void {\n if (RESERVED_HEADERS.has(key)) {\n throw new Error(\n `Header \"${key}\" is reserved by the JetStream transport and cannot be set manually. ` +\n `Reserved headers: ${[...RESERVED_HEADERS].join(', ')}`,\n );\n }\n }\n}\n","import { JSONCodec as NatsJSONCodec } from 'nats';\n\nimport type { Codec } from '../interfaces';\n\n/**\n * Default JSON codec wrapping the nats.js JSONCodec.\n *\n * Serializes to/from JSON using the native NATS implementation\n * which handles `TextEncoder`/`TextDecoder` internally.\n *\n * @example\n * ```typescript\n * const codec = new JsonCodec();\n * const bytes = codec.encode({ hello: 'world' });\n * const data = codec.decode(bytes); // { hello: 'world' }\n * ```\n */\nexport class JsonCodec implements Codec {\n private readonly inner = NatsJSONCodec();\n\n public encode(data: unknown): Uint8Array {\n return this.inner.encode(data);\n }\n\n public decode(data: Uint8Array): unknown {\n return this.inner.decode(data);\n }\n}\n","import { Logger } from '@nestjs/common';\nimport {\n connect,\n ConnectionOptions,\n DebugEvents,\n Events,\n JetStreamManager,\n NatsConnection,\n NatsError,\n Status,\n} from 'nats';\nimport { defer, from, Observable, share, shareReplay, switchMap } from 'rxjs';\n\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport type { JetstreamModuleOptions } from '../interfaces';\nimport { internalName } from '../jetstream.constants';\n\n/**\n * Manages the lifecycle of a single NATS connection shared across the application.\n *\n * Provides both Promise-based and Observable-based access to the connection:\n * - `connect()` / `getConnection()` — async/await for one-time setup\n * - `nc$` — cached observable (shareReplay) for reactive consumers\n * - `status$` — live connection status event stream\n *\n * One instance per application, created by `JetstreamModule.forRoot()`.\n */\nexport class ConnectionProvider {\n /** Cached observable that replays the established connection to new subscribers. */\n public readonly nc$: Observable<NatsConnection>;\n\n /** Live stream of connection status events (no replay). */\n public readonly status$: Observable<Status>;\n\n private readonly logger = new Logger('Jetstream:Connection');\n\n private connection: NatsConnection | null = null;\n private connectionPromise: Promise<NatsConnection> | null = null;\n private jsmInstance: JetStreamManager | null = null;\n private jsmPromise: Promise<JetStreamManager> | null = null;\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly eventBus: EventBus,\n ) {\n // Lazy observable — connects on first subscription, caches for all future subscribers\n this.nc$ = defer(() => this.getConnection()).pipe(\n shareReplay({ bufferSize: 1, refCount: false }),\n );\n\n this.status$ = this.nc$.pipe(\n switchMap((nc) => from(nc.status())),\n share(),\n );\n }\n\n /**\n * Establish NATS connection. Idempotent — returns cached connection on subsequent calls.\n *\n * @throws Error if connection is refused (fail fast).\n */\n public async getConnection(): Promise<NatsConnection> {\n if (this.connection && !this.connection.isClosed()) {\n return this.connection;\n }\n\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n this.connectionPromise = this.establish().catch((err) => {\n this.connectionPromise = null;\n throw err;\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Get the JetStream manager. Cached after first call.\n *\n * @returns The JetStreamManager for stream/consumer administration.\n */\n public async getJetStreamManager(): Promise<JetStreamManager> {\n if (this.jsmInstance) return this.jsmInstance;\n if (this.jsmPromise) return this.jsmPromise;\n\n this.jsmPromise = (async (): Promise<JetStreamManager> => {\n const nc = await this.getConnection();\n\n this.jsmInstance = await nc.jetstreamManager();\n this.logger.log('JetStream manager initialized');\n return this.jsmInstance;\n })().finally(() => {\n this.jsmPromise = null;\n });\n\n return this.jsmPromise;\n }\n\n /** Direct access to the raw NATS connection, or `null` if not yet connected. */\n public get unwrap(): NatsConnection | null {\n return this.connection;\n }\n\n /**\n * Gracefully shut down the connection.\n *\n * Sequence: drain → wait for close. Falls back to force-close on error.\n */\n public async shutdown(): Promise<void> {\n // Wait for in-flight connection to settle so it doesn't escape shutdown\n if (this.connectionPromise) {\n try {\n await this.connectionPromise;\n } catch {\n // Connection failed — nothing to shut down\n }\n }\n\n if (!this.connection || this.connection.isClosed()) return;\n\n try {\n await this.connection.drain();\n await this.connection.closed();\n } catch {\n try {\n await this.connection.close();\n } catch {\n // Best-effort — connection may already be gone\n }\n } finally {\n this.connection = null;\n this.connectionPromise = null;\n this.jsmInstance = null;\n this.jsmPromise = null;\n }\n }\n\n /** Internal: establish the physical connection with reconnect monitoring. */\n private async establish(): Promise<NatsConnection> {\n const name = internalName(this.options.name);\n\n try {\n const nc = await connect({\n ...this.options.connectionOptions,\n servers: this.options.servers,\n name,\n } as ConnectionOptions);\n\n this.connection = nc;\n this.logger.log(`NATS connection established: ${nc.getServer()}`);\n this.eventBus.emit(TransportEvent.Connect, nc.getServer());\n\n this.monitorStatus(nc);\n\n return nc;\n } catch (err) {\n if (err instanceof NatsError && err.code === 'CONNECTION_REFUSED') {\n throw new Error(`NATS connection refused: ${this.options.servers.join(', ')}`);\n }\n\n throw err;\n }\n }\n\n /** Subscribe to connection status events and emit hooks. */\n private monitorStatus(nc: NatsConnection): void {\n (async (): Promise<void> => {\n for await (const status of nc.status()) {\n switch (status.type) {\n case Events.Disconnect:\n this.eventBus.emit(TransportEvent.Disconnect);\n break;\n case Events.Reconnect:\n this.jsmInstance = null;\n this.jsmPromise = null;\n this.eventBus.emit(TransportEvent.Reconnect, nc.getServer());\n break;\n case Events.Error:\n this.eventBus.emit(TransportEvent.Error, new Error(String(status.data)), 'connection');\n break;\n case Events.Update:\n case Events.LDM:\n case DebugEvents.Reconnecting:\n case DebugEvents.PingTimer:\n case DebugEvents.StaleConnection:\n case DebugEvents.ClientInitiatedReconnect:\n break;\n }\n }\n })().catch((err) => {\n this.logger.error('Status monitor error', err);\n });\n }\n}\n","import { Logger } from '@nestjs/common';\n\nimport type { TransportHooks } from '../interfaces';\n\n/**\n * Central event bus for transport lifecycle notifications.\n *\n * Dispatches events to user-provided hooks. Events without a\n * registered hook are silently ignored — no default logging.\n *\n * @example\n * ```typescript\n * const bus = new EventBus(logger, {\n * [TransportEvent.Error]: (err) => sentry.captureException(err),\n * });\n *\n * bus.emit(TransportEvent.Error, new Error('timeout'), 'rpc-router');\n * // → calls sentry\n *\n * bus.emit(TransportEvent.Connect, 'nats://localhost:4222');\n * // → no-op (no hook registered)\n * ```\n */\nexport class EventBus {\n private readonly hooks: Partial<TransportHooks>;\n private readonly logger: Logger;\n\n public constructor(logger: Logger, hooks?: Partial<TransportHooks>) {\n this.logger = logger;\n this.hooks = hooks ?? {};\n }\n\n /**\n * Emit a lifecycle event. Dispatches to custom hook if registered, otherwise no-op.\n *\n * @param event - The {@link TransportEvent} to emit.\n * @param args - Arguments matching the hook signature for this event.\n */\n public emit<K extends keyof TransportHooks>(\n event: K,\n ...args: Parameters<TransportHooks[K]>\n ): void {\n const hook = this.hooks[event];\n\n if (!hook) return;\n\n try {\n const result = (hook as (...a: unknown[]) => unknown)(...args);\n\n // Catch async hook rejections that would otherwise go to unhandledRejection\n if (result && typeof (result as Promise<unknown>).catch === 'function') {\n (result as Promise<unknown>).catch((err: unknown) => {\n this.logger.error(\n `Async hook \"${event}\" rejected: ${err instanceof Error ? err.message : err}`,\n );\n });\n }\n } catch (err) {\n this.logger.error(\n `Hook \"${event}\" threw an error: ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\n\nimport { ConnectionProvider } from '../connection';\n\n/**\n * Health status returned by {@link JetstreamHealthIndicator.check}.\n */\nexport interface JetstreamHealthStatus {\n /** Whether the NATS connection is alive. */\n connected: boolean;\n /** NATS server URL, or `null` if not connected. */\n server: string | null;\n /** Round-trip latency in ms, or `null` if disconnected. */\n latency: number | null;\n}\n\n/**\n * Health indicator result compatible with @nestjs/terminus.\n *\n * Follows the Terminus convention: returns status object on success,\n * throws on failure. Works with Terminus out of the box — no wrapper needed:\n *\n * @example\n * ```typescript\n * // With Terminus\n * this.health.check([() => this.jetstream.isHealthy()])\n *\n * // Standalone\n * const status = await this.jetstream.check();\n * ```\n */\n@Injectable()\nexport class JetstreamHealthIndicator {\n private readonly logger = new Logger('Jetstream:Health');\n\n public constructor(private readonly connection: ConnectionProvider) {}\n\n /**\n * Plain health status check.\n *\n * Returns the current connection status without throwing.\n * Use this for custom health endpoints or monitoring integrations.\n *\n * @returns Connection status with server URL and RTT latency.\n */\n public async check(): Promise<JetstreamHealthStatus> {\n const nc = this.connection.unwrap;\n\n if (!nc || nc.isClosed()) {\n return { connected: false, server: null, latency: null };\n }\n\n try {\n const start = performance.now();\n\n await nc.rtt();\n\n const latency = Math.round(performance.now() - start);\n\n return { connected: true, server: nc.getServer(), latency };\n } catch (err) {\n this.logger.warn(`Health check failed: ${err instanceof Error ? err.message : err}`);\n return { connected: false, server: nc.getServer(), latency: null };\n }\n }\n\n /**\n * Terminus-compatible health check.\n *\n * Returns `{ [key]: { status: 'up', ... } }` on success.\n * Throws an error with `{ [key]: { status: 'down', ... } }` on failure.\n *\n * @param key - Health indicator key (default: `'jetstream'`).\n * @returns Object with status, server, and latency under the given key.\n * @throws Error with `{ [key]: { status: 'down' } }` when disconnected.\n */\n public async isHealthy(key = 'jetstream'): Promise<Record<string, Record<string, unknown>>> {\n const status = await this.check();\n\n const details: Record<string, unknown> = {\n status: status.connected ? 'up' : 'down',\n server: status.server,\n latency: status.latency,\n };\n\n if (!status.connected) {\n throw Object.assign(new Error('Jetstream health check failed'), {\n [key]: details,\n });\n }\n\n return { [key]: details };\n }\n}\n","import { CustomTransportStrategy, Server } from '@nestjs/microservices';\nimport type { ConsumerInfo } from 'nats';\n\nimport { ConnectionProvider } from '../connection';\nimport type { JetstreamModuleOptions, StreamKind } from '../interfaces';\n\nimport { CoreRpcServer } from './core-rpc.server';\nimport { ConsumerProvider, MessageProvider, StreamProvider } from './infrastructure';\nimport { EventRouter, PatternRegistry, RpcRouter } from './routing';\n\n/**\n * NestJS custom transport strategy for NATS JetStream.\n *\n * Coordinates all server-side providers:\n * 1. Registers handlers from NestJS into PatternRegistry\n * 2. Creates required streams and consumers\n * 3. Starts message consumption and routing\n * 4. Handles Core or JetStream RPC based on configuration\n *\n * All dependencies are injected via the NestJS DI container.\n */\nexport class JetstreamStrategy extends Server implements CustomTransportStrategy {\n public readonly transportId = Symbol('jetstream-transport');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private readonly listeners = new Map<string, Function[]>();\n private started = false;\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly streamProvider: StreamProvider,\n private readonly consumerProvider: ConsumerProvider,\n private readonly messageProvider: MessageProvider,\n private readonly eventRouter: EventRouter,\n private readonly rpcRouter: RpcRouter,\n private readonly coreRpcServer: CoreRpcServer,\n ) {\n super();\n }\n\n /**\n * Start the transport: register handlers, create infrastructure, begin consumption.\n *\n * Called by NestJS when `connectMicroservice()` is used, or internally by the module.\n */\n public async listen(callback: () => void): Promise<void> {\n if (this.started) {\n this.logger.warn('listen() called more than once — ignoring');\n\n return;\n }\n\n this.started = true;\n\n // 1. Register all NestJS handlers\n this.patternRegistry.registerHandlers(this.getHandlers());\n\n // 2. Determine which streams and durable consumers are needed\n const streamKinds = this.resolveStreamKinds();\n const durableKinds = this.resolveDurableConsumerKinds();\n\n if (streamKinds.length > 0) {\n // 3. Ensure streams exist\n await this.streamProvider.ensureStreams(streamKinds);\n\n // 4. Ensure durable consumers exist (ordered consumers are ephemeral — skip)\n if (durableKinds.length > 0) {\n const consumers = await this.consumerProvider.ensureConsumers(durableKinds);\n\n // 5. Update DLQ thresholds from actual NATS consumer configs\n this.eventRouter.updateMaxDeliverMap(this.buildMaxDeliverMap(consumers));\n\n // 6. Start durable message consumption\n this.messageProvider.start(consumers);\n }\n\n // 7. Start ordered consumer if handlers are registered\n if (this.patternRegistry.hasOrderedHandlers()) {\n const orderedStreamName = this.streamProvider.getStreamName('ordered');\n\n await this.messageProvider.startOrdered(\n orderedStreamName,\n this.patternRegistry.getOrderedSubjects(),\n this.options.ordered,\n );\n }\n\n // 8. Start event router if any event-type handlers exist\n if (\n this.patternRegistry.hasEventHandlers() ||\n this.patternRegistry.hasBroadcastHandlers() ||\n this.patternRegistry.hasOrderedHandlers()\n ) {\n this.eventRouter.start();\n }\n\n // 9. Start RPC router if JetStream mode\n if (this.isJetStreamRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n this.rpcRouter.start();\n }\n }\n\n // 10. Start Core RPC server if core mode\n if (this.isCoreRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n await this.coreRpcServer.start();\n }\n\n callback();\n }\n\n /** Stop all consumers, routers, and subscriptions. Called during shutdown. */\n public close(): void {\n this.eventRouter.destroy();\n this.rpcRouter.destroy();\n this.coreRpcServer.stop();\n this.messageProvider.destroy();\n this.started = false;\n }\n\n /**\n * Register event listener (required by Server base class).\n *\n * Stores callbacks for client use. Primary lifecycle events\n * are routed through EventBus.\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n public on(event: string, callback: Function): void {\n const existing = this.listeners.get(event) ?? [];\n\n existing.push(callback);\n this.listeners.set(event, existing);\n }\n\n /**\n * Unwrap the underlying NATS connection.\n *\n * @throws Error if the transport has not started.\n */\n public unwrap<T>(): T {\n const nc = this.connection.unwrap;\n\n if (!nc) {\n throw new Error('Not connected — transport has not started');\n }\n\n return nc as T;\n }\n\n /** Access the pattern registry (for module-level introspection). */\n public getPatternRegistry(): PatternRegistry {\n return this.patternRegistry;\n }\n\n /** Determine which JetStream streams are needed. */\n private resolveStreamKinds(): StreamKind[] {\n const kinds: StreamKind[] = [];\n\n if (this.patternRegistry.hasEventHandlers()) {\n kinds.push('ev');\n }\n\n if (this.patternRegistry.hasOrderedHandlers()) {\n kinds.push('ordered');\n }\n\n if (this.isJetStreamRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n kinds.push('cmd');\n }\n\n if (this.patternRegistry.hasBroadcastHandlers()) {\n kinds.push('broadcast');\n }\n\n return kinds;\n }\n\n /** Determine which stream kinds need durable consumers (ordered consumers are ephemeral). */\n private resolveDurableConsumerKinds(): StreamKind[] {\n const kinds: StreamKind[] = [];\n\n if (this.patternRegistry.hasEventHandlers()) {\n kinds.push('ev');\n }\n\n if (this.isJetStreamRpcMode() && this.patternRegistry.hasRpcHandlers()) {\n kinds.push('cmd');\n }\n\n if (this.patternRegistry.hasBroadcastHandlers()) {\n kinds.push('broadcast');\n }\n\n return kinds;\n }\n\n /** Build max_deliver map from actual NATS consumer configs (not options). */\n private buildMaxDeliverMap(consumers: Map<StreamKind, ConsumerInfo>): Map<string, number> {\n const map = new Map<string, number>();\n\n for (const [, info] of consumers) {\n const stream = info.stream_name;\n const maxDeliver = info.config.max_deliver;\n\n if (stream && maxDeliver !== undefined && maxDeliver > 0) {\n map.set(stream, maxDeliver);\n }\n }\n\n return map;\n }\n\n private isCoreRpcMode(): boolean {\n return !this.options.rpc || this.options.rpc.mode === 'core';\n }\n\n private isJetStreamRpcMode(): boolean {\n return this.options.rpc?.mode === 'jetstream';\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { headers as natsHeaders, Msg, Subscription } from 'nats';\n\nimport { ConnectionProvider } from '../connection';\nimport { RpcContext } from '../context';\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport type { Codec, JetstreamModuleOptions } from '../interfaces';\nimport { internalName, JetstreamHeader } from '../jetstream.constants';\nimport { serializeError, unwrapResult } from '../utils';\n\nimport { PatternRegistry } from './routing/pattern-registry';\n\n/**\n * Handles RPC via NATS Core request/reply pattern.\n *\n * Subscribes to `{service}.cmd.>` with a queue group for load balancing.\n * Each request is processed and replied to directly via `msg.respond()`.\n *\n * This is the default RPC mode — lowest latency, no persistence overhead.\n */\nexport class CoreRpcServer {\n private readonly logger = new Logger('Jetstream:CoreRpc');\n private subscription: Subscription | null = null;\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n ) {}\n\n /** Start listening for RPC requests on the command subject. */\n public async start(): Promise<void> {\n const nc = await this.connection.getConnection();\n const serviceName = internalName(this.options.name);\n const subject = `${serviceName}.cmd.>`;\n const queue = `${serviceName}_cmd_queue`;\n\n this.subscription = nc.subscribe(subject, {\n queue,\n callback: (err, msg) => {\n if (err) {\n this.logger.error('Core RPC subscription error:', err);\n return;\n }\n\n this.handleRequest(msg).catch((err) => {\n this.logger.error('Unhandled request error:', err);\n });\n },\n });\n\n this.logger.log(`Core RPC listening: ${subject} (queue: ${queue})`);\n }\n\n /** Stop listening and clean up the subscription. */\n public stop(): void {\n if (this.subscription) {\n this.subscription.unsubscribe();\n this.subscription = null;\n }\n }\n\n /** Handle an incoming Core NATS request. */\n private async handleRequest(msg: Msg): Promise<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n this.logger.warn(`No handler for Core RPC: ${msg.subject}`);\n this.respondWithError(msg, new Error(`No handler for subject: ${msg.subject}`));\n return;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'rpc');\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n this.logger.error(`Decode error for Core RPC ${msg.subject}:`, err);\n this.respondWithError(msg, err);\n return;\n }\n\n const ctx = new RpcContext([msg]);\n\n try {\n const result = await unwrapResult(handler(data, ctx));\n\n msg.respond(this.codec.encode(result));\n } catch (err) {\n this.logger.error(`Handler error for Core RPC ${msg.subject}:`, err);\n this.respondWithError(msg, err);\n }\n }\n\n /** Send an error response back to the caller with x-error header. */\n private respondWithError(msg: Msg, error: unknown): void {\n try {\n const hdrs = natsHeaders();\n\n hdrs.set(JetstreamHeader.Error, 'true');\n msg.respond(this.codec.encode(serializeError(error)), { headers: hdrs });\n } catch {\n this.logger.error('Failed to encode error response');\n }\n }\n}\n","import { BaseRpcContext } from '@nestjs/microservices';\nimport { JsMsg, MsgHdrs, Msg } from 'nats';\n\ntype NatsMessage = JsMsg | Msg;\n\n/**\n * Execution context for RPC and event handlers.\n *\n * Provides convenient accessors for the NATS message, subject,\n * and headers without needing to interact with the raw message directly.\n *\n * @example\n * ```typescript\n * @MessagePattern('get.user')\n * getUser(data: GetUserDto, @Ctx() ctx: RpcContext) {\n * const traceId = ctx.getHeader('x-trace-id');\n * const subject = ctx.getSubject();\n * return this.userService.findOne(data.id);\n * }\n * ```\n */\nexport class RpcContext extends BaseRpcContext<[NatsMessage]> {\n /**\n * Get the underlying NATS message.\n *\n * @returns `JsMsg` for JetStream handlers, `Msg` for Core RPC handlers.\n */\n public getMessage(): NatsMessage {\n return this.args[0];\n }\n\n /** @returns The NATS subject this message was published to. */\n public getSubject(): string {\n return this.args[0].subject;\n }\n\n /** @returns All NATS message headers, or `undefined` if none are present. */\n public getHeaders(): MsgHdrs | undefined {\n return this.args[0].headers;\n }\n\n /**\n * Get a single header value by key.\n *\n * @param key - Header name (e.g. `'x-trace-id'`).\n * @returns Header value, or `undefined` if the header is missing.\n */\n public getHeader(key: string): string | undefined {\n return this.args[0].headers?.get(key);\n }\n\n /**\n * Type guard: returns `true` when the message is a JetStream message.\n *\n * Narrows `getMessage()` return type to `JsMsg`, giving access to\n * `ack()`, `nak()`, `term()`, and delivery metadata.\n */\n public isJetStream(): this is RpcContext & { getMessage(): JsMsg } {\n return 'ack' in this.args[0];\n }\n}\n","import { RpcException } from '@nestjs/microservices';\n\n/**\n * Serialize an error for transport over NATS.\n *\n * Handles three cases:\n * 1. `RpcException` — unwraps via `getError()` to preserve the full payload.\n * 2. Generic `Error` — extracts `{ message }` to avoid `\"[object Object]\"`.\n * 3. Plain object — passed through as-is (already unwrapped by NestJS filters).\n *\n * @param err - The error to serialize.\n * @returns A JSON-safe representation of the error.\n */\nexport const serializeError = (err: unknown): unknown => {\n if (err instanceof RpcException) return err.getError();\n if (err instanceof Error) return { message: err.message };\n\n return err;\n};\n","import { isObservable, Observable, Subscription } from 'rxjs';\n\n/**\n * Unwrap a handler result that may be a Promise, Observable, or nested combination.\n *\n * NestJS-wrapped handlers may return `Promise<Observable>` (e.g. when exception\n * filters convert errors to `throwError()` Observables). This function handles:\n *\n * - `Observable` — subscribe immediately (no await — preserves sync emissions)\n * - `Promise<Observable>` — await Promise, then subscribe\n * - `Promise<value>` — await\n * - Plain value — return as-is\n *\n * @param result - The raw handler return value.\n * @returns The resolved value after unwrapping all layers.\n */\nexport const unwrapResult = async (result: unknown): Promise<unknown> => {\n // Direct Observable — subscribe immediately (no microtask yield)\n if (isObservable(result)) {\n return subscribeToFirst(result as Observable<unknown>);\n }\n\n // Await Promise, then check if it resolved to an Observable\n // (NestJS-wrapped handlers return Promise<Observable> when exception filters fire)\n const resolved = await result;\n\n if (isObservable(resolved)) {\n return subscribeToFirst(resolved as Observable<unknown>);\n }\n\n return resolved;\n};\n\n/** Subscribe to an Observable and resolve with its first emitted value. */\nconst subscribeToFirst = (obs: Observable<unknown>): Promise<unknown> =>\n new Promise((resolve, reject) => {\n let done = false;\n let subscription: Subscription | null = null;\n\n subscription = obs.subscribe({\n next: (val: unknown) => {\n if (!done) {\n done = true;\n resolve(val);\n // Unsubscribe if subscribe() has already returned; otherwise deferred below\n subscription?.unsubscribe();\n }\n },\n error: reject,\n complete: () => {\n if (!done) resolve(undefined);\n },\n });\n\n // Handle synchronous emission: next fired before subscribe() returned\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- mutated in sync callback above\n if (done) {\n subscription.unsubscribe();\n }\n });\n","import { Logger } from '@nestjs/common';\nimport { NatsError, StreamConfig, StreamInfo } from 'nats';\n\nimport { ConnectionProvider } from '../../connection';\nimport type { JetstreamModuleOptions, StreamKind } from '../../interfaces';\nimport {\n DEFAULT_BROADCAST_STREAM_CONFIG,\n DEFAULT_COMMAND_STREAM_CONFIG,\n DEFAULT_EVENT_STREAM_CONFIG,\n DEFAULT_ORDERED_STREAM_CONFIG,\n internalName,\n streamName,\n} from '../../jetstream.constants';\n\n/** JetStream API error code for missing streams. */\nconst STREAM_NOT_FOUND = 10059;\n\n/**\n * Manages JetStream stream lifecycle: creation, updates, and idempotent ensures.\n *\n * Creates up to three stream types depending on configuration:\n * - **Event stream** — workqueue events (always, when consumer enabled)\n * - **Command stream** — RPC commands (only in jetstream RPC mode)\n * - **Broadcast stream** — fan-out events (only if broadcast handlers exist)\n *\n * All operations are idempotent: safe to call on every startup and reconnection.\n */\nexport class StreamProvider {\n private readonly logger = new Logger('Jetstream:Stream');\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n ) {}\n\n /**\n * Ensure all required streams exist with correct configuration.\n *\n * @param kinds Which stream kinds to create. Determined by the module based\n * on RPC mode and registered handler patterns.\n */\n public async ensureStreams(kinds: StreamKind[]): Promise<void> {\n const jsm = await this.connection.getJetStreamManager();\n\n await Promise.all(kinds.map((kind) => this.ensureStream(jsm, kind)));\n }\n\n /** Get the stream name for a given kind. */\n public getStreamName(kind: StreamKind): string {\n return streamName(this.options.name, kind);\n }\n\n /** Get the subjects pattern for a given kind. */\n public getSubjects(kind: StreamKind): string[] {\n const name = internalName(this.options.name);\n\n switch (kind) {\n case 'ev':\n return [`${name}.ev.>`];\n case 'cmd':\n return [`${name}.cmd.>`];\n case 'broadcast':\n return ['broadcast.>'];\n case 'ordered':\n return [`${name}.ordered.>`];\n }\n }\n\n /** Ensure a single stream exists, creating or updating as needed. */\n private async ensureStream(\n jsm: Awaited<ReturnType<ConnectionProvider['getJetStreamManager']>>,\n kind: StreamKind,\n ): Promise<StreamInfo> {\n const config = this.buildConfig(kind);\n\n this.logger.log(`Ensuring stream: ${config.name}`);\n\n try {\n // Try to get existing stream info\n await jsm.streams.info(config.name);\n // Stream exists — update config\n this.logger.debug(`Stream exists, updating: ${config.name}`);\n return await jsm.streams.update(config.name, config);\n } catch (err) {\n if (err instanceof NatsError && err.api_error?.err_code === STREAM_NOT_FOUND) {\n this.logger.log(`Creating stream: ${config.name}`);\n return await jsm.streams.add(config as StreamConfig);\n }\n\n throw err;\n }\n }\n\n /** Build the full stream config by merging defaults with user overrides. */\n private buildConfig(\n kind: StreamKind,\n ): Partial<StreamConfig> & { name: string; subjects: string[] } {\n const name = this.getStreamName(kind);\n const subjects = this.getSubjects(kind);\n const description = `JetStream ${kind} stream for ${this.options.name}`;\n\n const defaults = this.getDefaults(kind);\n const overrides = this.getOverrides(kind);\n\n return {\n ...defaults,\n ...overrides,\n name,\n subjects,\n description,\n };\n }\n\n /** Get default config for a stream kind. */\n private getDefaults(kind: StreamKind): Partial<StreamConfig> {\n switch (kind) {\n case 'ev':\n return DEFAULT_EVENT_STREAM_CONFIG;\n case 'cmd':\n return DEFAULT_COMMAND_STREAM_CONFIG;\n case 'broadcast':\n return DEFAULT_BROADCAST_STREAM_CONFIG;\n case 'ordered':\n return DEFAULT_ORDERED_STREAM_CONFIG;\n }\n }\n\n /** Get user-provided overrides for a stream kind. */\n private getOverrides(kind: StreamKind): Partial<StreamConfig> {\n switch (kind) {\n case 'ev':\n return this.options.events?.stream ?? {};\n case 'cmd':\n return this.options.rpc?.mode === 'jetstream' ? (this.options.rpc.stream ?? {}) : {};\n case 'broadcast':\n return this.options.broadcast?.stream ?? {};\n case 'ordered':\n return this.options.ordered?.stream ?? {};\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { ConsumerConfig, ConsumerInfo, NatsError } from 'nats';\n\nimport { ConnectionProvider } from '../../connection';\nimport type { JetstreamModuleOptions, StreamKind } from '../../interfaces';\nimport {\n consumerName,\n DEFAULT_BROADCAST_CONSUMER_CONFIG,\n DEFAULT_COMMAND_CONSUMER_CONFIG,\n DEFAULT_EVENT_CONSUMER_CONFIG,\n internalName,\n} from '../../jetstream.constants';\nimport { PatternRegistry } from '../routing';\n\nimport { StreamProvider } from './stream.provider';\n\n/** JetStream API error code for missing consumers. */\nconst CONSUMER_NOT_FOUND = 10014;\n\n/**\n * Manages JetStream consumer lifecycle: creation and idempotent ensures.\n *\n * Creates durable pull-based consumers that survive restarts.\n * Consumer configuration is merged from defaults and user overrides.\n */\nexport class ConsumerProvider {\n private readonly logger = new Logger('Jetstream:Consumer');\n\n public constructor(\n private readonly options: JetstreamModuleOptions,\n private readonly connection: ConnectionProvider,\n private readonly streamProvider: StreamProvider,\n private readonly patternRegistry: PatternRegistry,\n ) {}\n\n /**\n * Ensure consumers exist for the specified kinds.\n *\n * @returns Map of kind -> ConsumerInfo for downstream use.\n */\n public async ensureConsumers(kinds: StreamKind[]): Promise<Map<StreamKind, ConsumerInfo>> {\n const jsm = await this.connection.getJetStreamManager();\n const results = new Map<StreamKind, ConsumerInfo>();\n\n await Promise.all(\n kinds.map(async (kind) => {\n const info = await this.ensureConsumer(jsm, kind);\n\n results.set(kind, info);\n }),\n );\n\n return results;\n }\n\n /** Get the consumer name for a given kind. */\n public getConsumerName(kind: StreamKind): string {\n return consumerName(this.options.name, kind);\n }\n\n /** Ensure a single consumer exists, creating if needed. */\n private async ensureConsumer(\n jsm: Awaited<ReturnType<ConnectionProvider['getJetStreamManager']>>,\n kind: StreamKind,\n ): Promise<ConsumerInfo> {\n const stream = this.streamProvider.getStreamName(kind);\n const config = this.buildConfig(kind);\n const name = config.durable_name;\n\n this.logger.log(`Ensuring consumer: ${name} on stream: ${stream}`);\n\n try {\n await jsm.consumers.info(stream, name);\n this.logger.debug(`Consumer exists, updating: ${name}`);\n return await jsm.consumers.update(stream, name, config);\n } catch (err) {\n if (err instanceof NatsError && err.api_error?.err_code === CONSUMER_NOT_FOUND) {\n this.logger.log(`Creating consumer: ${name}`);\n return await jsm.consumers.add(stream, config);\n }\n\n throw err;\n }\n }\n\n /** Build consumer config by merging defaults with user overrides. */\n // eslint-disable-next-line @typescript-eslint/naming-convention -- NATS API uses snake_case\n private buildConfig(kind: StreamKind): Partial<ConsumerConfig> & { durable_name: string } {\n const name = this.getConsumerName(kind);\n const serviceName = internalName(this.options.name);\n\n const defaults = this.getDefaults(kind);\n const overrides = this.getOverrides(kind);\n\n /* eslint-disable @typescript-eslint/naming-convention -- NATS API uses snake_case */\n if (kind === 'broadcast') {\n const broadcastPatterns = this.patternRegistry.getBroadcastPatterns();\n\n if (broadcastPatterns.length === 0) {\n throw new Error('Broadcast consumer requested but no broadcast patterns are registered');\n }\n\n if (broadcastPatterns.length === 1) {\n return {\n ...defaults,\n ...overrides,\n name,\n durable_name: name,\n filter_subject: broadcastPatterns[0],\n };\n }\n\n return {\n ...defaults,\n ...overrides,\n name,\n durable_name: name,\n filter_subjects: broadcastPatterns,\n };\n }\n\n // Build filter_subject based on kind\n const filter_subject = kind === 'ev' ? `${serviceName}.ev.>` : `${serviceName}.cmd.>`;\n\n return {\n ...defaults,\n ...overrides,\n name,\n durable_name: name,\n filter_subject,\n };\n /* eslint-enable @typescript-eslint/naming-convention */\n }\n\n /** Get default config for a consumer kind. */\n private getDefaults(kind: StreamKind): Partial<ConsumerConfig> {\n switch (kind) {\n case 'ev':\n return DEFAULT_EVENT_CONSUMER_CONFIG;\n case 'cmd':\n return DEFAULT_COMMAND_CONSUMER_CONFIG;\n case 'broadcast':\n return DEFAULT_BROADCAST_CONSUMER_CONFIG;\n case 'ordered':\n throw new Error('Ordered consumers are ephemeral and should not use durable config');\n }\n }\n\n /** Get user-provided overrides for a consumer kind. */\n private getOverrides(kind: StreamKind): Partial<ConsumerConfig> {\n switch (kind) {\n case 'ev':\n return this.options.events?.consumer ?? {};\n case 'cmd':\n return this.options.rpc?.mode === 'jetstream' ? (this.options.rpc.consumer ?? {}) : {};\n case 'broadcast':\n return this.options.broadcast?.consumer ?? {};\n case 'ordered':\n throw new Error('Ordered consumers are ephemeral and should not use durable config');\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { Consumer, ConsumerInfo, ConsumerMessages, DeliverPolicy, JsMsg } from 'nats';\nimport type { OrderedConsumerOptions } from 'nats';\nimport {\n catchError,\n defer,\n EMPTY,\n merge,\n Observable,\n repeat,\n Subject,\n takeUntil,\n tap,\n timer,\n} from 'rxjs';\n\nimport { ConnectionProvider } from '../../connection';\nimport { EventBus } from '../../hooks';\nimport type { OrderedEventOverrides, StreamKind } from '../../interfaces';\nimport { TransportEvent } from '../../interfaces';\n\n/**\n * Manages pull-based message consumption from JetStream consumers.\n *\n * Uses `defer()` + `repeat()` pattern for self-healing: when the async\n * iterator completes (e.g., NATS restart), the consumer automatically\n * re-establishes after a short delay.\n *\n * Emits messages to kind-specific RxJS subjects for downstream routing.\n */\nexport class MessageProvider {\n private readonly logger = new Logger('Jetstream:Message');\n private readonly activeIterators = new Set<ConsumerMessages>();\n private orderedReadyResolve: (() => void) | null = null;\n private orderedReadyReject: ((err: unknown) => void) | null = null;\n\n private destroy$ = new Subject<void>();\n private eventMessages$ = new Subject<JsMsg>();\n private commandMessages$ = new Subject<JsMsg>();\n private broadcastMessages$ = new Subject<JsMsg>();\n private orderedMessages$ = new Subject<JsMsg>();\n\n public constructor(\n private readonly connection: ConnectionProvider,\n private readonly eventBus: EventBus,\n ) {}\n\n /** Observable stream of workqueue event messages. */\n public get events$(): Observable<JsMsg> {\n return this.eventMessages$.asObservable();\n }\n\n /** Observable stream of RPC command messages (jetstream mode). */\n public get commands$(): Observable<JsMsg> {\n return this.commandMessages$.asObservable();\n }\n\n /** Observable stream of broadcast event messages. */\n public get broadcasts$(): Observable<JsMsg> {\n return this.broadcastMessages$.asObservable();\n }\n\n /** Observable stream of ordered event messages (strict sequential delivery). */\n public get ordered$(): Observable<JsMsg> {\n return this.orderedMessages$.asObservable();\n }\n\n /**\n * Start consuming messages from the given consumer infos.\n *\n * Each consumer gets an independent self-healing flow.\n * Call `destroy()` to stop all consumers.\n */\n public start(consumers: Map<StreamKind, ConsumerInfo>): void {\n const flows: Observable<void>[] = [];\n\n for (const [kind, info] of consumers) {\n flows.push(this.createFlow(kind, info));\n }\n\n if (flows.length > 0) {\n merge(...flows)\n .pipe(takeUntil(this.destroy$))\n .subscribe();\n }\n }\n\n /**\n * Start an ordered consumer for strict sequential delivery.\n *\n * Unlike durable consumers, ordered consumers are ephemeral — created at\n * consumption time, no durable state. nats.js handles auto-recreation.\n *\n * @param streamName - JetStream stream to consume from.\n * @param filterSubjects - NATS subjects to filter on.\n */\n public async startOrdered(\n streamName: string,\n filterSubjects: string[],\n orderedConfig?: OrderedEventOverrides,\n ): Promise<void> {\n const consumerOpts: Partial<OrderedConsumerOptions> = { filterSubjects };\n\n // Workaround: in nats.js (v2.29.x), explicitly passing DeliverPolicy.All to an\n // ordered consumer leaves opt_start_seq in the config, causing consume() to hang.\n // Omitting deliver_policy lets nats.js use its internal default (same All behavior).\n // See: nats.js/lib/jetstream/consumer.js, OrderedPullConsumerImpl.resetConsumer()\n if (\n orderedConfig?.deliverPolicy !== undefined &&\n orderedConfig.deliverPolicy !== DeliverPolicy.All\n ) {\n consumerOpts.deliver_policy = orderedConfig.deliverPolicy;\n }\n\n if (orderedConfig?.optStartSeq !== undefined) {\n consumerOpts.opt_start_seq = orderedConfig.optStartSeq;\n }\n\n if (orderedConfig?.optStartTime !== undefined) {\n consumerOpts.opt_start_time = orderedConfig.optStartTime;\n }\n\n if (orderedConfig?.replayPolicy !== undefined) {\n consumerOpts.replay_policy = orderedConfig.replayPolicy;\n }\n\n // Resolve/reject when the ordered consumer connects or fails on first attempt\n const ready = new Promise<void>((resolve, reject) => {\n this.orderedReadyResolve = resolve;\n this.orderedReadyReject = reject;\n });\n\n const flow = this.createOrderedFlow(streamName, consumerOpts);\n\n flow.pipe(takeUntil(this.destroy$)).subscribe();\n\n return ready;\n }\n\n /** Stop all consumer flows and reinitialize subjects for potential restart. */\n public destroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n\n for (const messages of this.activeIterators) {\n messages.stop();\n }\n\n this.activeIterators.clear();\n\n this.eventMessages$.complete();\n this.commandMessages$.complete();\n this.broadcastMessages$.complete();\n this.orderedMessages$.complete();\n\n // Reinitialize subjects so start() can be called again after destroy()\n this.destroy$ = new Subject<void>();\n this.eventMessages$ = new Subject<JsMsg>();\n this.commandMessages$ = new Subject<JsMsg>();\n this.broadcastMessages$ = new Subject<JsMsg>();\n this.orderedMessages$ = new Subject<JsMsg>();\n }\n\n /** Create a self-healing consumer flow for a specific kind. */\n private createFlow(kind: StreamKind, info: ConsumerInfo): Observable<void> {\n const target$ = this.getTargetSubject(kind);\n let consecutiveFailures = 0;\n let lastRunFailed = false;\n\n return defer(() => this.consumeOnce(info, target$)).pipe(\n tap(() => {\n lastRunFailed = false;\n }),\n catchError((err) => {\n consecutiveFailures++;\n lastRunFailed = true;\n this.logger.error(`Consumer ${info.name} error, will restart:`, err);\n this.eventBus.emit(\n TransportEvent.Error,\n err instanceof Error ? err : new Error(String(err)),\n 'message-provider',\n );\n return EMPTY;\n }),\n repeat({\n delay: () => {\n if (!lastRunFailed) {\n consecutiveFailures = 0;\n }\n\n const delay = Math.min(100 * Math.pow(2, consecutiveFailures), 30_000);\n\n this.logger.warn(`Consumer ${info.name} stream ended, restarting in ${delay}ms...`);\n return timer(delay);\n },\n }),\n takeUntil(this.destroy$),\n );\n }\n\n /** Single iteration: get consumer -> pull messages -> emit to subject. */\n private async consumeOnce(info: ConsumerInfo, target$: Subject<JsMsg>): Promise<void> {\n const js = (await this.connection.getConnection()).jetstream();\n const consumer: Consumer = await js.consumers.get(info.stream_name, info.name);\n const messages = await consumer.consume();\n\n this.activeIterators.add(messages);\n\n try {\n for await (const msg of messages) {\n target$.next(msg);\n }\n } finally {\n this.activeIterators.delete(messages);\n }\n }\n\n /** Get the target subject for a consumer kind. */\n private getTargetSubject(kind: StreamKind): Subject<JsMsg> {\n switch (kind) {\n case 'ev':\n return this.eventMessages$;\n case 'cmd':\n return this.commandMessages$;\n case 'broadcast':\n return this.broadcastMessages$;\n case 'ordered':\n return this.orderedMessages$;\n }\n }\n\n /** Create a self-healing ordered consumer flow. */\n private createOrderedFlow(\n streamName: string,\n consumerOpts: Partial<OrderedConsumerOptions>,\n ): Observable<void> {\n let consecutiveFailures = 0;\n let lastRunFailed = false;\n\n return defer(() => this.consumeOrderedOnce(streamName, consumerOpts)).pipe(\n tap(() => {\n lastRunFailed = false;\n }),\n catchError((err) => {\n consecutiveFailures++;\n lastRunFailed = true;\n this.logger.error('Ordered consumer error, will restart:', err);\n this.eventBus.emit(\n TransportEvent.Error,\n err instanceof Error ? err : new Error(String(err)),\n 'message-provider',\n );\n\n // Fail fast on first error so listen() propagates the failure.\n // Subsequent errors (after retry) are handled by the self-healing loop.\n if (this.orderedReadyReject) {\n this.orderedReadyReject(err);\n this.orderedReadyReject = null;\n this.orderedReadyResolve = null;\n }\n\n return EMPTY;\n }),\n repeat({\n delay: () => {\n if (!lastRunFailed) {\n consecutiveFailures = 0;\n }\n\n const delay = Math.min(100 * Math.pow(2, consecutiveFailures), 30_000);\n\n this.logger.warn(`Ordered consumer stream ended, restarting in ${delay}ms...`);\n return timer(delay);\n },\n }),\n );\n }\n\n /** Single iteration: create ordered consumer -> iterate messages. */\n private async consumeOrderedOnce(\n streamName: string,\n consumerOpts: Partial<OrderedConsumerOptions>,\n ): Promise<void> {\n const js = (await this.connection.getConnection()).jetstream();\n const consumer = await js.consumers.get(streamName, consumerOpts);\n const messages = await consumer.consume();\n\n // Signal that the ordered consumer is ready to receive messages\n if (this.orderedReadyResolve) {\n this.orderedReadyResolve();\n this.orderedReadyResolve = null;\n this.orderedReadyReject = null;\n }\n\n this.activeIterators.add(messages);\n\n try {\n for await (const msg of messages) {\n this.orderedMessages$.next(msg);\n }\n } finally {\n this.activeIterators.delete(messages);\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { MessageHandler } from '@nestjs/microservices';\n\nimport type { JetstreamModuleOptions, PatternsByKind, RegisteredHandler } from '../../interfaces';\nimport { buildBroadcastSubject, buildSubject, internalName } from '../../jetstream.constants';\n\n/**\n * Registry mapping NATS subjects to NestJS message handlers.\n *\n * Handles subject normalization and categorization:\n * - Detects broadcast handlers via `extras.broadcast` metadata\n * - Normalizes full NATS subjects back to user-facing patterns\n * - Provides lists of patterns by category for stream/consumer setup\n */\nexport class PatternRegistry {\n private readonly logger = new Logger('Jetstream:PatternRegistry');\n private readonly registry = new Map<string, RegisteredHandler>();\n\n public constructor(private readonly options: JetstreamModuleOptions) {}\n\n /**\n * Register all handlers from the NestJS strategy.\n *\n * @param handlers Map of pattern -> MessageHandler from `Server.getHandlers()`.\n */\n public registerHandlers(handlers: Map<string, MessageHandler>): void {\n const serviceName = this.options.name;\n\n for (const [pattern, handler] of handlers) {\n const extras = handler.extras as Record<string, unknown> | undefined;\n const isEvent = handler.isEventHandler ?? false;\n const isBroadcast = !!extras?.broadcast;\n const isOrdered = !!extras?.ordered;\n\n if (isBroadcast && isOrdered) {\n throw new Error(\n `Handler \"${pattern}\" cannot be both broadcast and ordered. Use one or the other.`,\n );\n }\n\n // Build the full NATS subject this handler should receive\n let fullSubject: string;\n\n if (isBroadcast) {\n fullSubject = buildBroadcastSubject(pattern);\n } else if (isOrdered) {\n fullSubject = buildSubject(serviceName, 'ordered', pattern);\n } else if (isEvent) {\n fullSubject = buildSubject(serviceName, 'ev', pattern);\n } else {\n fullSubject = buildSubject(serviceName, 'cmd', pattern);\n }\n\n this.registry.set(fullSubject, {\n handler,\n pattern,\n isEvent: isEvent && !isOrdered,\n isBroadcast,\n isOrdered,\n });\n\n let kind: string;\n\n if (isBroadcast) {\n kind = 'broadcast';\n } else if (isOrdered) {\n kind = 'ordered';\n } else if (isEvent) {\n kind = 'event';\n } else {\n kind = 'rpc';\n }\n\n this.logger.debug(`Registered ${kind}: ${pattern} -> ${fullSubject}`);\n }\n\n this.logSummary();\n }\n\n /** Find handler for a full NATS subject. */\n public getHandler(subject: string): MessageHandler | null {\n return this.registry.get(subject)?.handler ?? null;\n }\n\n /** Get all registered broadcast patterns (for consumer filter_subject setup). */\n public getBroadcastPatterns(): string[] {\n return Array.from(this.registry.values())\n .filter((r) => r.isBroadcast)\n .map((r) => `broadcast.${r.pattern}`);\n }\n\n /** Check if any broadcast handlers are registered. */\n public hasBroadcastHandlers(): boolean {\n return Array.from(this.registry.values()).some((r) => r.isBroadcast);\n }\n\n /** Check if any RPC (command) handlers are registered. */\n public hasRpcHandlers(): boolean {\n return Array.from(this.registry.values()).some(\n (r) => !r.isEvent && !r.isBroadcast && !r.isOrdered,\n );\n }\n\n /** Check if any workqueue event handlers are registered. */\n public hasEventHandlers(): boolean {\n return Array.from(this.registry.values()).some((r) => r.isEvent && !r.isBroadcast);\n }\n\n /** Check if any ordered event handlers are registered. */\n public hasOrderedHandlers(): boolean {\n return Array.from(this.registry.values()).some((r) => r.isOrdered);\n }\n\n /** Get fully-qualified NATS subjects for ordered handlers. */\n public getOrderedSubjects(): string[] {\n const name = internalName(this.options.name);\n\n return Array.from(this.registry.values())\n .filter((r) => r.isOrdered)\n .map((r) => `${name}.ordered.${r.pattern}`);\n }\n\n /** Get patterns grouped by kind. */\n public getPatternsByKind(): PatternsByKind {\n const events: string[] = [];\n const commands: string[] = [];\n const broadcasts: string[] = [];\n const ordered: string[] = [];\n\n for (const entry of this.registry.values()) {\n if (entry.isBroadcast) broadcasts.push(entry.pattern);\n else if (entry.isOrdered) ordered.push(entry.pattern);\n else if (entry.isEvent) events.push(entry.pattern);\n else commands.push(entry.pattern);\n }\n\n return { events, commands, broadcasts, ordered };\n }\n\n /** Normalize a full NATS subject back to the user-facing pattern. */\n public normalizeSubject(subject: string): string {\n const name = internalName(this.options.name);\n const prefixes = [`${name}.cmd.`, `${name}.ev.`, `${name}.ordered.`, 'broadcast.'];\n\n for (const prefix of prefixes) {\n if (subject.startsWith(prefix)) {\n return subject.slice(prefix.length);\n }\n }\n\n return subject;\n }\n\n /** Log a summary of all registered handlers. */\n private logSummary(): void {\n const { events, commands, broadcasts, ordered } = this.getPatternsByKind();\n\n const parts = [\n `${commands.length} RPC`,\n `${events.length} events`,\n `${broadcasts.length} broadcasts`,\n ];\n\n if (ordered.length > 0) {\n parts.push(`${ordered.length} ordered`);\n }\n\n this.logger.log(`Registered handlers: ${parts.join(', ')}`);\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { JsMsg } from 'nats';\nimport {\n catchError,\n concatMap,\n defer,\n EMPTY,\n from,\n mergeMap,\n Observable,\n Subscription,\n} from 'rxjs';\n\nimport { RpcContext } from '../../context';\nimport { EventBus } from '../../hooks';\nimport { TransportEvent } from '../../interfaces';\nimport type { Codec, DeadLetterInfo } from '../../interfaces';\nimport { unwrapResult } from '../../utils';\n\nimport { MessageProvider } from '../infrastructure';\nimport { PatternRegistry } from './pattern-registry';\n\n/** Options for dead letter queue handling. */\nexport interface DeadLetterConfig {\n /**\n * Map of stream name -> max_deliver value.\n * Used to detect when a message from a given stream has exhausted all delivery attempts.\n */\n maxDeliverByStream: Map<string, number>;\n /** Async callback invoked when a message exhausts all deliveries. */\n onDeadLetter(info: DeadLetterInfo): Promise<void>;\n}\n\n/**\n * Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.\n *\n * **Workqueue & Broadcast** — at-least-once delivery:\n * - Success -> ack | Error -> nak (retry) | Dead letter -> term\n *\n * **Ordered** — strict sequential delivery:\n * - No ack/nak/DLQ — nats.js auto-acknowledges ordered consumer messages.\n * - Handler errors are logged but do not affect delivery.\n */\nexport class EventRouter {\n private readonly logger = new Logger('Jetstream:EventRouter');\n private readonly subscriptions: Subscription[] = [];\n\n public constructor(\n private readonly messageProvider: MessageProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n private readonly deadLetterConfig?: DeadLetterConfig,\n ) {}\n\n /**\n * Update the max_deliver thresholds from actual NATS consumer configs.\n * Called after consumers are ensured so the DLQ map reflects reality.\n */\n public updateMaxDeliverMap(consumerMaxDelivers: Map<string, number>): void {\n if (!this.deadLetterConfig) return;\n this.deadLetterConfig.maxDeliverByStream = consumerMaxDelivers;\n }\n\n /** Start routing event, broadcast, and ordered messages to handlers. */\n public start(): void {\n this.subscribeToStream(this.messageProvider.events$, 'workqueue');\n this.subscribeToStream(this.messageProvider.broadcasts$, 'broadcast');\n\n if (this.patternRegistry.hasOrderedHandlers()) {\n this.subscribeToStream(this.messageProvider.ordered$, 'ordered', true);\n }\n }\n\n /** Stop routing and unsubscribe from all streams. */\n public destroy(): void {\n for (const sub of this.subscriptions) {\n sub.unsubscribe();\n }\n\n this.subscriptions.length = 0;\n }\n\n /** Subscribe to a message stream and route each message. */\n private subscribeToStream(stream$: Observable<JsMsg>, label: string, isOrdered = false): void {\n const route = (msg: JsMsg): Observable<void> =>\n defer(() => (isOrdered ? this.handleOrdered(msg) : this.handle(msg))).pipe(\n catchError((err) => {\n this.logger.error(`Unexpected error in ${label} event router`, err);\n return EMPTY;\n }),\n );\n\n // Ordered streams use concatMap for strict sequential processing;\n // workqueue/broadcast use mergeMap for parallel handler execution.\n const subscription = stream$.pipe(isOrdered ? concatMap(route) : mergeMap(route)).subscribe();\n\n this.subscriptions.push(subscription);\n }\n\n /** Handle a single event message: decode -> execute handler -> ack/nak. */\n private handle(msg: JsMsg): Observable<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n msg.term(`No handler for event: ${msg.subject}`);\n this.logger.error(`No handler for event subject: ${msg.subject}`);\n return EMPTY;\n }\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n msg.term('Decode error');\n this.logger.error(`Decode error for ${msg.subject}:`, err);\n return EMPTY;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'event');\n\n const ctx = new RpcContext([msg]);\n\n return from(this.executeHandler(handler, data, ctx, msg));\n }\n\n /** Execute handler, then ack on success or nak/dead-letter on failure. */\n private async executeHandler(\n handler: (data: unknown, ctx: RpcContext) => Promise<unknown>,\n data: unknown,\n ctx: RpcContext,\n msg: JsMsg,\n ): Promise<void> {\n try {\n await unwrapResult(handler(data, ctx));\n msg.ack();\n } catch (err) {\n this.logger.error(`Event handler error (${msg.subject}):`, err);\n\n if (this.isDeadLetter(msg)) {\n await this.handleDeadLetter(msg, data, err);\n } else {\n msg.nak();\n }\n }\n }\n\n /** Handle an ordered message: decode -> execute handler -> no ack/nak. */\n private handleOrdered(msg: JsMsg): Observable<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n this.logger.error(`No handler for ordered subject: ${msg.subject}`);\n return EMPTY;\n }\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n this.logger.error(`Decode error for ordered ${msg.subject}:`, err);\n return EMPTY;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'event');\n\n const ctx = new RpcContext([msg]);\n\n return from(\n unwrapResult(handler(data, ctx)).catch((err: unknown) => {\n this.logger.error(`Ordered handler error (${msg.subject}):`, err);\n }),\n ) as Observable<void>;\n }\n\n /** Check if the message has exhausted all delivery attempts. */\n private isDeadLetter(msg: JsMsg): boolean {\n if (!this.deadLetterConfig) return false;\n\n const maxDeliver = this.deadLetterConfig.maxDeliverByStream.get(msg.info.stream);\n\n if (maxDeliver === undefined || maxDeliver <= 0) return false;\n\n return msg.info.deliveryCount >= maxDeliver;\n }\n\n /** Handle a dead letter: invoke callback, then term or nak based on result. */\n private async handleDeadLetter(msg: JsMsg, data: unknown, error: unknown): Promise<void> {\n const info: DeadLetterInfo = {\n subject: msg.subject,\n data,\n headers: msg.headers,\n error,\n deliveryCount: msg.info.deliveryCount,\n stream: msg.info.stream,\n streamSequence: msg.info.streamSequence,\n timestamp: new Date(msg.info.timestampNanos / 1_000_000).toISOString(),\n };\n\n this.eventBus.emit(TransportEvent.DeadLetter, info);\n\n if (!this.deadLetterConfig) return;\n\n try {\n await this.deadLetterConfig.onDeadLetter(info);\n msg.term('Dead letter processed');\n } catch (hookErr) {\n this.logger.error(`onDeadLetter callback failed for ${msg.subject}, nak for retry:`, hookErr);\n msg.nak();\n }\n }\n}\n","import { Logger } from '@nestjs/common';\nimport { MessageHandler } from '@nestjs/microservices';\nimport { headers, JsMsg } from 'nats';\nimport { catchError, defer, EMPTY, from, mergeMap, Observable, Subscription } from 'rxjs';\n\nimport { ConnectionProvider } from '../../connection';\nimport { RpcContext } from '../../context';\nimport { EventBus } from '../../hooks';\nimport { TransportEvent } from '../../interfaces';\nimport type { Codec } from '../../interfaces';\nimport { DEFAULT_JETSTREAM_RPC_TIMEOUT, JetstreamHeader } from '../../jetstream.constants';\nimport { serializeError, unwrapResult } from '../../utils';\n\nimport { MessageProvider } from '../infrastructure';\nimport { PatternRegistry } from './pattern-registry';\n\n/**\n * Routes RPC command messages in JetStream mode.\n *\n * Delivery semantics:\n * - Handler must complete within timeout (default: 3 min)\n * - Success -> ack -> publish response to ReplyTo (publish failure does not affect ack)\n * - Handler error -> publish error to ReplyTo -> term (no redelivery)\n * - Timeout -> no response -> term\n * - No handler / decode error -> term immediately\n *\n * Nak is never used for RPC — prevents duplicate side effects.\n */\nexport class RpcRouter {\n private readonly logger = new Logger('Jetstream:RpcRouter');\n private readonly timeout: number;\n private subscription: Subscription | null = null;\n\n public constructor(\n private readonly messageProvider: MessageProvider,\n private readonly patternRegistry: PatternRegistry,\n private readonly connection: ConnectionProvider,\n private readonly codec: Codec,\n private readonly eventBus: EventBus,\n timeout?: number,\n ) {\n this.timeout = timeout ?? DEFAULT_JETSTREAM_RPC_TIMEOUT;\n }\n\n /** Start routing command messages to handlers. */\n public start(): void {\n this.subscription = this.messageProvider.commands$\n .pipe(\n mergeMap((msg) =>\n defer(() => this.handle(msg)).pipe(\n catchError((err) => {\n this.logger.error('Unexpected error in RPC router', err);\n return EMPTY;\n }),\n ),\n ),\n )\n .subscribe();\n }\n\n /** Stop routing and unsubscribe. */\n public destroy(): void {\n this.subscription?.unsubscribe();\n this.subscription = null;\n }\n\n /** Handle a single RPC command message. */\n private handle(msg: JsMsg): Observable<void> {\n const handler = this.patternRegistry.getHandler(msg.subject);\n\n if (!handler) {\n msg.term(`No handler for RPC: ${msg.subject}`);\n this.logger.error(`No handler for RPC subject: ${msg.subject}`);\n return EMPTY;\n }\n\n const replyTo = msg.headers?.get(JetstreamHeader.ReplyTo);\n const correlationId = msg.headers?.get(JetstreamHeader.CorrelationId);\n\n if (!replyTo || !correlationId) {\n msg.term('Missing required headers (reply-to or correlation-id)');\n this.logger.error(`Missing headers for RPC: ${msg.subject}`);\n return EMPTY;\n }\n\n let data: unknown;\n\n try {\n data = this.codec.decode(msg.data);\n } catch (err) {\n msg.term('Decode error');\n this.logger.error(`Decode error for RPC ${msg.subject}:`, err);\n return EMPTY;\n }\n\n this.eventBus.emit(TransportEvent.MessageRouted, msg.subject, 'rpc');\n\n return from(this.executeHandler(handler, data, msg, replyTo, correlationId));\n }\n\n /** Execute handler, publish response, settle message. */\n private async executeHandler(\n handler: MessageHandler,\n data: unknown,\n msg: JsMsg,\n replyTo: string,\n correlationId: string,\n ): Promise<void> {\n const nc = await this.connection.getConnection();\n const ctx = new RpcContext([msg]);\n\n const hdrs = headers();\n\n hdrs.set(JetstreamHeader.CorrelationId, correlationId);\n\n let settled = false;\n\n // Race handler against timeout\n const timeoutId = setTimeout(() => {\n if (settled) return;\n settled = true;\n this.logger.error(`RPC timeout (${this.timeout}ms): ${msg.subject}`);\n this.eventBus.emit(TransportEvent.RpcTimeout, msg.subject, correlationId);\n msg.term('Handler timeout');\n }, this.timeout);\n\n try {\n const result = await unwrapResult(handler(data, ctx));\n\n // settled may be set by the setTimeout callback above (async race)\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n\n // Ack first — handler succeeded, message is processed regardless of\n // whether we can deliver the response back to the caller.\n msg.ack();\n\n try {\n nc.publish(replyTo, this.codec.encode(result), { headers: hdrs });\n } catch (publishErr) {\n this.logger.error(`Failed to publish RPC response for ${msg.subject}`, publishErr);\n }\n } catch (err) {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n\n // Publish error response with x-error header\n try {\n hdrs.set(JetstreamHeader.Error, 'true');\n nc.publish(replyTo, this.codec.encode(serializeError(err)), { headers: hdrs });\n } catch (encodeErr) {\n this.logger.error(`Failed to encode RPC error for ${msg.subject}`, encodeErr);\n }\n\n msg.term(`Handler error: ${msg.subject}`);\n }\n }\n}\n","import { Logger } from '@nestjs/common';\n\nimport { ConnectionProvider } from '../connection';\nimport { EventBus } from '../hooks';\nimport { TransportEvent } from '../interfaces';\nimport { JetstreamStrategy } from '../server/strategy';\n\n/**\n * Orchestrates graceful transport shutdown.\n *\n * Shutdown sequence:\n * 1. Emit onShutdownStart hook\n * 2. Stop accepting new messages (close subscriptions, stop consumers)\n * 3. Wait for in-flight handlers to complete (up to timeout)\n * 4. Drain and close NATS connection\n * 5. Emit onShutdownComplete hook\n */\nexport class ShutdownManager {\n private readonly logger = new Logger('Jetstream:Shutdown');\n\n public constructor(\n private readonly connection: ConnectionProvider,\n private readonly eventBus: EventBus,\n private readonly timeout: number,\n ) {}\n\n /**\n * Execute the full shutdown sequence.\n *\n * @param strategy Optional strategy to close (stops consumers and subscriptions).\n */\n public async shutdown(strategy?: JetstreamStrategy): Promise<void> {\n this.eventBus.emit(TransportEvent.ShutdownStart);\n this.logger.log(`Graceful shutdown started (timeout: ${this.timeout}ms)`);\n\n // 1. Stop accepting new messages (close subscriptions, stop consumers)\n strategy?.close();\n\n // 2. Drain and close NATS connection.\n // NATS drain() waits for in-flight messages and pending subscriptions,\n // then closes the connection. We add a timeout as a safety net.\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n await Promise.race([\n this.connection.shutdown(),\n new Promise<void>((resolve) => {\n timeoutId = setTimeout(resolve, this.timeout);\n }),\n ]);\n } finally {\n clearTimeout(timeoutId);\n }\n\n this.eventBus.emit(TransportEvent.ShutdownComplete);\n this.logger.log('Graceful shutdown complete');\n }\n}\n"],"mappings":"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","names":["Logger","TransportEvent","JetstreamHeader","headers","Logger","Events","Logger","Events","Logger","Logger","Logger","natsHeaders","Logger","err","natsHeaders","Logger","NatsError","Logger","NatsError","Logger","NatsError","Logger","NatsError","Logger","DeliverPolicy","defer","Logger","streamName","DeliverPolicy","defer","Logger","Logger","Logger","catchError","defer","EMPTY","from","Logger","defer","catchError","EMPTY","from","Logger","catchError","defer","EMPTY","from","mergeMap","Logger","mergeMap","defer","catchError","EMPTY","from","Logger","Logger","Logger"]}
|