@fetaoily/nest-mqtt 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 microud
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,191 @@
1
+ # Nest-MQTT
2
+
3
+ ## Description
4
+
5
+ A MQTT module for Nest.js. Compatible with emqtt.
6
+
7
+ ## Installation
8
+
9
+ > ⚠️ After version 0.2.0, `nest-mqtt` make a breaking change. User should add additional `mqtt` package manual.
10
+
11
+ ```bash
12
+ $ npm install nest-mqtt mqtt --save
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Import
18
+
19
+ Nest-mqtt will register as a global module.
20
+
21
+ You can import with configuration
22
+
23
+ ```typescript
24
+ // app.module.ts
25
+ import { Module } from '@nestjs/common';
26
+ import { MqttModule } from 'nest-mqtt';
27
+
28
+ @Module({
29
+ imports: [MqttModule.forRoot(options)]
30
+ })
31
+ export class AppModule {}
32
+ ```
33
+
34
+ or use async import method
35
+
36
+ ```typescript
37
+ // app.module.ts
38
+ import { Module } from '@nestjs/common';
39
+ import { MqttModule } from 'nest-mqtt';
40
+
41
+ @Module({
42
+ imports: [MqttModule.forRootAsync({
43
+ useFactory: () => options,
44
+ })]
45
+ })
46
+ export class AppModule {}
47
+ ```
48
+
49
+
50
+ ### Subscribe
51
+
52
+ You can define any subscriber or consumer in any provider. For example,
53
+
54
+ ```typescript
55
+ import { Injectable } from '@nestjs/common';
56
+ import { Subscribe, Payload, Topic } from 'nest-mqtt';
57
+
58
+ @Injectable()
59
+ export class TestService {
60
+ @Subscribe('test')
61
+ test() {
62
+
63
+ }
64
+
65
+ @Subscribe({
66
+ topic: 'test2',
67
+ transform: payload => payload.toString(),
68
+ })
69
+ test2() {
70
+
71
+ }
72
+ }
73
+ ```
74
+
75
+ Also, you can inject parameter with decorator:
76
+
77
+ ```typescript
78
+ import { Injectable } from '@nestjs/common';
79
+ import { Subscribe, Payload } from 'nest-mqtt';
80
+
81
+ @Injectable()
82
+ export class TestService {
83
+ @Subscribe('test')
84
+ test(@Payload() payload) {
85
+ console.log(payload);
86
+ }
87
+ }
88
+ ```
89
+
90
+ Here are all supported parameter decorators:
91
+
92
+ #### Payload(transform?: (payload) => any)
93
+
94
+ Get the payload data of incoming message. You can pass in a transform function for converting.
95
+
96
+ #### Topic()
97
+
98
+ Get the topic of incoming message.
99
+
100
+ #### Packet()
101
+
102
+ Get the raw packet of incoming message.
103
+
104
+ #### Params()
105
+
106
+ Get the wildcard part of topic. It will return an array of string which extract from topic. For example:
107
+
108
+ When subscribe the topic "test/+/test/+" and incoming topic is "test/1/test/2", you will get the array `["1", "2"]`.
109
+
110
+ ### Publish
111
+
112
+ Nest-mqtt wrap some functions with `Promise` and provide a provider.
113
+
114
+ ```typescript
115
+ import { Inject, Injectable } from '@nestjs/common';
116
+ import { MqttService } from 'nest-mqtt';
117
+
118
+ @Injectable()
119
+ export class TestService {
120
+ constructor(
121
+ @Inject(MqttService) private readonly mqttService: MqttService,
122
+ ) {}
123
+
124
+ async testPublish() {
125
+ this.mqttService.publish('topic', {
126
+ foo: 'bar'
127
+ });
128
+ }
129
+
130
+ }
131
+ ```
132
+
133
+ ## Emqtt Compatible
134
+
135
+ nest-mqtt support emq shared subscription
136
+
137
+ - Global mode
138
+
139
+ Module options support queue and share property for globally converting all topic to shared topic except configured in subscription options.
140
+
141
+ ```typescript
142
+ // app.module.ts
143
+ import { Module } from '@nestjs/common';
144
+ import { MqttModule } from 'nest-mqtt';
145
+
146
+ @Module({
147
+ imports: [MqttModule.forRoot({
148
+ host: '127.0.0.1',
149
+ queue: true,
150
+ share: 'group1'
151
+ })]
152
+ })
153
+ export class AppModule {}
154
+ ```
155
+
156
+ - Configure in Subscribe
157
+
158
+ ```typescript
159
+ import { Injectable } from '@nestjs/common';
160
+ import { Subscribe, Payload, Topic } from 'nest-mqtt';
161
+
162
+ @Injectable()
163
+ export class TestService {
164
+ @Subscribe('test')
165
+ test() {
166
+
167
+ }
168
+
169
+ @Subscribe({
170
+ topic: 'test2',
171
+ queue: true,
172
+ })
173
+ test2() {
174
+
175
+ }
176
+ }
177
+ ```
178
+
179
+ The priority of subscribe is higher than the global mode. If you want to specify a topic do not use the shared mode, set it as false in subscribe decorator.
180
+
181
+ ## Support
182
+
183
+ Nest-mqtt is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
184
+
185
+ ## Stay in touch
186
+
187
+ - Author - [microud](https://xknow.net)
188
+
189
+ ## License
190
+
191
+ nest-mqtt is [MIT licensed](LICENSE).
@@ -0,0 +1,2 @@
1
+ import { Provider } from '@nestjs/common';
2
+ export declare function createClientProvider(): Provider;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createClientProvider = void 0;
4
+ const mqtt_1 = require("mqtt");
5
+ const mqtt_constants_1 = require("./mqtt.constants");
6
+ function createClientProvider() {
7
+ return {
8
+ provide: mqtt_constants_1.MQTT_CLIENT_INSTANCE,
9
+ useFactory: (options, logger) => {
10
+ const client = (0, mqtt_1.connect)(options);
11
+ client.on('connect', () => {
12
+ logger.log('MQTT connected');
13
+ });
14
+ client.on('disconnect', packet => {
15
+ logger.log('MQTT disconnected');
16
+ });
17
+ client.on('error', error => {
18
+ this.logger.log(`MQTT error: ${error.message}`);
19
+ });
20
+ client.on('reconnect', () => {
21
+ logger.log('MQTT reconnecting');
22
+ });
23
+ client.on('close', () => {
24
+ logger.log(`MQTT closed`);
25
+ });
26
+ client.on('offline', () => {
27
+ logger.log('MQTT offline');
28
+ });
29
+ return client;
30
+ },
31
+ inject: [mqtt_constants_1.MQTT_OPTION_PROVIDER, mqtt_constants_1.MQTT_LOGGER_PROVIDER],
32
+ };
33
+ }
34
+ exports.createClientProvider = createClientProvider;
35
+ //# sourceMappingURL=client.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.provider.js","sourceRoot":"","sources":["../src/client.provider.ts"],"names":[],"mappings":";;;AACA,+BAA+B;AAE/B,qDAAoG;AAEpG,SAAgB,oBAAoB;IAClC,OAAO;QACL,OAAO,EAAE,qCAAoB;QAC7B,UAAU,EAAE,CAAC,OAA0B,EAAE,MAAc,EAAE,EAAE;YACzD,MAAM,MAAM,GAAG,IAAA,cAAO,EAAC,OAAO,CAAC,CAAC;YAEhC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACxB,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE;gBAC/B,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;gBACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAClD,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;gBAC1B,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACtB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACxB,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,EAAE,CAAC,qCAAoB,EAAE,qCAAoB,CAAC;KACrD,CAAC;AACJ,CAAC;AAlCD,oDAkCC"}
@@ -0,0 +1,5 @@
1
+ export * from './mqtt.interface';
2
+ export * from './mqtt.decorator';
3
+ export * from './mqtt.constants';
4
+ export * from './mqtt.module';
5
+ export * from './mqtt.service';
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
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("./mqtt.interface"), exports);
18
+ __exportStar(require("./mqtt.decorator"), exports);
19
+ __exportStar(require("./mqtt.constants"), exports);
20
+ __exportStar(require("./mqtt.module"), exports);
21
+ __exportStar(require("./mqtt.service"), exports);
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,mDAAiC;AACjC,mDAAiC;AACjC,gDAA8B;AAC9B,iDAA+B"}
@@ -0,0 +1,5 @@
1
+ export declare const MQTT_SUBSCRIBE_OPTIONS = "__mqtt_subscribe_options";
2
+ export declare const MQTT_SUBSCRIBER_PARAMS = "__mqtt_subscriber_params";
3
+ export declare const MQTT_CLIENT_INSTANCE = "MQTT_CLIENT_INSTANCE";
4
+ export declare const MQTT_OPTION_PROVIDER = "MQTT_OPTION_PROVIDER";
5
+ export declare const MQTT_LOGGER_PROVIDER = "MQTT_LOGGER_PROVIDER";
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MQTT_LOGGER_PROVIDER = exports.MQTT_OPTION_PROVIDER = exports.MQTT_CLIENT_INSTANCE = exports.MQTT_SUBSCRIBER_PARAMS = exports.MQTT_SUBSCRIBE_OPTIONS = void 0;
4
+ exports.MQTT_SUBSCRIBE_OPTIONS = '__mqtt_subscribe_options';
5
+ exports.MQTT_SUBSCRIBER_PARAMS = '__mqtt_subscriber_params';
6
+ exports.MQTT_CLIENT_INSTANCE = 'MQTT_CLIENT_INSTANCE';
7
+ exports.MQTT_OPTION_PROVIDER = 'MQTT_OPTION_PROVIDER';
8
+ exports.MQTT_LOGGER_PROVIDER = 'MQTT_LOGGER_PROVIDER';
9
+ //# sourceMappingURL=mqtt.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mqtt.constants.js","sourceRoot":"","sources":["../src/mqtt.constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,sBAAsB,GAAG,0BAA0B,CAAC;AACpD,QAAA,sBAAsB,GAAG,0BAA0B,CAAC;AACpD,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAC9C,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAC9C,QAAA,oBAAoB,GAAG,sBAAsB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { CustomDecorator } from '@nestjs/common';
2
+ import { MqttMessageTransformer, MqttSubscribeOptions } from './mqtt.interface';
3
+ export declare function Subscribe(topic: string | string[] | MqttSubscribeOptions): CustomDecorator;
4
+ export declare function Topic(): (target: object, propertyKey: string | symbol, paramIndex: number) => void;
5
+ export declare function Packet(): (target: object, propertyKey: string | symbol, paramIndex: number) => void;
6
+ export declare function Payload(transform?: 'json' | 'text' | MqttMessageTransformer): (target: object, propertyKey: string | symbol, paramIndex: number) => void;
7
+ export declare function Params(): (target: object, propertyKey: string | symbol, paramIndex: number) => void;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Params = exports.Payload = exports.Packet = exports.Topic = exports.Subscribe = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const mqtt_constants_1 = require("./mqtt.constants");
6
+ function Subscribe(topicOrOptions) {
7
+ if (typeof topicOrOptions === 'string' || Array.isArray(topicOrOptions)) {
8
+ return (0, common_1.SetMetadata)(mqtt_constants_1.MQTT_SUBSCRIBE_OPTIONS, {
9
+ topic: topicOrOptions,
10
+ });
11
+ }
12
+ else {
13
+ return (0, common_1.SetMetadata)(mqtt_constants_1.MQTT_SUBSCRIBE_OPTIONS, topicOrOptions);
14
+ }
15
+ }
16
+ exports.Subscribe = Subscribe;
17
+ function SetParameter(parameter) {
18
+ return (target, propertyKey, paramIndex) => {
19
+ const params = Reflect.getMetadata(mqtt_constants_1.MQTT_SUBSCRIBER_PARAMS, target[propertyKey]) || [];
20
+ params.push(Object.assign({ index: paramIndex }, parameter));
21
+ Reflect.defineMetadata(mqtt_constants_1.MQTT_SUBSCRIBER_PARAMS, params, target[propertyKey]);
22
+ };
23
+ }
24
+ function Topic() {
25
+ return SetParameter({
26
+ type: 'topic',
27
+ });
28
+ }
29
+ exports.Topic = Topic;
30
+ function Packet() {
31
+ return SetParameter({
32
+ type: 'packet',
33
+ });
34
+ }
35
+ exports.Packet = Packet;
36
+ function Payload(transform) {
37
+ return SetParameter({
38
+ type: 'payload',
39
+ transform,
40
+ });
41
+ }
42
+ exports.Payload = Payload;
43
+ function Params() {
44
+ return SetParameter({
45
+ type: 'params',
46
+ });
47
+ }
48
+ exports.Params = Params;
49
+ //# sourceMappingURL=mqtt.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mqtt.decorator.js","sourceRoot":"","sources":["../src/mqtt.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAA8D;AAC9D,qDAAkF;AAIlF,SAAgB,SAAS,CAAC,cAAc;IACtC,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE;QACvE,OAAO,IAAA,oBAAW,EAAC,uCAAsB,EAAE;YACzC,KAAK,EAAE,cAAc;SACtB,CAAC,CAAC;KACJ;SAAM;QACL,OAAO,IAAA,oBAAW,EAAC,uCAAsB,EAAE,cAAc,CAAC,CAAC;KAC5D;AACH,CAAC;AARD,8BAQC;AAED,SAAS,YAAY,CAAC,SAA2C;IAC/D,OAAO,CAAC,MAAc,EAAE,WAA4B,EAAE,UAAkB,EAAE,EAAE;QAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,uCAAsB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;QACtF,MAAM,CAAC,IAAI,iBACT,KAAK,EAAE,UAAU,IACd,SAAS,EACZ,CAAC;QACH,OAAO,CAAC,cAAc,CAAC,uCAAsB,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC;AACJ,CAAC;AAMD,SAAgB,KAAK;IACnB,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;AACL,CAAC;AAJD,sBAIC;AAMD,SAAgB,MAAM;IACpB,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;AACL,CAAC;AAJD,wBAIC;AAOD,SAAgB,OAAO,CAAC,SAAoD;IAC1E,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,SAAS;QACf,SAAS;KACV,CAAC,CAAC;AACL,CAAC;AALD,0BAKC;AAOD,SAAgB,MAAM;IACpB,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;AACL,CAAC;AAJD,wBAIC"}
@@ -0,0 +1,21 @@
1
+ import { Logger, OnModuleInit } from '@nestjs/common';
2
+ import { DiscoveryService, MetadataScanner } from '@nestjs/core';
3
+ import { MqttClient } from 'mqtt';
4
+ import { MqttModuleOptions, MqttSubscribeOptions, MqttSubscriber, MqttSubscriberParameter } from './mqtt.interface';
5
+ export declare class MqttExplorer implements OnModuleInit {
6
+ private readonly discoveryService;
7
+ private readonly metadataScanner;
8
+ private readonly logger;
9
+ private readonly client;
10
+ private readonly options;
11
+ private readonly reflector;
12
+ subscribers: MqttSubscriber[];
13
+ constructor(discoveryService: DiscoveryService, metadataScanner: MetadataScanner, logger: Logger, client: MqttClient, options: MqttModuleOptions);
14
+ onModuleInit(): void;
15
+ preprocess(options: MqttSubscribeOptions): string | string[];
16
+ subscribe(options: MqttSubscribeOptions, parameters: MqttSubscriberParameter[], handle: any, provider: any): void;
17
+ explore(): void;
18
+ private getSubscriber;
19
+ private static topicToRegexp;
20
+ private static matchGroups;
21
+ }
@@ -0,0 +1,176 @@
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
+ var MqttExplorer_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.MqttExplorer = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const core_1 = require("@nestjs/core");
19
+ const mqtt_constants_1 = require("./mqtt.constants");
20
+ const mqtt_1 = require("mqtt");
21
+ const mqtt_transform_1 = require("./mqtt.transform");
22
+ let MqttExplorer = MqttExplorer_1 = class MqttExplorer {
23
+ constructor(discoveryService, metadataScanner, logger, client, options) {
24
+ this.discoveryService = discoveryService;
25
+ this.metadataScanner = metadataScanner;
26
+ this.logger = logger;
27
+ this.client = client;
28
+ this.options = options;
29
+ this.reflector = new core_1.Reflector();
30
+ this.subscribers = [];
31
+ }
32
+ onModuleInit() {
33
+ this.logger.log('MqttModule dependencies initialized');
34
+ this.explore();
35
+ }
36
+ preprocess(options) {
37
+ const processTopic = (topic) => {
38
+ const queue = typeof options.queue === 'boolean' ? options.queue : this.options.queue;
39
+ const share = typeof options.share === 'string' ? options.share : this.options.share;
40
+ topic = topic.replace('$queue/', '')
41
+ .replace(/^\$share\/([A-Za-z0-9]+)\//, '');
42
+ if (queue) {
43
+ return `$queue/${topic}`;
44
+ }
45
+ if (share) {
46
+ return `$share/${share}/${topic}`;
47
+ }
48
+ return topic;
49
+ };
50
+ if (Array.isArray(options.topic)) {
51
+ return options.topic.map(processTopic);
52
+ }
53
+ else {
54
+ return processTopic(options.topic);
55
+ }
56
+ }
57
+ subscribe(options, parameters, handle, provider) {
58
+ const rawOpts = options.rawOpts;
59
+ this.client.subscribe(this.preprocess(options), rawOpts, err => {
60
+ if (!err) {
61
+ (Array.isArray(options.topic) ? options.topic : [options.topic])
62
+ .forEach(topic => {
63
+ this.subscribers.push({
64
+ topic,
65
+ route: topic.replace('$queue/', '').replace(/^\$share\/([A-Za-z0-9]+)\//, ''),
66
+ regexp: MqttExplorer_1.topicToRegexp(topic),
67
+ provider,
68
+ handle,
69
+ options,
70
+ parameters,
71
+ });
72
+ });
73
+ }
74
+ else {
75
+ this.logger.error(`subscribe topic [${options.topic} failed]`);
76
+ }
77
+ });
78
+ }
79
+ explore() {
80
+ const providers = this.discoveryService.getProviders();
81
+ providers.forEach((wrapper) => {
82
+ const { instance } = wrapper;
83
+ if (!instance) {
84
+ return;
85
+ }
86
+ this.metadataScanner.scanFromPrototype(instance, Object.getPrototypeOf(instance), key => {
87
+ const subscribeOptions = this.reflector.get(mqtt_constants_1.MQTT_SUBSCRIBE_OPTIONS, instance[key]);
88
+ const parameters = this.reflector.get(mqtt_constants_1.MQTT_SUBSCRIBER_PARAMS, instance[key]);
89
+ if (subscribeOptions) {
90
+ this.subscribe(subscribeOptions, parameters, instance[key], instance);
91
+ }
92
+ });
93
+ });
94
+ this.client.on('message', (topic, payload, packet) => {
95
+ const subscriber = this.getSubscriber(topic);
96
+ if (subscriber) {
97
+ const parameters = subscriber.parameters || [];
98
+ const scatterParameters = [];
99
+ for (const parameter of parameters) {
100
+ scatterParameters[parameter.index] = parameter;
101
+ }
102
+ try {
103
+ const transform = (0, mqtt_transform_1.getTransform)(subscriber.options.transform);
104
+ if (this.options.beforeHandle) {
105
+ this.options.beforeHandle(topic, payload, packet);
106
+ }
107
+ subscriber.handle.bind(subscriber.provider)(...scatterParameters.map(parameter => {
108
+ switch (parameter === null || parameter === void 0 ? void 0 : parameter.type) {
109
+ case 'payload':
110
+ return transform(payload);
111
+ case 'topic':
112
+ return topic;
113
+ case 'packet':
114
+ return packet;
115
+ case 'params':
116
+ return MqttExplorer_1.matchGroups(topic, subscriber.regexp);
117
+ default:
118
+ return null;
119
+ }
120
+ }));
121
+ }
122
+ catch (err) {
123
+ this.logger.error(err);
124
+ }
125
+ }
126
+ });
127
+ }
128
+ getSubscriber(topic) {
129
+ for (const subscriber of this.subscribers) {
130
+ subscriber.regexp.lastIndex = 0;
131
+ if (subscriber.regexp.test(topic)) {
132
+ return subscriber;
133
+ }
134
+ }
135
+ return null;
136
+ }
137
+ static topicToRegexp(topic) {
138
+ return new RegExp('^' +
139
+ topic
140
+ .replace('$queue/', '')
141
+ .replace(/^\$share\/([A-Za-z0-9]+)\//, '')
142
+ .replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g, '\\$1')
143
+ .replace(/\+/g, '([^/]+)')
144
+ .replace(/\/#$/, '(/.*)?') +
145
+ '$', 'y');
146
+ }
147
+ static matchGroups(str, regex) {
148
+ regex.lastIndex = 0;
149
+ let m = regex.exec(str);
150
+ const matches = [];
151
+ while (m !== null) {
152
+ if (m.index === regex.lastIndex) {
153
+ regex.lastIndex++;
154
+ }
155
+ m.forEach((match, groupIndex) => {
156
+ if (groupIndex !== 0) {
157
+ matches.push(match);
158
+ }
159
+ });
160
+ m = regex.exec(str);
161
+ }
162
+ return matches;
163
+ }
164
+ };
165
+ exports.MqttExplorer = MqttExplorer;
166
+ exports.MqttExplorer = MqttExplorer = MqttExplorer_1 = __decorate([
167
+ (0, common_1.Injectable)(),
168
+ __param(2, (0, common_1.Inject)(mqtt_constants_1.MQTT_LOGGER_PROVIDER)),
169
+ __param(3, (0, common_1.Inject)(mqtt_constants_1.MQTT_CLIENT_INSTANCE)),
170
+ __param(4, (0, common_1.Inject)(mqtt_constants_1.MQTT_OPTION_PROVIDER)),
171
+ __metadata("design:paramtypes", [core_1.DiscoveryService,
172
+ core_1.MetadataScanner,
173
+ common_1.Logger,
174
+ mqtt_1.MqttClient, Object])
175
+ ], MqttExplorer);
176
+ //# sourceMappingURL=mqtt.explorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mqtt.explorer.js","sourceRoot":"","sources":["../src/mqtt.explorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /// <reference types="node" />
2
+ import { IClientOptions, Packet } from 'mqtt';
3
+ import { LoggerService, Type } from '@nestjs/common';
4
+ import { ModuleMetadata } from '@nestjs/common/interfaces';
5
+ import { IClientSubscribeOptions, IClientSubscribeProperties } from 'mqtt/src/lib/client';
6
+ export type MqttMessageTransformer = (payload: Buffer) => any;
7
+ export type LoggerConstructor = new (...params: any[]) => LoggerService;
8
+ export interface MqttSubscribeOptions {
9
+ topic: string | string[];
10
+ queue?: boolean;
11
+ share?: string;
12
+ rawOpts?: IClientSubscribeOptions | IClientSubscribeProperties;
13
+ transform?: 'json' | 'text' | MqttMessageTransformer;
14
+ }
15
+ export interface MqttSubscriberParameter {
16
+ index: number;
17
+ type: 'payload' | 'topic' | 'packet' | 'params';
18
+ transform?: 'json' | 'text' | MqttMessageTransformer;
19
+ }
20
+ export interface MqttSubscriber {
21
+ topic: string;
22
+ handle: any;
23
+ route: string;
24
+ provider: any;
25
+ regexp: RegExp;
26
+ options: MqttSubscribeOptions;
27
+ parameters: MqttSubscriberParameter[];
28
+ }
29
+ export interface MqttLoggerOptions {
30
+ useValue?: LoggerService;
31
+ useClass?: Type<LoggerService>;
32
+ }
33
+ export interface MqttModuleOptions extends IClientOptions {
34
+ queue?: boolean;
35
+ share?: string;
36
+ logger?: MqttLoggerOptions;
37
+ beforeHandle?: (topic: string, payload: Buffer, packet: Packet) => any;
38
+ }
39
+ export interface MqttOptionsFactory {
40
+ createMqttConnectOptions(): Promise<MqttModuleOptions> | MqttModuleOptions;
41
+ }
42
+ export interface MqttModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
43
+ inject?: any[];
44
+ useExisting?: Type<MqttOptionsFactory>;
45
+ useClass?: Type<MqttOptionsFactory>;
46
+ useFactory?: (...args: any[]) => Promise<MqttModuleOptions> | MqttModuleOptions;
47
+ logger?: MqttLoggerOptions;
48
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=mqtt.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mqtt.interface.js","sourceRoot":"","sources":["../src/mqtt.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { MqttModuleAsyncOptions, MqttModuleOptions } from './mqtt.interface';
3
+ export declare class MqttModule {
4
+ static forRootAsync(options: MqttModuleAsyncOptions): DynamicModule;
5
+ static forRoot(options: MqttModuleOptions): DynamicModule;
6
+ }