@riaskov/nevo-messaging 1.1.1 → 1.1.2
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 +247 -297
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
# Nevo Messaging
|
|
2
2
|
|
|
3
|
-
A powerful microservices messaging framework for NestJS 11+ with Kafka
|
|
3
|
+
A powerful microservices messaging framework for NestJS 11+ with multi-transport support (NATS, Kafka, Socket.IO, HTTP/SSE), designed for building scalable distributed systems with type-safe inter-service communication.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- 🚀 **Type-safe messaging** - Full TypeScript support with auto-completion
|
|
8
|
-
- 🔄 **Dual communication patterns** - Both request-response (query) and fire-and-forget (emit)
|
|
9
|
-
- 📡 **Subscriptions** - Publish/subscribe updates without direct requests
|
|
10
|
-
- 📢 **Broadcast** - System-wide messages for all connected consumers
|
|
11
|
-
- 🎯 **Signal-based routing** - Declarative method mapping with `@Signal` decorator
|
|
12
|
-
- 📡 **Kafka transport** - Production-ready Apache Kafka integration
|
|
13
|
-
- 🧭 **Service discovery** - Heartbeat-based registry topic
|
|
14
|
-
- 🔐 **Access control** - Topic + method + service-level ACLs
|
|
15
|
-
- 🔌 **Multiple transports** - Kafka,
|
|
16
|
-
- 🔧 **Auto-configuration** - Automatic topic creation and client setup
|
|
17
|
-
- 🛡️ **Error handling** - Comprehensive error propagation and timeout management
|
|
18
|
-
- 📊 **BigInt support** - Native handling of large integers across services
|
|
19
|
-
- 🪝 **Lifecycle hooks** - Before/after message processing hooks
|
|
20
|
-
- 🔍 **Debug mode** - Built-in logging for development and troubleshooting
|
|
7
|
+
- 🚀 **Type-safe messaging** - Full TypeScript support with auto-completion
|
|
8
|
+
- 🔄 **Dual communication patterns** - Both request-response (query) and fire-and-forget (emit)
|
|
9
|
+
- 📡 **Subscriptions** - Publish/subscribe updates without direct requests
|
|
10
|
+
- 📢 **Broadcast** - System-wide messages for all connected consumers
|
|
11
|
+
- 🎯 **Signal-based routing** - Declarative method mapping with `@Signal` decorator
|
|
12
|
+
- 📡 **Kafka transport** - Production-ready Apache Kafka integration
|
|
13
|
+
- 🧭 **Service discovery** - Heartbeat-based registry topic
|
|
14
|
+
- 🔐 **Access control** - Topic + method + service-level ACLs
|
|
15
|
+
- 🔌 **Multiple transports** - NATS, Kafka, Socket.IO, HTTP (SSE)
|
|
16
|
+
- 🔧 **Auto-configuration** - Automatic topic creation and client setup
|
|
17
|
+
- 🛡️ **Error handling** - Comprehensive error propagation and timeout management
|
|
18
|
+
- 📊 **BigInt support** - Native handling of large integers across services
|
|
19
|
+
- 🪝 **Lifecycle hooks** - Before/after message processing hooks
|
|
20
|
+
- 🔍 **Debug mode** - Built-in logging for development and troubleshooting
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
@@ -28,23 +28,23 @@ npm install @riaskov/nevo-messaging
|
|
|
28
28
|
### Peer Dependencies
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
npm install @nestjs/common @nestjs/core @nestjs/microservices @nestjs/config @nestjs/platform-fastify kafkajs nats socket.io socket.io-client rxjs reflect-metadata
|
|
31
|
+
npm install @nestjs/common @nestjs/core @nestjs/microservices @nestjs/config @nestjs/platform-fastify kafkajs nats socket.io socket.io-client rxjs reflect-metadata
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
## Quick Start
|
|
35
35
|
|
|
36
|
-
### 1. Basic Service Setup
|
|
36
|
+
### 1. Basic Service Setup (NATS)
|
|
37
37
|
|
|
38
38
|
Create a simple microservice that responds to messages:
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
41
|
// user.service.ts
|
|
42
42
|
import { Injectable, Inject } from "@nestjs/common"
|
|
43
|
-
import {
|
|
43
|
+
import { NatsClientBase, NevoNatsClient } from "@riaskov/nevo-messaging"
|
|
44
44
|
|
|
45
45
|
@Injectable()
|
|
46
|
-
export class UserService extends
|
|
47
|
-
constructor(@Inject("
|
|
46
|
+
export class UserService extends NatsClientBase {
|
|
47
|
+
constructor(@Inject("NEVO_NATS_CLIENT") nevoClient: NevoNatsClient) {
|
|
48
48
|
super(nevoClient)
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -66,11 +66,11 @@ Map service methods to external signals using the `@Signal` decorator:
|
|
|
66
66
|
```typescript
|
|
67
67
|
// user.controller.ts
|
|
68
68
|
import { Controller, Inject } from "@nestjs/common"
|
|
69
|
-
import {
|
|
69
|
+
import { NatsSignalRouter, Signal } from "@riaskov/nevo-messaging"
|
|
70
70
|
import { UserService } from "./user.service"
|
|
71
71
|
|
|
72
72
|
@Controller()
|
|
73
|
-
@
|
|
73
|
+
@NatsSignalRouter([UserService])
|
|
74
74
|
export class UserController {
|
|
75
75
|
constructor(@Inject(UserService) private readonly userService: UserService) {}
|
|
76
76
|
|
|
@@ -84,13 +84,13 @@ export class UserController {
|
|
|
84
84
|
|
|
85
85
|
### 3. Module Configuration
|
|
86
86
|
|
|
87
|
-
Configure the module with
|
|
87
|
+
Configure the module with the NATS client:
|
|
88
88
|
|
|
89
89
|
```typescript
|
|
90
90
|
// user.module.ts
|
|
91
91
|
import { Module } from "@nestjs/common"
|
|
92
92
|
import { ConfigModule } from "@nestjs/config"
|
|
93
|
-
import {
|
|
93
|
+
import { createNevoNatsClient } from "@riaskov/nevo-messaging"
|
|
94
94
|
import { UserController } from "./user.controller"
|
|
95
95
|
import { UserService } from "./user.service"
|
|
96
96
|
|
|
@@ -99,8 +99,9 @@ import { UserService } from "./user.service"
|
|
|
99
99
|
controllers: [UserController],
|
|
100
100
|
providers: [
|
|
101
101
|
UserService,
|
|
102
|
-
|
|
103
|
-
clientIdPrefix: "user"
|
|
102
|
+
createNevoNatsClient(["COORDINATOR"], {
|
|
103
|
+
clientIdPrefix: "user",
|
|
104
|
+
servers: ["nats://127.0.0.1:4222"]
|
|
104
105
|
})
|
|
105
106
|
]
|
|
106
107
|
})
|
|
@@ -109,20 +110,20 @@ export class UserModule {}
|
|
|
109
110
|
|
|
110
111
|
### 4. Application Bootstrap
|
|
111
112
|
|
|
112
|
-
Start your
|
|
113
|
+
Start your service:
|
|
113
114
|
|
|
114
115
|
```typescript
|
|
115
116
|
// main.ts
|
|
116
|
-
import {
|
|
117
|
+
import { NestFactory } from "@nestjs/core"
|
|
117
118
|
import { AppModule } from "./app.module"
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}).then()
|
|
124
|
-
```
|
|
120
|
+
async function bootstrap() {
|
|
121
|
+
const app = await NestFactory.create(AppModule)
|
|
122
|
+
await app.listen(8086)
|
|
123
|
+
}
|
|
125
124
|
|
|
125
|
+
bootstrap()
|
|
126
|
+
```
|
|
126
127
|
## Core Concepts
|
|
127
128
|
|
|
128
129
|
### Signal Routing
|
|
@@ -142,44 +143,44 @@ Use for operations that need a response:
|
|
|
142
143
|
const user = await this.query("user", "user.getById", { id: 123n })
|
|
143
144
|
```
|
|
144
145
|
|
|
145
|
-
#### Emit Pattern (Fire-and-Forget)
|
|
146
|
-
Use for events and notifications:
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
await this.emit("notifications", "user.created", { userId: 123n, email: "user@example.com" })
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
#### Subscription Pattern (Publish/Subscribe)
|
|
153
|
-
Use when you want to receive updates without requesting:
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
const sub = await this.subscribe("user", "user.updated", { ack: true }, async (msg, ctx) => {
|
|
157
|
-
await ctx.ack()
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
await sub.unsubscribe()
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Publish updates:
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
await this.publish("user", "user.updated", { userId: 123n })
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
#### Broadcast Pattern (System-Wide)
|
|
170
|
-
Send to everyone connected to the broker:
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
await this.broadcast("system.status", { ok: true })
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Receive broadcast:
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
await this.subscribe("__broadcast", "system.status", {}, (msg) => {
|
|
180
|
-
console.log("System status:", msg)
|
|
181
|
-
})
|
|
182
|
-
```
|
|
146
|
+
#### Emit Pattern (Fire-and-Forget)
|
|
147
|
+
Use for events and notifications:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
await this.emit("notifications", "user.created", { userId: 123n, email: "user@example.com" })
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Subscription Pattern (Publish/Subscribe)
|
|
154
|
+
Use when you want to receive updates without requesting:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const sub = await this.subscribe("user", "user.updated", { ack: true }, async (msg, ctx) => {
|
|
158
|
+
await ctx.ack()
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
await sub.unsubscribe()
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Publish updates:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
await this.publish("user", "user.updated", { userId: 123n })
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### Broadcast Pattern (System-Wide)
|
|
171
|
+
Send to everyone connected to the broker:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
await this.broadcast("system.status", { ok: true })
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Receive broadcast:
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
await this.subscribe("__broadcast", "system.status", {}, (msg) => {
|
|
181
|
+
console.log("System status:", msg)
|
|
182
|
+
})
|
|
183
|
+
```
|
|
183
184
|
|
|
184
185
|
## Advanced Usage
|
|
185
186
|
|
|
@@ -295,7 +296,7 @@ export class UserController {
|
|
|
295
296
|
}
|
|
296
297
|
```
|
|
297
298
|
|
|
298
|
-
### Error Handling
|
|
299
|
+
### Error Handling
|
|
299
300
|
|
|
300
301
|
The framework provides comprehensive error handling:
|
|
301
302
|
|
|
@@ -316,69 +317,69 @@ export class UserService extends KafkaClientBase {
|
|
|
316
317
|
|
|
317
318
|
return user
|
|
318
319
|
}
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### Method Suggestions (Did You Mean)
|
|
323
|
-
|
|
324
|
-
If you call a method that doesn't exist, the framework returns a helpful error:
|
|
325
|
-
|
|
326
|
-
```
|
|
327
|
-
Invalid method name 'user.getByI', did you mean 'user.getById'?
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
This works for all transports.
|
|
331
|
-
|
|
332
|
-
### Exponential Backoff (Client-Side)
|
|
333
|
-
|
|
334
|
-
Clients apply a backoff for **in-flight requests** to avoid sending a duplicate query while the previous one is still being processed.
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
createNevoKafkaClient(["USER"], {
|
|
338
|
-
clientIdPrefix: "frontend",
|
|
339
|
-
backoff: {
|
|
340
|
-
enabled: true,
|
|
341
|
-
baseMs: 100,
|
|
342
|
-
maxMs: 2000,
|
|
343
|
-
maxAttempts: 0, // 0 = wait until slot is free
|
|
344
|
-
jitter: true
|
|
345
|
-
}
|
|
346
|
-
})
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
This prevents repeated sending of the same request while the service is busy (e.g., stopped on a breakpoint).
|
|
350
|
-
|
|
351
|
-
### Access Control (ACL)
|
|
352
|
-
|
|
353
|
-
Restrict who can read messages by topic + method + service:
|
|
354
|
-
|
|
355
|
-
```typescript
|
|
356
|
-
@KafkaSignalRouter([UserService], {
|
|
357
|
-
accessControl: {
|
|
358
|
-
rules: [
|
|
359
|
-
{ topic: "user-events", method: "*", allow: ["frontend", "coordinator"] },
|
|
360
|
-
{ topic: "user-events", method: "user.delete", deny: ["frontend"] }
|
|
361
|
-
],
|
|
362
|
-
logDenied: true
|
|
363
|
-
}
|
|
364
|
-
})
|
|
365
|
-
export class UserController {}
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
By default, all services are allowed.
|
|
369
|
-
|
|
370
|
-
### Service Discovery (Registry Topic)
|
|
371
|
-
|
|
372
|
-
Each client sends heartbeats to `__nevo.discovery`. You can read the registry:
|
|
373
|
-
|
|
374
|
-
```typescript
|
|
375
|
-
const services = this.getDiscoveredServices()
|
|
376
|
-
const isUserAvailable = this.isServiceAvailable("user")
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
Discovery is enabled by default for Kafka/NATS. HTTP and Socket.IO discovery are
|
|
380
|
-
|
|
381
|
-
## Configuration
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Method Suggestions (Did You Mean)
|
|
324
|
+
|
|
325
|
+
If you call a method that doesn't exist, the framework returns a helpful error:
|
|
326
|
+
|
|
327
|
+
```
|
|
328
|
+
Invalid method name 'user.getByI', did you mean 'user.getById'?
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
This works for all transports.
|
|
332
|
+
|
|
333
|
+
### Exponential Backoff (Client-Side)
|
|
334
|
+
|
|
335
|
+
Clients apply a backoff for **in-flight requests** to avoid sending a duplicate query while the previous one is still being processed.
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
createNevoKafkaClient(["USER"], {
|
|
339
|
+
clientIdPrefix: "frontend",
|
|
340
|
+
backoff: {
|
|
341
|
+
enabled: true,
|
|
342
|
+
baseMs: 100,
|
|
343
|
+
maxMs: 2000,
|
|
344
|
+
maxAttempts: 0, // 0 = wait until slot is free
|
|
345
|
+
jitter: true
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
This prevents repeated sending of the same request while the service is busy (e.g., stopped on a breakpoint).
|
|
351
|
+
|
|
352
|
+
### Access Control (ACL)
|
|
353
|
+
|
|
354
|
+
Restrict who can read messages by topic + method + service:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
@KafkaSignalRouter([UserService], {
|
|
358
|
+
accessControl: {
|
|
359
|
+
rules: [
|
|
360
|
+
{ topic: "user-events", method: "*", allow: ["frontend", "coordinator"] },
|
|
361
|
+
{ topic: "user-events", method: "user.delete", deny: ["frontend"] }
|
|
362
|
+
],
|
|
363
|
+
logDenied: true
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
export class UserController {}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
By default, all services are allowed.
|
|
370
|
+
|
|
371
|
+
### Service Discovery (Registry Topic)
|
|
372
|
+
|
|
373
|
+
Each client sends heartbeats to `__nevo.discovery`. You can read the registry:
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
const services = this.getDiscoveredServices()
|
|
377
|
+
const isUserAvailable = this.isServiceAvailable("user")
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Discovery is enabled by default for Kafka/NATS. HTTP and Socket.IO discovery are available when enabled (HTTP requires `discoveryUrl`).
|
|
381
|
+
|
|
382
|
+
## Configuration
|
|
382
383
|
|
|
383
384
|
### Environment Variables
|
|
384
385
|
|
|
@@ -392,102 +393,108 @@ NODE_ENV=production
|
|
|
392
393
|
### Kafka Client Options
|
|
393
394
|
|
|
394
395
|
```typescript
|
|
395
|
-
createNevoKafkaClient(["USER", "INVENTORY", "NOTIFICATIONS"], {
|
|
396
|
-
clientIdPrefix: "order-service",
|
|
397
|
-
groupIdPrefix: "order-consumer",
|
|
398
|
-
sessionTimeout: 30000,
|
|
399
|
-
allowAutoTopicCreation: true,
|
|
400
|
-
retryAttempts: 5,
|
|
401
|
-
brokerRetryTimeout: 2000,
|
|
402
|
-
timeoutMs: 25000,
|
|
403
|
-
debug: false,
|
|
404
|
-
discovery: {
|
|
405
|
-
enabled: true,
|
|
406
|
-
heartbeatIntervalMs: 5000,
|
|
407
|
-
ttlMs: 15000
|
|
408
|
-
}
|
|
409
|
-
})
|
|
410
|
-
```
|
|
396
|
+
createNevoKafkaClient(["USER", "INVENTORY", "NOTIFICATIONS"], {
|
|
397
|
+
clientIdPrefix: "order-service",
|
|
398
|
+
groupIdPrefix: "order-consumer",
|
|
399
|
+
sessionTimeout: 30000,
|
|
400
|
+
allowAutoTopicCreation: true,
|
|
401
|
+
retryAttempts: 5,
|
|
402
|
+
brokerRetryTimeout: 2000,
|
|
403
|
+
timeoutMs: 25000,
|
|
404
|
+
debug: false,
|
|
405
|
+
discovery: {
|
|
406
|
+
enabled: true,
|
|
407
|
+
heartbeatIntervalMs: 5000,
|
|
408
|
+
ttlMs: 15000
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
```
|
|
411
412
|
|
|
412
413
|
### Microservice Startup Options
|
|
413
414
|
|
|
414
415
|
```typescript
|
|
415
|
-
createKafkaMicroservice({
|
|
416
|
-
microserviceName: "user",
|
|
417
|
-
module: AppModule,
|
|
418
|
-
port: 8086,
|
|
419
|
-
host: "0.0.0.0",
|
|
420
|
-
debug: true,
|
|
421
|
-
onInit: async (app) => {
|
|
422
|
-
// Custom initialization logic
|
|
423
|
-
await app.get(DatabaseService).runMigrations()
|
|
424
|
-
}
|
|
425
|
-
})
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
## Transports
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
```typescript
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
{
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
416
|
+
createKafkaMicroservice({
|
|
417
|
+
microserviceName: "user",
|
|
418
|
+
module: AppModule,
|
|
419
|
+
port: 8086,
|
|
420
|
+
host: "0.0.0.0",
|
|
421
|
+
debug: true,
|
|
422
|
+
onInit: async (app) => {
|
|
423
|
+
// Custom initialization logic
|
|
424
|
+
await app.get(DatabaseService).runMigrations()
|
|
425
|
+
}
|
|
426
|
+
})
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Transports
|
|
430
|
+
|
|
431
|
+
| Transport | Patterns | Discovery | Infra | Notes |
|
|
432
|
+
| --- | --- | --- | --- | --- |
|
|
433
|
+
| NATS | query/emit/publish/subscribe/broadcast | on by default | NATS server | Lowest latency, simple ops |
|
|
434
|
+
| Kafka | query/emit/publish/subscribe/broadcast | on by default | Kafka broker | Durable log, topic setup |
|
|
435
|
+
| Socket.IO | query/emit/publish/subscribe/broadcast | optional | Socket.IO server | WebSocket-friendly apps |
|
|
436
|
+
| HTTP (SSE) | query/emit + SSE subscribe/broadcast | optional | HTTP server | Simple HTTP/SSE integration |
|
|
437
|
+
|
|
438
|
+
### NATS (priority)
|
|
439
|
+
Client factory:
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
createNevoNatsClient(["USER", "COORDINATOR"], {
|
|
443
|
+
clientIdPrefix: "user",
|
|
444
|
+
servers: ["nats://127.0.0.1:4222"]
|
|
445
|
+
})
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Controller decorator:
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
@NatsSignalRouter([UserService])
|
|
452
|
+
export class UserController {}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Kafka
|
|
456
|
+
Use `createKafkaMicroservice` + `KafkaSignalRouter` as before.
|
|
457
|
+
|
|
458
|
+
### Socket.IO
|
|
459
|
+
Socket.IO server is started inside the router decorator:
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
@SocketSignalRouter([UserService], { serviceName: "user", port: 8093 })
|
|
463
|
+
export class UserController {}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Client:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
createNevoSocketClient(
|
|
470
|
+
{ coordinator: "http://127.0.0.1:8094" },
|
|
471
|
+
{ clientIdPrefix: "user" }
|
|
472
|
+
)
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### HTTP (SSE)
|
|
476
|
+
HTTP uses plain POST for `query/emit` and SSE for `subscribe`.
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
@HttpSignalRouter([UserService])
|
|
480
|
+
export class UserController {}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Include transport controller to enable SSE + publish endpoints:
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
controllers: [UserController, HttpTransportController]
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Client:
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
createNevoHttpClient(
|
|
493
|
+
{ coordinator: "http://127.0.0.1:8091" },
|
|
494
|
+
{ clientIdPrefix: "user" }
|
|
495
|
+
)
|
|
496
|
+
```
|
|
497
|
+
## BigInt Support
|
|
491
498
|
|
|
492
499
|
The framework automatically handles BigInt serialization across service boundaries:
|
|
493
500
|
|
|
@@ -860,79 +867,22 @@ createNevoKafkaClient(["HIGH_VOLUME_SERVICE"], {
|
|
|
860
867
|
|
|
861
868
|
## API Reference
|
|
862
869
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
#### `@Signal(signalName, methodName?, paramTransformer?, resultTransformer?)`
|
|
866
|
-
|
|
867
|
-
Maps external signals to service methods.
|
|
868
|
-
|
|
869
|
-
**Parameters:**
|
|
870
|
-
- `signalName` (string): External signal identifier
|
|
871
|
-
- `methodName` (string, optional): Service method name (defaults to signalName)
|
|
872
|
-
- `paramTransformer` (function, optional): Transform incoming parameters
|
|
873
|
-
- `resultTransformer` (function, optional): Transform outgoing results
|
|
874
|
-
|
|
875
|
-
#### `@KafkaSignalRouter(serviceTypes, options?)`
|
|
876
|
-
|
|
877
|
-
Class decorator for signal routing setup.
|
|
878
|
-
|
|
879
|
-
**Parameters:**
|
|
880
|
-
- `serviceTypes` (Type<any> | Type<any>[]): Service classes to route to
|
|
881
|
-
- `options` (object, optional): Configuration options
|
|
882
|
-
|
|
883
|
-
### Classes
|
|
884
|
-
|
|
885
|
-
#### `KafkaClientBase`
|
|
886
|
-
|
|
887
|
-
Base class for services that need to communicate with other microservices.
|
|
888
|
-
|
|
889
|
-
**Methods:**
|
|
890
|
-
- `query<T>(serviceName, method, params): Promise<T>` - Request-response communication
|
|
891
|
-
- `emit(serviceName, method, params): Promise<void>` - Fire-and-forget communication
|
|
892
|
-
- `publish(serviceName, method, params): Promise<void>` - Publish to subscriptions
|
|
893
|
-
- `subscribe(serviceName, method, options, handler): Promise<Subscription>` - Subscribe to updates
|
|
894
|
-
- `broadcast(method, params): Promise<void>` - System-wide broadcast
|
|
895
|
-
- `getAvailableServices(): string[]` - List registered services
|
|
896
|
-
- `getDiscoveredServices(): DiscoveryEntry[]` - Service registry snapshot
|
|
897
|
-
- `isServiceAvailable(serviceName): boolean` - Availability check
|
|
898
|
-
|
|
899
|
-
#### `NevoKafkaClient`
|
|
900
|
-
|
|
901
|
-
Universal Kafka client for multi-service communication.
|
|
902
|
-
|
|
903
|
-
**Methods:**
|
|
904
|
-
- `query<T>(serviceName, method, params): Promise<T>` - Send query to service
|
|
905
|
-
- `emit(serviceName, method, params): Promise<void>` - Emit event to service
|
|
906
|
-
- `publish(serviceName, method, params): Promise<void>` - Publish to subscriptions
|
|
907
|
-
- `subscribe(serviceName, method, options, handler): Promise<Subscription>` - Subscribe to updates
|
|
908
|
-
- `broadcast(method, params): Promise<void>` - System-wide broadcast
|
|
909
|
-
- `getAvailableServices(): string[]` - Get list of available services
|
|
910
|
-
|
|
911
|
-
### Functions
|
|
870
|
+
See `API.md`.
|
|
912
871
|
|
|
913
|
-
|
|
872
|
+
## Examples
|
|
914
873
|
|
|
915
|
-
|
|
874
|
+
### NATS
|
|
875
|
+
- `examples/nats-user` - NATS request/response + publish/subscribe + broadcast
|
|
916
876
|
|
|
917
|
-
|
|
877
|
+
### Kafka
|
|
878
|
+
- `examples/user` - standard Kafka microservice
|
|
918
879
|
|
|
919
|
-
|
|
880
|
+
### Socket.IO
|
|
881
|
+
- `examples/socket-user` - Socket.IO transport with subscribe/broadcast
|
|
920
882
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
- `examples/user` - standard Kafka microservice
|
|
925
|
-
|
|
926
|
-
### NATS
|
|
927
|
-
- `examples/nats-user` - NATS request/response + publish/subscribe + broadcast
|
|
928
|
-
|
|
929
|
-
### HTTP (SSE)
|
|
930
|
-
- `examples/http-user` - HTTP query/emit + SSE subscribe + broadcast + discovery
|
|
931
|
-
|
|
932
|
-
### Socket.IO
|
|
933
|
-
- `examples/socket-user` - Socket.IO transport with subscribe/broadcast
|
|
934
|
-
|
|
935
|
-
## Troubleshooting
|
|
883
|
+
### HTTP (SSE)
|
|
884
|
+
- `examples/http-user` - HTTP query/emit + SSE subscribe + broadcast + discovery
|
|
885
|
+
## Troubleshooting
|
|
936
886
|
|
|
937
887
|
### Common Issues
|
|
938
888
|
|
|
@@ -1013,4 +963,4 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
1013
963
|
- Examples: Check the `examples/` directory for complete working examples
|
|
1014
964
|
|
|
1015
965
|
## Aux
|
|
1016
|
-
There are many anys in core code - the simple temporary solution for changeable Nest.js microservices API.
|
|
966
|
+
There are many anys in core code - the simple temporary solution for changeable Nest.js microservices API.
|
package/package.json
CHANGED