@horizon-republic/nestjs-jetstream 1.0.4
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/LICENSE.md +21 -0
- package/README.md +180 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +18 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/jetstream-client.module.d.ts +6 -0
- package/dist/client/jetstream-client.module.d.ts.map +1 -0
- package/dist/client/jetstream-client.module.js +68 -0
- package/dist/client/jetstream-client.module.js.map +1 -0
- package/dist/client/jetstream.client-proxy.d.ts +179 -0
- package/dist/client/jetstream.client-proxy.d.ts.map +1 -0
- package/dist/client/jetstream.client-proxy.js +300 -0
- package/dist/client/jetstream.client-proxy.js.map +1 -0
- package/dist/client/types/index.d.ts +7 -0
- package/dist/client/types/index.d.ts.map +1 -0
- package/dist/client/types/index.js +3 -0
- package/dist/client/types/index.js.map +1 -0
- package/dist/common/connection.provider.d.ts +309 -0
- package/dist/common/connection.provider.d.ts.map +1 -0
- package/dist/common/connection.provider.js +326 -0
- package/dist/common/connection.provider.js.map +1 -0
- package/dist/common/enum/service-type.enum.d.ts +5 -0
- package/dist/common/enum/service-type.enum.d.ts.map +1 -0
- package/dist/common/enum/service-type.enum.js +9 -0
- package/dist/common/enum/service-type.enum.js.map +1 -0
- package/dist/common/helpers.d.ts +14 -0
- package/dist/common/helpers.d.ts.map +1 -0
- package/dist/common/helpers.js +21 -0
- package/dist/common/helpers.js.map +1 -0
- package/dist/common/index.d.ts +2 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +7 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/pattern-registry.d.ts +51 -0
- package/dist/common/pattern-registry.d.ts.map +1 -0
- package/dist/common/pattern-registry.js +86 -0
- package/dist/common/pattern-registry.js.map +1 -0
- package/dist/common/rpc.context.d.ts +8 -0
- package/dist/common/rpc.context.d.ts.map +1 -0
- package/dist/common/rpc.context.js +14 -0
- package/dist/common/rpc.context.js.map +1 -0
- package/dist/common/types/index.d.ts +2 -0
- package/dist/common/types/index.d.ts.map +1 -0
- package/dist/common/types/index.js +18 -0
- package/dist/common/types/index.js.map +1 -0
- package/dist/common/types/jetstream-transport.options.d.ts +60 -0
- package/dist/common/types/jetstream-transport.options.d.ts.map +1 -0
- package/dist/common/types/jetstream-transport.options.js +3 -0
- package/dist/common/types/jetstream-transport.options.js.map +1 -0
- package/dist/enum/index.d.ts +16 -0
- package/dist/enum/index.d.ts.map +1 -0
- package/dist/enum/index.js +21 -0
- package/dist/enum/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/server/const/index.d.ts +4 -0
- package/dist/server/const/index.d.ts.map +1 -0
- package/dist/server/const/index.js +96 -0
- package/dist/server/const/index.js.map +1 -0
- package/dist/server/enum/index.d.ts +5 -0
- package/dist/server/enum/index.d.ts.map +1 -0
- package/dist/server/enum/index.js +9 -0
- package/dist/server/enum/index.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +19 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/jetstream-server.module.d.ts +157 -0
- package/dist/server/jetstream-server.module.d.ts.map +1 -0
- package/dist/server/jetstream-server.module.js +375 -0
- package/dist/server/jetstream-server.module.js.map +1 -0
- package/dist/server/jetstream.strategy.d.ts +150 -0
- package/dist/server/jetstream.strategy.d.ts.map +1 -0
- package/dist/server/jetstream.strategy.js +192 -0
- package/dist/server/jetstream.strategy.js.map +1 -0
- package/dist/server/jetstream.transport.d.ts +9 -0
- package/dist/server/jetstream.transport.d.ts.map +1 -0
- package/dist/server/jetstream.transport.js +26 -0
- package/dist/server/jetstream.transport.js.map +1 -0
- package/dist/server/providers/consumer.provider.d.ts +226 -0
- package/dist/server/providers/consumer.provider.d.ts.map +1 -0
- package/dist/server/providers/consumer.provider.js +272 -0
- package/dist/server/providers/consumer.provider.js.map +1 -0
- package/dist/server/providers/message-routing.provider.d.ts +295 -0
- package/dist/server/providers/message-routing.provider.d.ts.map +1 -0
- package/dist/server/providers/message-routing.provider.js +420 -0
- package/dist/server/providers/message-routing.provider.js.map +1 -0
- package/dist/server/providers/message.provider.d.ts +142 -0
- package/dist/server/providers/message.provider.d.ts.map +1 -0
- package/dist/server/providers/message.provider.js +209 -0
- package/dist/server/providers/message.provider.js.map +1 -0
- package/dist/server/providers/stream.provider.d.ts +320 -0
- package/dist/server/providers/stream.provider.d.ts.map +1 -0
- package/dist/server/providers/stream.provider.js +376 -0
- package/dist/server/providers/stream.provider.js.map +1 -0
- package/dist/server/types/index.d.ts +7 -0
- package/dist/server/types/index.d.ts.map +1 -0
- package/dist/server/types/index.js +3 -0
- package/dist/server/types/index.js.map +1 -0
- package/dist/server/types/nats.events-map.d.ts +22 -0
- package/dist/server/types/nats.events-map.d.ts.map +1 -0
- package/dist/server/types/nats.events-map.js +4 -0
- package/dist/server/types/nats.events-map.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +76 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [year] [fullname]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# NestJs JetStream Transport
|
|
2
|
+
|
|
3
|
+
A NestJS transport for NATS JetStream with built-in support for **Events** (fire-and-forget) and **Commands** (RPC)
|
|
4
|
+
messaging patterns.
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/jetstream-transport)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🔄 **Full JetStream support**: JetStream used for persistence + Core NATS for low-latency replies in RPC
|
|
12
|
+
- 🚀 **Dual messaging patterns**: Events (pub/sub) and Commands (RPC)
|
|
13
|
+
- 🎯 **Type-safe**: Full TypeScript support with strict types
|
|
14
|
+
- 📦 **Multiple instances**: Run multiple services in a single application
|
|
15
|
+
- ⚡ **High performance**: Optimized for throughput and low latency
|
|
16
|
+
- 🛡️ **Reliable**: At-least-once delivery with configurable acknowledgment strategies
|
|
17
|
+
|
|
18
|
+
# ToDo
|
|
19
|
+
|
|
20
|
+
- 🔧 **Configurable**: Extensive stream and consumer configuration options
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @horizon-republic/nestjs-jetstream
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
# Quick Start
|
|
29
|
+
|
|
30
|
+
## Server (Consumer)
|
|
31
|
+
|
|
32
|
+
Register the module in your app.module.ts:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import {JetstreamServerModule} from '@horizon-republic/nestjs-jetstream'
|
|
36
|
+
|
|
37
|
+
imports: [
|
|
38
|
+
JetstreamServerModule.forRoot({
|
|
39
|
+
name: 'my_service', // Unique name for the JetStream service. Will be registered as `my_service__microservice``
|
|
40
|
+
servers: ['localhost:4222'], // List of NATS servers to connect to.
|
|
41
|
+
}),
|
|
42
|
+
],
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Get transport instance in your main.ts:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import {getJetStreamTransportToken, JetstreamTransport} from '@horizon-republic/nestjs-jetstream';
|
|
49
|
+
|
|
50
|
+
const bootstrap = async () => {
|
|
51
|
+
// ... your code here
|
|
52
|
+
|
|
53
|
+
const transport: JetstreamTransport = app.get(getJetStreamTransportToken('my_service'));
|
|
54
|
+
|
|
55
|
+
app.connectMicroservice(transport, {inheritAppConfig: true});
|
|
56
|
+
|
|
57
|
+
await app.startAllMicroservices();
|
|
58
|
+
|
|
59
|
+
// ... app.listen() and etc
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If everything is set up correctly, you should see the following logs in your console:
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM LOG [StreamProvider] Ensure stream requested: my_service__microservice_ev-stream
|
|
67
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM LOG [StreamProvider] Ensure stream requested: my_service__microservice_cmd-stream
|
|
68
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM LOG [ConnectionProvider] NATS connection established: localhost:4222
|
|
69
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM LOG [ConnectionProvider] NATS JetStream manager initialized
|
|
70
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM DEBUG [StreamProvider] Checking stream existence: my_service__microservice_ev-stream
|
|
71
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM DEBUG [StreamProvider] Checking stream existence: my_service__microservice_cmd-stream
|
|
72
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM LOG [StreamProvider] Stream exists, updating: my_service__microservice_ev-stream (subjects: 1)
|
|
73
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM LOG [StreamProvider] Stream exists, updating: my_service__microservice_cmd-stream (subjects: 1)
|
|
74
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM DEBUG [ConsumerProvider] Consumer exists: my_service__microservice_cmd-consumer
|
|
75
|
+
[Nest] 98936 - 11/04/2025, 10:25:59 PM DEBUG [ConsumerProvider] Consumer exists: my_service__microservice_ev-consumer
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Consumer register 2 message handlers and process them independently:
|
|
79
|
+
|
|
80
|
+
- `my_service__microservice_ev-stream` - for events
|
|
81
|
+
- `my_service__microservice_cmd-stream` - for commands
|
|
82
|
+
|
|
83
|
+
**Message Handlers:**
|
|
84
|
+
|
|
85
|
+
You can register message handlers for events and commands in the same way as you would do for any other NestJS
|
|
86
|
+
microservice.
|
|
87
|
+
You can use the `@EventPattern` and `@MessagePattern` decorators not only in controllers, but also in other classes as
|
|
88
|
+
well.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { EventPattern, MessagePattern, Payload } from '@nestjs/microservices';
|
|
92
|
+
import { Controller } from '@nestjs/common';
|
|
93
|
+
|
|
94
|
+
@Controller()
|
|
95
|
+
export class AppMicroserviceController {
|
|
96
|
+
@EventPattern('user.created')
|
|
97
|
+
public handleEvent(@Payload() payload: any) {
|
|
98
|
+
console.log('Received event:', payload);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@MessagePattern('user.get')
|
|
102
|
+
public handleCommand(@Payload() payload: any) {
|
|
103
|
+
console.log('Received command:', payload);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
id: 1,
|
|
107
|
+
name: 'John Doe',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Client (Publisher)
|
|
115
|
+
|
|
116
|
+
Register the module in your module:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { JetstreamClientModule } from '@horizon-republic/nestjs-jetstream';
|
|
120
|
+
|
|
121
|
+
imports: [
|
|
122
|
+
JetstreamClientModule.forFeature({
|
|
123
|
+
name: 'my_service', // Should match the name of the server module because routing is based on the name
|
|
124
|
+
servers: ['localhost:4222'],
|
|
125
|
+
}),
|
|
126
|
+
]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Using the Client:**
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { ClientProxy } from '@nestjs/microservices';
|
|
133
|
+
import { Controller, Get, Inject } from '@nestjs/common';
|
|
134
|
+
|
|
135
|
+
@Controller()
|
|
136
|
+
export class AppMicroserviceController {
|
|
137
|
+
public constructor(
|
|
138
|
+
@Inject('my_service')
|
|
139
|
+
private readonly myServiceProxy: ClientProxy,
|
|
140
|
+
) {}
|
|
141
|
+
|
|
142
|
+
@Get('send-event')
|
|
143
|
+
public sendEvent() {
|
|
144
|
+
return this.myServiceProxy.emit('user.created', { someData: 'someData' });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@Get('send-command')
|
|
148
|
+
public sendCommand() {
|
|
149
|
+
return this.myServiceProxy.send('user.get', { id: 1 });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Success connection will trigger the following log:
|
|
156
|
+
|
|
157
|
+
```shell
|
|
158
|
+
[Nest] 843 - 11/04/2025, 10:37:37 PM LOG [JetstreamClientProxy] Inbox subscription established: my_service__microservice.PWL9AF1Y7EQKTZ8RSA0V0Y
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Contributing
|
|
162
|
+
|
|
163
|
+
Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT © [Your Name]
|
|
168
|
+
|
|
169
|
+
## Links
|
|
170
|
+
|
|
171
|
+
- [NATS JetStream Documentation](https://docs.nats.io/nats-concepts/jetstream)
|
|
172
|
+
- [NestJS Microservices](https://docs.nestjs.com/microservices/basics)
|
|
173
|
+
- [GitHub Repository](https://github.com/HorizonRepublic/nestjs-jetstream)
|
|
174
|
+
- [npm Package](https://www.npmjs.com/package/@horizon-republic/nestjs-jetstream)
|
|
175
|
+
|
|
176
|
+
## Support
|
|
177
|
+
|
|
178
|
+
- 🐛 [Report bugs](https://github.com/HorizonRepublic/nestjs-jetstream/issues)
|
|
179
|
+
- 💬 [Discussions](https://github.com/HorizonRepublic/nestjs-jetstream/discussions)
|
|
180
|
+
- 📧 Email: [themaiby0@gmail.com](mailto:themaiby0@gmail.com)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./jetstream-client.module"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { IJetstreamTransportOptions } from '../common/types';
|
|
3
|
+
export declare class JetstreamClientModule {
|
|
4
|
+
static forFeature(options: Omit<IJetstreamTransportOptions, 'serviceType'>): DynamicModule;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=jetstream-client.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jetstream-client.module.d.ts","sourceRoot":"","sources":["../../src/client/jetstream-client.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAOvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAK7D,qBACa,qBAAqB;WAClB,UAAU,CACtB,OAAO,EAAE,IAAI,CAAC,0BAA0B,EAAE,aAAa,CAAC,GACvD,aAAa;CAkDjB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var JetstreamClientModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.JetstreamClientModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const microservices_1 = require("@nestjs/microservices");
|
|
13
|
+
const connection_provider_1 = require("../common/connection.provider");
|
|
14
|
+
const service_type_enum_1 = require("../common/enum/service-type.enum");
|
|
15
|
+
const helpers_1 = require("../common/helpers");
|
|
16
|
+
const jetstream_client_proxy_1 = require("./jetstream.client-proxy");
|
|
17
|
+
let JetstreamClientModule = JetstreamClientModule_1 = class JetstreamClientModule {
|
|
18
|
+
static forFeature(options) {
|
|
19
|
+
return {
|
|
20
|
+
module: JetstreamClientModule_1,
|
|
21
|
+
imports: [
|
|
22
|
+
microservices_1.ClientsModule.registerAsync({
|
|
23
|
+
clients: [
|
|
24
|
+
{
|
|
25
|
+
name: options.name,
|
|
26
|
+
extraProviders: [
|
|
27
|
+
{
|
|
28
|
+
provide: (0, helpers_1.getJetStreamClientOptionsToken)(options.name),
|
|
29
|
+
useValue: {
|
|
30
|
+
...options,
|
|
31
|
+
name: `${options.name}__microservice`,
|
|
32
|
+
serviceType: service_type_enum_1.ServiceType.Producer,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
provide: helpers_1.getToken.connection(options.name),
|
|
37
|
+
inject: [(0, helpers_1.getJetStreamClientOptionsToken)(options.name)],
|
|
38
|
+
useFactory: (options) => {
|
|
39
|
+
return new connection_provider_1.ConnectionProvider(options);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
inject: [
|
|
44
|
+
(0, helpers_1.getJetStreamClientOptionsToken)(options.name),
|
|
45
|
+
helpers_1.getToken.connection(options.name),
|
|
46
|
+
],
|
|
47
|
+
useFactory: (options, connectionProvider) => {
|
|
48
|
+
return {
|
|
49
|
+
customClass: jetstream_client_proxy_1.JetstreamClientProxy,
|
|
50
|
+
options: {
|
|
51
|
+
options,
|
|
52
|
+
connectionProvider,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
}),
|
|
59
|
+
],
|
|
60
|
+
exports: [microservices_1.ClientsModule],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
exports.JetstreamClientModule = JetstreamClientModule;
|
|
65
|
+
exports.JetstreamClientModule = JetstreamClientModule = JetstreamClientModule_1 = __decorate([
|
|
66
|
+
(0, common_1.Module)({})
|
|
67
|
+
], JetstreamClientModule);
|
|
68
|
+
//# sourceMappingURL=jetstream-client.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jetstream-client.module.js","sourceRoot":"","sources":["../../src/client/jetstream-client.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,yDAAsD;AAGtD,uEAAmE;AACnE,wEAA+D;AAC/D,+CAA6E;AAG7E,qEAAgE;AAIzD,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IACzB,MAAM,CAAC,UAAU,CACtB,OAAwD;QAExD,OAAO;YACL,MAAM,EAAE,uBAAqB;YAC7B,OAAO,EAAE;gBACP,6BAAa,CAAC,aAAa,CAAC;oBAC1B,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,OAAO,CAAC,IAAI;4BAClB,cAAc,EAAE;gCACd;oCACE,OAAO,EAAE,IAAA,wCAA8B,EAAC,OAAO,CAAC,IAAI,CAAC;oCACrD,QAAQ,EAAE;wCACR,GAAG,OAAO;wCACV,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,gBAAgB;wCACrC,WAAW,EAAE,+BAAW,CAAC,QAAQ;qCAClC;iCACF;gCAED;oCACE,OAAO,EAAE,kBAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;oCAC1C,MAAM,EAAE,CAAC,IAAA,wCAA8B,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oCACtD,UAAU,EAAE,CAAC,OAAmC,EAAsB,EAAE;wCACtE,OAAO,IAAI,wCAAkB,CAAC,OAAO,CAAC,CAAC;oCACzC,CAAC;iCACF;6BACF;4BAED,MAAM,EAAE;gCACN,IAAA,wCAA8B,EAAC,OAAO,CAAC,IAAI,CAAC;gCAC5C,kBAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;6BAClC;4BACD,UAAU,EAAE,CACV,OAAmC,EACnC,kBAAsC,EACjB,EAAE;gCACvB,OAAO;oCACL,WAAW,EAAE,6CAAoB;oCACjC,OAAO,EAAE;wCACP,OAAO;wCACP,kBAAkB;qCACQ;iCAC7B,CAAC;4BACJ,CAAC;yBACF;qBACF;iBACF,CAAC;aACH;YACD,OAAO,EAAE,CAAC,6BAAa,CAAC;SACzB,CAAC;IACJ,CAAC;CACF,CAAA;AArDY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,qBAAqB,CAqDjC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ClientProxy, ReadPacket, WritePacket } from '@nestjs/microservices';
|
|
3
|
+
import { NatsConnection, PubAck } from 'nats';
|
|
4
|
+
import { IClientProviders } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* NATS JetStream client proxy for NestJS microservices.
|
|
7
|
+
*
|
|
8
|
+
* Implements hybrid messaging pattern:
|
|
9
|
+
* - Events: Fire-and-forget via JetStream (guaranteed delivery, no response)
|
|
10
|
+
* - Commands: Request-reply via JetStream + Core NATS inbox (RPC with response).
|
|
11
|
+
*
|
|
12
|
+
* Architecture:.
|
|
13
|
+
* ```
|
|
14
|
+
* Events: Client --[JetStream publish]--> Stream --> Consumers
|
|
15
|
+
* └─> returns immediately
|
|
16
|
+
*
|
|
17
|
+
* Commands: Client --[JetStream publish]--> Stream --> Consumer
|
|
18
|
+
* └─[inbox subscribe]<--[Core NATS publish]<-- Response
|
|
19
|
+
* └─> waits for response via callback
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Fire-and-forget event
|
|
25
|
+
* await firstValueFrom(client.emit('user.created', { id: 1 }));
|
|
26
|
+
*
|
|
27
|
+
* // Request-reply command
|
|
28
|
+
* const user = await firstValueFrom(client.send('get.user', { id: 1 }));
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class JetstreamClientProxy extends ClientProxy implements OnModuleInit {
|
|
32
|
+
private readonly providers;
|
|
33
|
+
private readonly logger;
|
|
34
|
+
private readonly destroy$;
|
|
35
|
+
/**
|
|
36
|
+
* Unique inbox subject for receiving RPC responses.
|
|
37
|
+
* Format: <service_name>.<random>
|
|
38
|
+
* Shared across all command requests from this client instance.
|
|
39
|
+
*/
|
|
40
|
+
private readonly inbox;
|
|
41
|
+
private readonly codec;
|
|
42
|
+
/**
|
|
43
|
+
* Map of pending RPC requests awaiting responses.
|
|
44
|
+
* Key: correlation ID (UUID v7)
|
|
45
|
+
* Value: callback to invoke when response arrives.
|
|
46
|
+
*/
|
|
47
|
+
private readonly pendingMessages;
|
|
48
|
+
/**
|
|
49
|
+
* Flag to prevent duplicate inbox subscriptions.
|
|
50
|
+
* Reset to false on connection errors to allow re-subscription.
|
|
51
|
+
*/
|
|
52
|
+
private isInboxSubscribed;
|
|
53
|
+
constructor(providers: IClientProviders);
|
|
54
|
+
/**
|
|
55
|
+
* Establish connection and setup inbox on module initialization to don't wait for the first request.
|
|
56
|
+
*/
|
|
57
|
+
onModuleInit(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Establishes NATS connection and sets up an inbox subscription for RPC responses.
|
|
60
|
+
*
|
|
61
|
+
* Idempotent: multiple calls reuse existing connection and subscription.
|
|
62
|
+
* Automatically recovers subscription after reconnection.
|
|
63
|
+
*
|
|
64
|
+
* @returns Promise resolving to active NATS connection.
|
|
65
|
+
*/
|
|
66
|
+
connect(): Promise<NatsConnection>;
|
|
67
|
+
/**
|
|
68
|
+
* Gracefully closes connection and cleans up resources.
|
|
69
|
+
*
|
|
70
|
+
* Emits destroy signal to stop connection monitoring,
|
|
71
|
+
* completes all pending observables, and closes NATS connection.
|
|
72
|
+
*/
|
|
73
|
+
close(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Returns raw NATS connection for advanced use cases.
|
|
76
|
+
*
|
|
77
|
+
* @returns Raw NATS connection instance.
|
|
78
|
+
*/
|
|
79
|
+
unwrap<T = NatsConnection>(): T;
|
|
80
|
+
/**
|
|
81
|
+
* Publishes fire-and-forget event to JetStream.
|
|
82
|
+
*
|
|
83
|
+
* Does not wait for acknowledgment or response.
|
|
84
|
+
* JetStream guarantees persistence and at-least-once delivery to consumers.
|
|
85
|
+
*
|
|
86
|
+
* @param packet Event packet containing pattern and data.
|
|
87
|
+
* @returns Promise resolving immediately after publish (undefined).
|
|
88
|
+
*/
|
|
89
|
+
protected dispatchEvent<T = PubAck>(packet: ReadPacket<T>): Promise<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Publishes RPC command to JetStream and registers callback for response.
|
|
92
|
+
*
|
|
93
|
+
* Command is persisted in JetStream for guaranteed delivery.
|
|
94
|
+
* Response arrives via Core NATS inbox subscription.
|
|
95
|
+
*
|
|
96
|
+
* Pattern:
|
|
97
|
+
* 1. Register callback in pending map with correlation ID
|
|
98
|
+
* 2. Publish command with reply-to inbox address
|
|
99
|
+
* 3. Consumer processes command and publishes response to inbox
|
|
100
|
+
* 4. Inbox subscription routes response to callback via correlation ID.
|
|
101
|
+
*
|
|
102
|
+
* @param packet Command packet containing pattern and data.
|
|
103
|
+
* @param callback Function to invoke when response arrives or error occurs.
|
|
104
|
+
* @returns Cleanup function to cancel pending request.
|
|
105
|
+
*/
|
|
106
|
+
protected publish(packet: ReadPacket, callback: (p: WritePacket) => void): () => void;
|
|
107
|
+
/**
|
|
108
|
+
* Internal: executes command publication with error handling.
|
|
109
|
+
*
|
|
110
|
+
* Invokes callback immediately on publish error to fail fast.
|
|
111
|
+
* On success, response will arrive asynchronously via inbox.
|
|
112
|
+
*
|
|
113
|
+
* @param subject Fully-qualified NATS subject to publish to.
|
|
114
|
+
* @param data Payload data to encode and send.
|
|
115
|
+
* @param ctx Context object containing correlation metadata.
|
|
116
|
+
* @param ctx.correlationId UUID v7 linking request and response.
|
|
117
|
+
* @param ctx.messageId Unique message identifier for tracing.
|
|
118
|
+
* @param ctx.callback Function to invoke on error or when response arrives.
|
|
119
|
+
*/
|
|
120
|
+
private publishCommand;
|
|
121
|
+
/**
|
|
122
|
+
* Sets up Core NATS subscription to inbox for receiving RPC responses.
|
|
123
|
+
*
|
|
124
|
+
* Inbox subscription persists across multiple command requests.
|
|
125
|
+
* Each response is routed to the correct callback via correlation ID.
|
|
126
|
+
*
|
|
127
|
+
* Note: Uses Core NATS (not JetStream) for low-latency, ephemeral replies.
|
|
128
|
+
*
|
|
129
|
+
* @param nc Active NATS connection to subscribe with.
|
|
130
|
+
*/
|
|
131
|
+
private setupInboxSubscription;
|
|
132
|
+
/**
|
|
133
|
+
* Routes inbox message to pending callback using correlation ID.
|
|
134
|
+
*
|
|
135
|
+
* Handles:
|
|
136
|
+
* - Missing correlation ID (warns and ignores)
|
|
137
|
+
* - No matching handler (warns - possible timeout/cleanup race)
|
|
138
|
+
* - Decoding errors (invokes callback with error)
|
|
139
|
+
* - Success (invokes callback with response).
|
|
140
|
+
*
|
|
141
|
+
* Always cleans up pending message entry after processing.
|
|
142
|
+
*
|
|
143
|
+
* @param msg NATS message received in inbox subscription.
|
|
144
|
+
*/
|
|
145
|
+
private routeReply;
|
|
146
|
+
/**
|
|
147
|
+
* Creates NATS message headers with common metadata.
|
|
148
|
+
*
|
|
149
|
+
* Standard headers:
|
|
150
|
+
* - message-id: Unique identifier for idempotency and tracing
|
|
151
|
+
* - subject: Full subject name for routing and debugging.
|
|
152
|
+
*
|
|
153
|
+
* Optional headers:
|
|
154
|
+
* - correlation-id: Links request and response for RPC pattern
|
|
155
|
+
* - reply-to: Inbox address for receiving responses.
|
|
156
|
+
*
|
|
157
|
+
* @param data Header data configuration object.
|
|
158
|
+
* @param data.messageId Unique message identifier (UUID v7).
|
|
159
|
+
* @param data.subject Fully-qualified NATS subject.
|
|
160
|
+
* @param data.correlationId Optional correlation ID for RPC linking.
|
|
161
|
+
* @param data.replyTo Optional inbox subject for receiving responses.
|
|
162
|
+
* @returns NATS message headers instance.
|
|
163
|
+
*/
|
|
164
|
+
private createHeaders;
|
|
165
|
+
/**
|
|
166
|
+
* Builds fully-qualified NATS subject from kind and pattern.
|
|
167
|
+
*
|
|
168
|
+
* Format: <service-name>.<kind>.<pattern>
|
|
169
|
+
* Example: "user-service.Command.get.user".
|
|
170
|
+
*
|
|
171
|
+
* This namespacing prevents collisions between services and message types.
|
|
172
|
+
*
|
|
173
|
+
* @param kind Message type (Event or Command).
|
|
174
|
+
* @param pattern User-defined pattern from decorator (e.g., "get.user").
|
|
175
|
+
* @returns Fully-qualified NATS subject string.
|
|
176
|
+
*/
|
|
177
|
+
private buildSubject;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=jetstream.client-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jetstream.client-proxy.d.ts","sourceRoot":"","sources":["../../src/client/jetstream.client-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAiD,cAAc,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAM7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,oBAAqB,SAAQ,WAAY,YAAW,YAAY;IA2BxD,OAAO,CAAC,QAAQ,CAAC,SAAS;IA1B7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAEhD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAGlE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+C;IAE/E;;;OAGG;IACH,OAAO,CAAC,iBAAiB,CAAS;gBAEE,SAAS,EAAE,gBAAgB;IAI/D;;OAEG;IACI,YAAY,IAAI,IAAI;IAI3B;;;;;;;OAOG;IACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IA0B/C;;;;;OAKG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWnC;;;;OAIG;IACa,MAAM,CAAC,CAAC,GAAG,cAAc,KAAK,CAAC;IAI/C;;;;;;;;OAQG;cACa,aAAa,CAAC,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAa5E;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI;IAcrF;;;;;;;;;;;;OAYG;YACW,cAAc;IA6B5B;;;;;;;;;OASG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,UAAU;IA8BlB;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,aAAa;IAsBrB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,YAAY;CAGrB"}
|