@lokative/messaging 0.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 +49 -12
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +14 -0
- package/dist/cjs/kafka.d.ts +1 -0
- package/dist/cjs/kafka.js +5 -0
- package/dist/cjs/messaging.config.d.ts +15 -0
- package/dist/cjs/messaging.config.js +2 -0
- package/dist/cjs/messaging.decorator.d.ts +2 -0
- package/dist/cjs/messaging.decorator.js +20 -0
- package/dist/cjs/messaging.module.d.ts +5 -0
- package/dist/cjs/messaging.module.js +34 -0
- package/dist/cjs/messaging.publisher.d.ts +6 -0
- package/dist/cjs/messaging.publisher.js +32 -0
- package/dist/cjs/messaging.registry.d.ts +12 -0
- package/dist/cjs/messaging.registry.js +67 -0
- package/dist/cjs/nats.d.ts +1 -0
- package/dist/cjs/nats.js +5 -0
- package/dist/cjs/redis.d.ts +1 -0
- package/dist/cjs/redis.js +5 -0
- package/dist/cjs/transport.interface.d.ts +18 -0
- package/dist/cjs/transport.interface.js +4 -0
- package/dist/cjs/transports/kafka.transport.d.ts +15 -0
- package/dist/cjs/transports/kafka.transport.js +82 -0
- package/dist/cjs/transports/nats.transport.d.ts +20 -0
- package/dist/cjs/transports/nats.transport.js +90 -0
- package/dist/cjs/transports/redis.transport.d.ts +16 -0
- package/dist/cjs/transports/redis.transport.js +71 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/kafka.d.ts +1 -0
- package/dist/esm/kafka.js +1 -0
- package/dist/esm/messaging.config.d.ts +15 -0
- package/dist/esm/messaging.config.js +1 -0
- package/dist/esm/messaging.decorator.d.ts +2 -0
- package/dist/esm/messaging.decorator.js +16 -0
- package/dist/esm/messaging.module.d.ts +5 -0
- package/dist/esm/messaging.module.js +31 -0
- package/dist/esm/messaging.publisher.d.ts +6 -0
- package/dist/esm/messaging.publisher.js +29 -0
- package/dist/esm/messaging.registry.d.ts +12 -0
- package/dist/esm/messaging.registry.js +64 -0
- package/dist/esm/nats.d.ts +1 -0
- package/dist/esm/nats.js +1 -0
- package/dist/esm/redis.d.ts +1 -0
- package/dist/esm/redis.js +1 -0
- package/dist/esm/transport.interface.d.ts +18 -0
- package/dist/esm/transport.interface.js +1 -0
- package/dist/esm/transports/kafka.transport.d.ts +15 -0
- package/dist/esm/transports/kafka.transport.js +79 -0
- package/dist/esm/transports/nats.transport.d.ts +20 -0
- package/dist/esm/transports/nats.transport.js +87 -0
- package/dist/esm/transports/redis.transport.d.ts +16 -0
- package/dist/esm/transports/redis.transport.js +68 -0
- package/package.json +27 -7
package/README.md
CHANGED
|
@@ -23,13 +23,30 @@ npm install redis
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
+
## Imports
|
|
27
|
+
|
|
28
|
+
Transports are isolated behind subpath exports so only the dependency you use gets loaded:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Core (always needed)
|
|
32
|
+
import { MessagingModule, MessagingPublisher, Incoming, Outgoing } from '@lokative/messaging';
|
|
33
|
+
|
|
34
|
+
// Pick one transport
|
|
35
|
+
import { NatsTransport } from '@lokative/messaging/nats';
|
|
36
|
+
import { KafkaTransport } from '@lokative/messaging/kafka';
|
|
37
|
+
import { RedisTransport } from '@lokative/messaging/redis';
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
26
42
|
## Quick Start
|
|
27
43
|
|
|
28
44
|
### NATS JetStream
|
|
29
45
|
|
|
30
46
|
```typescript
|
|
31
47
|
import { Module } from '@nestjs/common';
|
|
32
|
-
import { MessagingModule
|
|
48
|
+
import { MessagingModule } from '@lokative/messaging';
|
|
49
|
+
import { NatsTransport } from '@lokative/messaging/nats';
|
|
33
50
|
|
|
34
51
|
@Module({
|
|
35
52
|
imports: [
|
|
@@ -54,7 +71,8 @@ export class AppModule {}
|
|
|
54
71
|
|
|
55
72
|
```typescript
|
|
56
73
|
import { Module } from '@nestjs/common';
|
|
57
|
-
import { MessagingModule
|
|
74
|
+
import { MessagingModule } from '@lokative/messaging';
|
|
75
|
+
import { KafkaTransport } from '@lokative/messaging/kafka';
|
|
58
76
|
|
|
59
77
|
@Module({
|
|
60
78
|
imports: [
|
|
@@ -77,7 +95,8 @@ export class AppModule {}
|
|
|
77
95
|
|
|
78
96
|
```typescript
|
|
79
97
|
import { Module } from '@nestjs/common';
|
|
80
|
-
import { MessagingModule
|
|
98
|
+
import { MessagingModule } from '@lokative/messaging';
|
|
99
|
+
import { RedisTransport } from '@lokative/messaging/redis';
|
|
81
100
|
|
|
82
101
|
@Module({
|
|
83
102
|
imports: [
|
|
@@ -309,7 +328,8 @@ interface SubscribeOptions {
|
|
|
309
328
|
```typescript
|
|
310
329
|
// app.module.ts
|
|
311
330
|
import { Module } from '@nestjs/common';
|
|
312
|
-
import { MessagingModule
|
|
331
|
+
import { MessagingModule } from '@lokative/messaging';
|
|
332
|
+
import { NatsTransport } from '@lokative/messaging/nats';
|
|
313
333
|
import { OrderModule } from './order/order.module';
|
|
314
334
|
|
|
315
335
|
@Module({
|
|
@@ -390,7 +410,7 @@ export class OrderHandler {
|
|
|
390
410
|
To switch this app to Kafka, change only the module registration:
|
|
391
411
|
|
|
392
412
|
```typescript
|
|
393
|
-
import { KafkaTransport } from '@lokative/messaging';
|
|
413
|
+
import { KafkaTransport } from '@lokative/messaging/kafka';
|
|
394
414
|
|
|
395
415
|
MessagingModule.register({
|
|
396
416
|
transport: KafkaTransport,
|
|
@@ -405,7 +425,7 @@ MessagingModule.register({
|
|
|
405
425
|
Or to Redis:
|
|
406
426
|
|
|
407
427
|
```typescript
|
|
408
|
-
import { RedisTransport } from '@lokative/messaging';
|
|
428
|
+
import { RedisTransport } from '@lokative/messaging/redis';
|
|
409
429
|
|
|
410
430
|
MessagingModule.register({
|
|
411
431
|
transport: RedisTransport,
|
|
@@ -421,6 +441,8 @@ No changes needed in services or handlers.
|
|
|
421
441
|
|
|
422
442
|
### Exports
|
|
423
443
|
|
|
444
|
+
From `@lokative/messaging`:
|
|
445
|
+
|
|
424
446
|
| Export | Type | Description |
|
|
425
447
|
| -------------------------- | ----------- | ---------------------------------------------- |
|
|
426
448
|
| `MessagingModule` | Module | NestJS dynamic module |
|
|
@@ -432,15 +454,30 @@ No changes needed in services or handlers.
|
|
|
432
454
|
| `Subscription` | Interface | Async-iterable subscription |
|
|
433
455
|
| `SubscribeOptions` | Interface | Options passed to `subscribe()` |
|
|
434
456
|
| `MESSAGING_TRANSPORT` | Token | DI token for the transport provider |
|
|
435
|
-
| `NatsTransport` | Injectable | Built-in NATS JetStream transport |
|
|
436
|
-
| `NatsTransportOptions` | Interface | Options for `NatsTransport` |
|
|
437
|
-
| `KafkaTransport` | Injectable | Built-in Kafka transport |
|
|
438
|
-
| `KafkaTransportOptions` | Interface | Options for `KafkaTransport` |
|
|
439
|
-
| `RedisTransport` | Injectable | Built-in Redis Pub/Sub transport |
|
|
440
|
-
| `RedisTransportOptions` | Interface | Options for `RedisTransport` |
|
|
441
457
|
| `Incoming` | Decorator | Subscribe a method to a subject |
|
|
442
458
|
| `Outgoing` | Decorator | Auto-publish a method's return value |
|
|
443
459
|
|
|
460
|
+
From `@lokative/messaging/nats`:
|
|
461
|
+
|
|
462
|
+
| Export | Type | Description |
|
|
463
|
+
| --------------------- | ----------- | --------------------------------- |
|
|
464
|
+
| `NatsTransport` | Injectable | Built-in NATS JetStream transport |
|
|
465
|
+
| `NatsTransportOptions`| Interface | Options for `NatsTransport` |
|
|
466
|
+
|
|
467
|
+
From `@lokative/messaging/kafka`:
|
|
468
|
+
|
|
469
|
+
| Export | Type | Description |
|
|
470
|
+
| ---------------------- | ----------- | -------------------------- |
|
|
471
|
+
| `KafkaTransport` | Injectable | Built-in Kafka transport |
|
|
472
|
+
| `KafkaTransportOptions`| Interface | Options for `KafkaTransport` |
|
|
473
|
+
|
|
474
|
+
From `@lokative/messaging/redis`:
|
|
475
|
+
|
|
476
|
+
| Export | Type | Description |
|
|
477
|
+
| ---------------------- | ----------- | -------------------------------- |
|
|
478
|
+
| `RedisTransport` | Injectable | Built-in Redis Pub/Sub transport |
|
|
479
|
+
| `RedisTransportOptions`| Interface | Options for `RedisTransport` |
|
|
480
|
+
|
|
444
481
|
### Injection
|
|
445
482
|
|
|
446
483
|
```typescript
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { MessagingConfig } from './messaging.config';
|
|
2
|
+
export { MessagingTransport, MessageEnvelope, Subscription, SubscribeOptions, MESSAGING_TRANSPORT } from './transport.interface';
|
|
3
|
+
export { Incoming, Outgoing } from './messaging.decorator';
|
|
4
|
+
export { MessagingModule } from './messaging.module';
|
|
5
|
+
export { MessagingPublisher } from './messaging.publisher';
|
|
6
|
+
export { MessagingConsumerRegistry } from './messaging.registry';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessagingConsumerRegistry = exports.MessagingPublisher = exports.MessagingModule = exports.Outgoing = exports.Incoming = exports.MESSAGING_TRANSPORT = void 0;
|
|
4
|
+
var transport_interface_1 = require("./transport.interface");
|
|
5
|
+
Object.defineProperty(exports, "MESSAGING_TRANSPORT", { enumerable: true, get: function () { return transport_interface_1.MESSAGING_TRANSPORT; } });
|
|
6
|
+
var messaging_decorator_1 = require("./messaging.decorator");
|
|
7
|
+
Object.defineProperty(exports, "Incoming", { enumerable: true, get: function () { return messaging_decorator_1.Incoming; } });
|
|
8
|
+
Object.defineProperty(exports, "Outgoing", { enumerable: true, get: function () { return messaging_decorator_1.Outgoing; } });
|
|
9
|
+
var messaging_module_1 = require("./messaging.module");
|
|
10
|
+
Object.defineProperty(exports, "MessagingModule", { enumerable: true, get: function () { return messaging_module_1.MessagingModule; } });
|
|
11
|
+
var messaging_publisher_1 = require("./messaging.publisher");
|
|
12
|
+
Object.defineProperty(exports, "MessagingPublisher", { enumerable: true, get: function () { return messaging_publisher_1.MessagingPublisher; } });
|
|
13
|
+
var messaging_registry_1 = require("./messaging.registry");
|
|
14
|
+
Object.defineProperty(exports, "MessagingConsumerRegistry", { enumerable: true, get: function () { return messaging_registry_1.MessagingConsumerRegistry; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { KafkaTransport, KafkaTransportOptions } from './transports/kafka.transport';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KafkaTransport = void 0;
|
|
4
|
+
var kafka_transport_1 = require("./transports/kafka.transport");
|
|
5
|
+
Object.defineProperty(exports, "KafkaTransport", { enumerable: true, get: function () { return kafka_transport_1.KafkaTransport; } });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Type } from '@nestjs/common';
|
|
2
|
+
import type { MessagingTransport } from './transport.interface';
|
|
3
|
+
export interface MessagingConfig {
|
|
4
|
+
transport: Type<MessagingTransport>;
|
|
5
|
+
transportOptions?: Record<string, any>;
|
|
6
|
+
streams?: {
|
|
7
|
+
name: string;
|
|
8
|
+
subjects: string[];
|
|
9
|
+
}[];
|
|
10
|
+
consumers?: {
|
|
11
|
+
group?: string;
|
|
12
|
+
retry?: number;
|
|
13
|
+
dlq?: boolean;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Incoming = Incoming;
|
|
4
|
+
exports.Outgoing = Outgoing;
|
|
5
|
+
function Incoming(subject) {
|
|
6
|
+
return (target, key) => {
|
|
7
|
+
Reflect.defineMetadata("msg:incoming", { subject }, target[key]);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function Outgoing(subject) {
|
|
11
|
+
return (target, key, descriptor) => {
|
|
12
|
+
const original = descriptor.value;
|
|
13
|
+
descriptor.value = async function (...args) {
|
|
14
|
+
const result = await original.apply(this, args);
|
|
15
|
+
const publisher = this.publisher;
|
|
16
|
+
await publisher.publish(subject, result);
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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 MessagingModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.MessagingModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const core_1 = require("@nestjs/core");
|
|
13
|
+
const transport_interface_1 = require("./transport.interface");
|
|
14
|
+
const messaging_publisher_1 = require("./messaging.publisher");
|
|
15
|
+
const messaging_registry_1 = require("./messaging.registry");
|
|
16
|
+
let MessagingModule = MessagingModule_1 = class MessagingModule {
|
|
17
|
+
static register(config) {
|
|
18
|
+
return {
|
|
19
|
+
module: MessagingModule_1,
|
|
20
|
+
imports: [core_1.DiscoveryModule],
|
|
21
|
+
providers: [
|
|
22
|
+
{ provide: "MSG_CONFIG", useValue: config },
|
|
23
|
+
{ provide: transport_interface_1.MESSAGING_TRANSPORT, useClass: config.transport },
|
|
24
|
+
messaging_publisher_1.MessagingPublisher,
|
|
25
|
+
messaging_registry_1.MessagingConsumerRegistry,
|
|
26
|
+
],
|
|
27
|
+
exports: [messaging_publisher_1.MessagingPublisher],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
exports.MessagingModule = MessagingModule;
|
|
32
|
+
exports.MessagingModule = MessagingModule = MessagingModule_1 = __decorate([
|
|
33
|
+
(0, common_1.Module)({})
|
|
34
|
+
], MessagingModule);
|
|
@@ -0,0 +1,32 @@
|
|
|
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 __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.MessagingPublisher = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const transport_interface_1 = require("./transport.interface");
|
|
18
|
+
let MessagingPublisher = class MessagingPublisher {
|
|
19
|
+
transport;
|
|
20
|
+
constructor(transport) {
|
|
21
|
+
this.transport = transport;
|
|
22
|
+
}
|
|
23
|
+
async publish(subject, payload) {
|
|
24
|
+
await this.transport.publish(subject, payload);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.MessagingPublisher = MessagingPublisher;
|
|
28
|
+
exports.MessagingPublisher = MessagingPublisher = __decorate([
|
|
29
|
+
(0, common_1.Injectable)(),
|
|
30
|
+
__param(0, (0, common_1.Inject)(transport_interface_1.MESSAGING_TRANSPORT)),
|
|
31
|
+
__metadata("design:paramtypes", [Object])
|
|
32
|
+
], MessagingPublisher);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { DiscoveryService } from "@nestjs/core/discovery";
|
|
3
|
+
import { MessagingTransport } from "./transport.interface";
|
|
4
|
+
import type { MessagingConfig } from "./messaging.config";
|
|
5
|
+
export declare class MessagingConsumerRegistry implements OnModuleInit {
|
|
6
|
+
private transport;
|
|
7
|
+
private discovery;
|
|
8
|
+
private config;
|
|
9
|
+
constructor(transport: MessagingTransport, discovery: DiscoveryService, config: MessagingConfig);
|
|
10
|
+
onModuleInit(): Promise<void>;
|
|
11
|
+
private startConsumer;
|
|
12
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
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 __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.MessagingConsumerRegistry = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const discovery_1 = require("@nestjs/core/discovery");
|
|
18
|
+
const transport_interface_1 = require("./transport.interface");
|
|
19
|
+
let MessagingConsumerRegistry = class MessagingConsumerRegistry {
|
|
20
|
+
transport;
|
|
21
|
+
discovery;
|
|
22
|
+
config;
|
|
23
|
+
constructor(transport, discovery, config) {
|
|
24
|
+
this.transport = transport;
|
|
25
|
+
this.discovery = discovery;
|
|
26
|
+
this.config = config;
|
|
27
|
+
}
|
|
28
|
+
async onModuleInit() {
|
|
29
|
+
await this.transport.connect();
|
|
30
|
+
const providers = this.discovery.getProviders();
|
|
31
|
+
for (const provider of providers) {
|
|
32
|
+
const instance = provider.instance;
|
|
33
|
+
if (!instance)
|
|
34
|
+
continue;
|
|
35
|
+
const proto = Object.getPrototypeOf(instance);
|
|
36
|
+
for (const key of Object.getOwnPropertyNames(proto)) {
|
|
37
|
+
const handler = instance[key];
|
|
38
|
+
if (typeof handler !== 'function')
|
|
39
|
+
continue;
|
|
40
|
+
const meta = Reflect.getMetadata("msg:incoming", handler);
|
|
41
|
+
if (!meta)
|
|
42
|
+
continue;
|
|
43
|
+
this.startConsumer(instance, handler, meta);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async startConsumer(instance, handler, meta) {
|
|
48
|
+
const group = this.config.consumers?.group;
|
|
49
|
+
const sub = await this.transport.subscribe(meta.subject, { group });
|
|
50
|
+
for await (const msg of sub) {
|
|
51
|
+
try {
|
|
52
|
+
await handler.call(instance, msg.data);
|
|
53
|
+
msg.ack();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
msg.nak();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
exports.MessagingConsumerRegistry = MessagingConsumerRegistry;
|
|
62
|
+
exports.MessagingConsumerRegistry = MessagingConsumerRegistry = __decorate([
|
|
63
|
+
(0, common_1.Injectable)(),
|
|
64
|
+
__param(0, (0, common_1.Inject)(transport_interface_1.MESSAGING_TRANSPORT)),
|
|
65
|
+
__param(2, (0, common_1.Inject)("MSG_CONFIG")),
|
|
66
|
+
__metadata("design:paramtypes", [Object, discovery_1.DiscoveryService, Object])
|
|
67
|
+
], MessagingConsumerRegistry);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NatsTransport, NatsTransportOptions } from './transports/nats.transport';
|
package/dist/cjs/nats.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NatsTransport = void 0;
|
|
4
|
+
var nats_transport_1 = require("./transports/nats.transport");
|
|
5
|
+
Object.defineProperty(exports, "NatsTransport", { enumerable: true, get: function () { return nats_transport_1.NatsTransport; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RedisTransport, RedisTransportOptions } from './transports/redis.transport';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RedisTransport = void 0;
|
|
4
|
+
var redis_transport_1 = require("./transports/redis.transport");
|
|
5
|
+
Object.defineProperty(exports, "RedisTransport", { enumerable: true, get: function () { return redis_transport_1.RedisTransport; } });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface MessageEnvelope {
|
|
2
|
+
subject: string;
|
|
3
|
+
data: any;
|
|
4
|
+
ack(): void;
|
|
5
|
+
nak(): void;
|
|
6
|
+
}
|
|
7
|
+
export interface Subscription {
|
|
8
|
+
[Symbol.asyncIterator](): AsyncIterator<MessageEnvelope>;
|
|
9
|
+
}
|
|
10
|
+
export interface MessagingTransport {
|
|
11
|
+
connect(): Promise<void>;
|
|
12
|
+
publish(subject: string, payload: any): Promise<void>;
|
|
13
|
+
subscribe(subject: string, options?: SubscribeOptions): Promise<Subscription>;
|
|
14
|
+
}
|
|
15
|
+
export interface SubscribeOptions {
|
|
16
|
+
group?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const MESSAGING_TRANSPORT = "MESSAGING_TRANSPORT";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MessagingTransport, Subscription, SubscribeOptions } from '../transport.interface';
|
|
2
|
+
import type { MessagingConfig } from '../messaging.config';
|
|
3
|
+
export interface KafkaTransportOptions {
|
|
4
|
+
brokers: string[];
|
|
5
|
+
clientId?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class KafkaTransport implements MessagingTransport {
|
|
8
|
+
private config;
|
|
9
|
+
private kafka;
|
|
10
|
+
private producer;
|
|
11
|
+
constructor(config: MessagingConfig);
|
|
12
|
+
connect(): Promise<void>;
|
|
13
|
+
publish(subject: string, payload: any): Promise<void>;
|
|
14
|
+
subscribe(subject: string, options?: SubscribeOptions): Promise<Subscription>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
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 __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.KafkaTransport = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const kafkajs_1 = require("kafkajs");
|
|
18
|
+
let KafkaTransport = class KafkaTransport {
|
|
19
|
+
config;
|
|
20
|
+
kafka;
|
|
21
|
+
producer;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
}
|
|
25
|
+
async connect() {
|
|
26
|
+
const opts = this.config.transportOptions;
|
|
27
|
+
this.kafka = new kafkajs_1.Kafka({
|
|
28
|
+
clientId: opts.clientId ?? 'nestjs-app',
|
|
29
|
+
brokers: opts.brokers,
|
|
30
|
+
});
|
|
31
|
+
this.producer = this.kafka.producer();
|
|
32
|
+
await this.producer.connect();
|
|
33
|
+
}
|
|
34
|
+
async publish(subject, payload) {
|
|
35
|
+
await this.producer.send({
|
|
36
|
+
topic: subject,
|
|
37
|
+
messages: [{ value: JSON.stringify(payload) }],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async subscribe(subject, options) {
|
|
41
|
+
const consumer = this.kafka.consumer({
|
|
42
|
+
groupId: options?.group ?? 'nest-consumer',
|
|
43
|
+
});
|
|
44
|
+
await consumer.connect();
|
|
45
|
+
await consumer.subscribe({ topic: subject, fromBeginning: false });
|
|
46
|
+
const buffer = [];
|
|
47
|
+
let waiting = null;
|
|
48
|
+
await consumer.run({
|
|
49
|
+
eachMessage: async ({ topic, message }) => {
|
|
50
|
+
const envelope = {
|
|
51
|
+
subject: topic,
|
|
52
|
+
data: JSON.parse(message.value?.toString() ?? '{}'),
|
|
53
|
+
ack: () => { }, // kafkajs auto-commits offsets
|
|
54
|
+
nak: () => { },
|
|
55
|
+
};
|
|
56
|
+
if (waiting) {
|
|
57
|
+
const resolve = waiting;
|
|
58
|
+
waiting = null;
|
|
59
|
+
resolve({ done: false, value: envelope });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
buffer.push(envelope);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
const iterator = {
|
|
67
|
+
next() {
|
|
68
|
+
if (buffer.length > 0) {
|
|
69
|
+
return Promise.resolve({ done: false, value: buffer.shift() });
|
|
70
|
+
}
|
|
71
|
+
return new Promise(r => { waiting = r; });
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
return { [Symbol.asyncIterator]: () => iterator };
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
exports.KafkaTransport = KafkaTransport;
|
|
78
|
+
exports.KafkaTransport = KafkaTransport = __decorate([
|
|
79
|
+
(0, common_1.Injectable)(),
|
|
80
|
+
__param(0, (0, common_1.Inject)('MSG_CONFIG')),
|
|
81
|
+
__metadata("design:paramtypes", [Object])
|
|
82
|
+
], KafkaTransport);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MessagingTransport, Subscription, SubscribeOptions } from '../transport.interface';
|
|
2
|
+
import type { MessagingConfig } from '../messaging.config';
|
|
3
|
+
export interface NatsTransportOptions {
|
|
4
|
+
servers: string[];
|
|
5
|
+
streams?: {
|
|
6
|
+
name: string;
|
|
7
|
+
subjects: string[];
|
|
8
|
+
}[];
|
|
9
|
+
}
|
|
10
|
+
export declare class NatsTransport implements MessagingTransport {
|
|
11
|
+
private config;
|
|
12
|
+
private nc;
|
|
13
|
+
private js;
|
|
14
|
+
private jsm;
|
|
15
|
+
constructor(config: MessagingConfig);
|
|
16
|
+
connect(): Promise<void>;
|
|
17
|
+
publish(subject: string, payload: any): Promise<void>;
|
|
18
|
+
subscribe(subject: string, options?: SubscribeOptions): Promise<Subscription>;
|
|
19
|
+
private ensureStreams;
|
|
20
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
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 __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.NatsTransport = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const nats_1 = require("nats");
|
|
18
|
+
let NatsTransport = class NatsTransport {
|
|
19
|
+
config;
|
|
20
|
+
nc;
|
|
21
|
+
js;
|
|
22
|
+
jsm;
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
}
|
|
26
|
+
async connect() {
|
|
27
|
+
const opts = this.config.transportOptions;
|
|
28
|
+
this.nc = await (0, nats_1.connect)({ servers: opts.servers });
|
|
29
|
+
this.js = this.nc.jetstream();
|
|
30
|
+
this.jsm = await this.nc.jetstreamManager();
|
|
31
|
+
await this.ensureStreams(opts.streams ?? this.config.streams ?? []);
|
|
32
|
+
}
|
|
33
|
+
async publish(subject, payload) {
|
|
34
|
+
await this.js.publish(subject, Buffer.from(JSON.stringify(payload)));
|
|
35
|
+
}
|
|
36
|
+
async subscribe(subject, options) {
|
|
37
|
+
const durable = options?.group ?? 'nest-consumer';
|
|
38
|
+
const opts = (0, nats_1.consumerOpts)();
|
|
39
|
+
opts.durable(durable);
|
|
40
|
+
opts.ackExplicit();
|
|
41
|
+
opts.deliverTo(durable);
|
|
42
|
+
const sub = await this.js.subscribe(subject, opts);
|
|
43
|
+
const iterator = {
|
|
44
|
+
async next() {
|
|
45
|
+
const result = await sub[Symbol.asyncIterator]().next();
|
|
46
|
+
if (result.done)
|
|
47
|
+
return { done: true, value: undefined };
|
|
48
|
+
const msg = result.value;
|
|
49
|
+
return {
|
|
50
|
+
done: false,
|
|
51
|
+
value: {
|
|
52
|
+
subject: msg.subject,
|
|
53
|
+
data: JSON.parse(msg.data.toString()),
|
|
54
|
+
ack: () => msg.ack(),
|
|
55
|
+
nak: () => msg.nak(),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
return { [Symbol.asyncIterator]: () => iterator };
|
|
61
|
+
}
|
|
62
|
+
async ensureStreams(streams) {
|
|
63
|
+
for (const stream of streams) {
|
|
64
|
+
try {
|
|
65
|
+
const info = await this.jsm.streams.info(stream.name);
|
|
66
|
+
const existing = info.config.subjects ?? [];
|
|
67
|
+
const missing = stream.subjects.filter(s => !existing.includes(s));
|
|
68
|
+
if (missing.length > 0) {
|
|
69
|
+
info.config.subjects = [...existing, ...missing];
|
|
70
|
+
await this.jsm.streams.update(stream.name, info.config);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
try {
|
|
75
|
+
await this.jsm.streams.add({ name: stream.name, subjects: stream.subjects });
|
|
76
|
+
}
|
|
77
|
+
catch (addErr) {
|
|
78
|
+
if (addErr?.api_error?.err_code !== 10065)
|
|
79
|
+
throw addErr;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
exports.NatsTransport = NatsTransport;
|
|
86
|
+
exports.NatsTransport = NatsTransport = __decorate([
|
|
87
|
+
(0, common_1.Injectable)(),
|
|
88
|
+
__param(0, (0, common_1.Inject)('MSG_CONFIG')),
|
|
89
|
+
__metadata("design:paramtypes", [Object])
|
|
90
|
+
], NatsTransport);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MessagingTransport, Subscription, SubscribeOptions } from '../transport.interface';
|
|
2
|
+
import type { MessagingConfig } from '../messaging.config';
|
|
3
|
+
export interface RedisTransportOptions {
|
|
4
|
+
url?: string;
|
|
5
|
+
host?: string;
|
|
6
|
+
port?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class RedisTransport implements MessagingTransport {
|
|
9
|
+
private config;
|
|
10
|
+
private pub;
|
|
11
|
+
private sub;
|
|
12
|
+
constructor(config: MessagingConfig);
|
|
13
|
+
connect(): Promise<void>;
|
|
14
|
+
publish(subject: string, payload: any): Promise<void>;
|
|
15
|
+
subscribe(subject: string, _options?: SubscribeOptions): Promise<Subscription>;
|
|
16
|
+
}
|