mqtt-plus 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,457 @@
1
+
2
+ <img src="https://raw.githubusercontent.com/rse/mqtt-plus/master/etc/logo.svg" width="400" align="right" alt=""/>
3
+
4
+ MQTT+
5
+ =====
6
+
7
+ [MQTT](http://mqtt.org/) Communication Patterns
8
+
9
+ <p/>
10
+ <img src="https://nodei.co/npm/mqtt-plus.png?downloads=true&stars=true" alt=""/>
11
+
12
+ [![github (author stars)](https://img.shields.io/github/stars/rse?logo=github&label=author%20stars&color=%233377aa)](https://github.com/rse)
13
+ [![github (author followers)](https://img.shields.io/github/followers/rse?label=author%20followers&logo=github&color=%234477aa)](https://github.com/rse)
14
+
15
+ Installation
16
+ ------------
17
+
18
+ ```shell
19
+ $ npm install mqtt mqtt-plus
20
+ ```
21
+
22
+ About
23
+ -----
24
+
25
+ This is **MQTT+**, an addon JavaScript/TypeScript API for the excellent
26
+ [MQTT.js](https://www.npmjs.com/package/mqtt), for additional
27
+ communication patterns like [Remote Procedure
28
+ Call](https://en.wikipedia.org/wiki/Remote_procedure_call) (RPC).
29
+ This allows a bi-directional request/response-style
30
+ communication over the technically uni-directional message protocol
31
+ [MQTT](http://mqtt.org).
32
+
33
+ Conceptually, the **MQTT+** API provides two types of communication patterns:
34
+
35
+ - **Event Emission**:
36
+ Event Emission is a *uni-directional* communication pattern.
37
+ An Event is the combination of an event name and optionally zero or more arguments.
38
+ You *subscribe* to events.
39
+ When an event is *emitted*, either a single particular subscriber (in case of
40
+ a directed event emission) or all subscribers are called and receive the
41
+ arguments as extra information.
42
+ In contrast to the regular MQTT message publish/subscribe, this
43
+ pattern allows to direct the event to particular subscribers and
44
+ provides optional information about the sender to subscribers.
45
+
46
+ - **Service Call**:
47
+ Service Call is a *bi-directional* communication pattern.
48
+ A Service is the combination of a service name and optionally zero or more arguments.
49
+ You *register* for a service.
50
+ When a service is *called*, a single particular registrator (in case
51
+ of a directed service call) or one arbitrary registrator is called and
52
+ receives the arguments as the request. The registrator then has to
53
+ provide the service response.
54
+
55
+ > [!Note]
56
+ > **MQTT+** is similar to and derived from
57
+ > [MQTT-JSON-RPC](https://github.com/rse/mqtt-json-rpc) of the same
58
+ > author, but instead of just JSON, MQTT+ encodes packets as JSON
59
+ > or CBOR (default), uses an own packet format (allowing sender and
60
+ > receiver information) and uses shorter NanoIDs instead of longer UUIDs
61
+ > for identification of sender, receiver and requests.
62
+
63
+ Usage
64
+ -----
65
+
66
+ ### API:
67
+
68
+ ```ts
69
+ export type API = {
70
+ "example/sample": (a1: string, a2: boolean) => void
71
+ "example/hello": (a1: string, a2: number) => string
72
+ }
73
+ ```
74
+
75
+ ### Server:
76
+
77
+ ```ts
78
+ import MQTT from "mqtt"
79
+ import MQTTp from "mqtt-plus"
80
+ import type { API } from [...]
81
+
82
+ const mqtt = MQTT.connect("wss://127.0.0.1:8883", { ... })
83
+ const mqttp = new MQTTp<API>(mqtt)
84
+
85
+ mqtt.on("connect", async () => {
86
+ mqttp.subscribe("example/sample", (a1, a2) => {
87
+ console.log("example/sample: ", a1, a2)
88
+ })
89
+ mqttp.register("example/hello", (a1, a2) => {
90
+ console.log("example/hello: ", a1, a2)
91
+ return `${a1}:${a2}`
92
+ })
93
+ })
94
+ ```
95
+
96
+ ### Client:
97
+
98
+ ```ts
99
+ import MQTT from "mqtt"
100
+ import MQTTp from "mqtt-plus"
101
+ import type { API } from [...]
102
+
103
+ const mqtt = MQTT.connect("wss://127.0.0.1:8883", { ... })
104
+ const mqttp = new MQTTp<API>(mqtt)
105
+
106
+ mqtt.on("connect", () => {
107
+ mqttp.emit("example/sample", "foo", true)
108
+ mqttp.call("example/hello", "world", 42).then((response) => {
109
+ console.log("example/hello response: ", response)
110
+ mqtt.end()
111
+ })
112
+ })
113
+ ```
114
+
115
+ Application Programming Interface
116
+ ---------------------------------
117
+
118
+ The MQTT+ API provides the following methods:
119
+
120
+ - **Construction**:<br/>
121
+
122
+ constructor(
123
+ mqtt: MqttClient,
124
+ options?: {
125
+ id: string
126
+ codec: "cbor" | "json"
127
+ timeout: number
128
+ topicEventNoticeMake: (topic: string) => TopicMatching | null
129
+ topicServiceRequestMake: (topic: string) => TopicMatching | null
130
+ topicServiceResponseMake: (topic: string) => TopicMatching | null
131
+ topicEventNoticeMatch: { name: string, clientId?: string }
132
+ topicServiceRequestMatch: { name: string, clientId?: string }
133
+ topicServiceResponseMatch: { name: string, clientId?: string }
134
+ }
135
+ )
136
+
137
+ The `mqtt` is the [MQTT.js](https://www.npmjs.com/package/mqtt) instance,
138
+ which has to be establish separately.
139
+ The optional `options` object supports the following fields:
140
+ - `id`: Custom MQTT peer identifier (default: auto-generated NanoID).
141
+ - `codec`: Encoding format (default: `cbor`).
142
+ - `timeout`: Communication timeout in milliseconds (default: `10000`).
143
+ - `topicEventNoticeMake`: Custom topic generation for event notices.
144
+ (default: `` (name, clientId) => clientId ? `${name}/event-notice/${clientId}` : `${name}/event-notice` ``)
145
+ - `topicServiceRequestMake`: Custom topic generation for service requests.
146
+ (default: `` (name, clientId) => clientId ? `${name}/service-request/${clientId}` : `${name}/service-request` ``)
147
+ - `topicServiceResponseMake`): Custom topic generation for service responses.
148
+ (default: `` (name, clientId) => clientId ? `${name}/service-response/${clientId}` : `${name}/service-response` ``)
149
+ - `topicEventNoticeMatch`: Custom topic matching for event notices.
150
+ (default: `` (topic) => { const m = topic.match(/^(.+?)\/event-notice(?:\/(.+))?$/); return m ? { name: m[1], clientId: m[2] } : null } ``)
151
+ - `topicServiceRequestMatch`: Custom topic matching for service requests.
152
+ (default: `` (topic) => { const m = topic.match(/^(.+?)\/service-request(?:\/(.+))?$/); return m ? { name: m[1], clientId: m[2] } : null } ``)
153
+ - `topicServiceResponseMatch`: Custom topic matching for service responses.
154
+ (default: `` (topic) => { const m = topic.match(/^(.+?)\/service-response\/(.+)$/); return m ? { name: m[1], clientId: m[2] } : null } ``)
155
+
156
+ - **Event Subscription**:<br/>
157
+
158
+ /* (simplified TypeScript API method signature) */
159
+ subscribe(
160
+ event: string,
161
+ options?: MQTT::IClientSubscribeOptions
162
+ callback: (...params: any[], info?: sender: string, receiver?: string) => void
163
+ ): Promise<Subscription>
164
+
165
+ Subscribe to an event.
166
+ The `event` has to be a valid MQTT topic name.
167
+ The optional `options` allows setting MQTT.js `subscribe()` options like `qos`.
168
+ The `callback` is called with the `params` passed to a remote `emit()`.
169
+ There is no return value of `callback`.
170
+
171
+ Internally, on the MQTT broker, the topics generated by
172
+ `topicEventNoticeMake()` (default: `${event}/event-notice` and
173
+ `${event}/event-notice/${clientId}`) are subscribed. Returns a
174
+ `Subscription` object with an `unsubscribe()` method.
175
+
176
+ - **Service Registration**:<br/>
177
+
178
+ /* (simplified TypeScript API method signature) */
179
+ register(
180
+ service: string,
181
+ options?: MQTT::IClientSubscribeOptions
182
+ callback: (...params: any[], info?: sender: string, receiver?: string) => any
183
+ ): Promise<Registration>
184
+
185
+ Register a service.
186
+ The `service` has to be a valid MQTT topic name.
187
+ The optional `options` allows setting MQTT.js `subscribe()` options like `qos`.
188
+ The `callback` is called with the `params` passed to a remote `call()`.
189
+ The return value of `callback` will resolve the `Promise` returned by the remote `call()`.
190
+
191
+ Internally, on the MQTT broker, the topics by
192
+ `topicServiceRequestMake()` (default: `${service}/service-request` and
193
+ `${service}/service-request/${clientId}`) are subscribed. Returns a
194
+ `Registration` object with an `unregister()` method.
195
+
196
+ - **Event Emission**:<br/>
197
+
198
+ /* (simplified TypeScript API method signature) */
199
+ emit(
200
+ event: string,
201
+ receiver?: Receiver,
202
+ options?: MQTT::IClientSubscribeOptions,
203
+ ...params: any[]
204
+ ): void
205
+
206
+ Emit an event to all subscribers or a specific subscriber ("fire and forget").
207
+ The optional `receiver` directs the event to a specific subscriber only.
208
+ The optional `options` allows setting MQTT.js `publish()` options like `qos` or `retain`.
209
+
210
+ The remote `subscribe()` `callback` is called with `params` and its
211
+ return value is silently ignored.
212
+
213
+ Internally, publishes to the MQTT topic by `topicEventNoticeMake(event, clientId)`
214
+ (default: `${event}/event-notice` or `${event}/event-notice/${clientId}`).
215
+
216
+ - **Service Call**:<br/>
217
+
218
+ /* (simplified TypeScript API method signature) */
219
+ call(
220
+ service: string,
221
+ receiver?: Receiver,
222
+ options?: MQTT::IClientSubscribeOptions,
223
+ ...params: any[]
224
+ ): Promise<any>
225
+
226
+ Call a service on all registrants or on a specific registrant ("request and response").
227
+ The optional `receiver` directs the call to a specific registrant only.
228
+ The optional `options` allows setting MQTT.js `publish()` options like `qos` or `retain`.
229
+
230
+ The remote `register()` `callback` is called with `params` and its
231
+ return value resolves the returned `Promise`. If the remote `callback`
232
+ throws an exception, this rejects the returned `Promise`.
233
+
234
+ Internally, on the MQTT broker, the topic by `topicServiceResponseMake(service, clientId)`
235
+ (default: `${service}/service-response/${clientId}`) is temporarily subscribed
236
+ for receiving the response.
237
+
238
+ - **Receiver Wrapping**:<br/>
239
+
240
+ receiver(
241
+ id: string
242
+ ): Receiver
243
+
244
+ Wrap a receiver ID string for use with `emit()` or `call()` to direct the
245
+ message to a specific receiver. Returns a `Receiver` object.
246
+
247
+ Internals
248
+ ---------
249
+
250
+ In the following, assume that an MQTT+ instance is created with:
251
+
252
+ ```ts
253
+ import MQTT from "mqtt"
254
+ import MQTTp from "mqtt-plus"
255
+
256
+ const mqtt = MQTT.connect("...", { ... })
257
+ const mqttp = new MQTTp(mqtt, { codec: "json" })
258
+ ```
259
+
260
+ Internally, remote services are assigned to MQTT topics. When calling a
261
+ remote service named `example/hello` with parameters `"world"` and `42` via...
262
+
263
+ ```ts
264
+ mqttp.call("example/hello", "world", 42).then((result) => {
265
+ ...
266
+ })
267
+ ```
268
+
269
+ ...the following message is sent to the permanent MQTT topic
270
+ `example/hello/service-request` (the shown NanoIDs are just pseudo
271
+ ones):
272
+
273
+ ```json
274
+ {
275
+ "id": "RRRRRRRRRRRRRRRRRRRRR",
276
+ "sender": "SSSSSSSSSSSSSSSSSSSSS",
277
+ "method": "example/hello",
278
+ "params": [ "world", 42 ]
279
+ }
280
+ ```
281
+
282
+ Beforehand, this `example/hello` service should have been registered with...
283
+
284
+ ```ts
285
+ mqttp.register("example/hello", (a1, a2) => {
286
+ return `${a1}:${a2}`
287
+ })
288
+ ```
289
+
290
+ ...and then its result, in the above `mqttp.call()` example `"world:42"`, is then
291
+ sent back as the following success response
292
+ message to the temporary (client-specific) MQTT topic
293
+ `example/hello/service-response/SSSSSSSSSSSSSSSSSSSSS`:
294
+
295
+ ```json
296
+ {
297
+ "id": "RRRRRRRRRRRRRRRRRRRRR",
298
+ "sender": "SSSSSSSSSSSSSSSSSSSSS",
299
+ "result": "world:42"
300
+ }
301
+ ```
302
+
303
+ The `sender` field is the NanoID of the MQTT+ sender instance and
304
+ `id` is the NanoID of the particular service request. The `sender` is
305
+ used for sending back the response message to the requestor only. The
306
+ `id` is used for correlating the response to the request only.
307
+
308
+ Broker Setup
309
+ ------------
310
+
311
+ For a real test-drive of MQTT+, install the
312
+ [Mosquitto](https://mosquitto.org/) MQTT broker and a `mosquitto.conf`
313
+ file like...
314
+
315
+ ```
316
+ [...]
317
+
318
+ password_file mosquitto-pwd.txt
319
+ acl_file mosquitto-acl.txt
320
+
321
+ [...]
322
+
323
+ # additional listener
324
+ listener 1883 127.0.0.1
325
+ max_connections -1
326
+ protocol mqtt
327
+
328
+ [...]
329
+ ```
330
+
331
+ ...and an access control list in `mosquitto-acl.txt` like...
332
+
333
+ ```
334
+ # shared ACL
335
+ topic read $SYS/#
336
+ pattern write $SYS/broker/connection/%c/state
337
+ pattern readwrite %u/#
338
+
339
+ # anonymous ACL
340
+ topic read event/+
341
+ pattern read event/+/%c
342
+ topic write event/+/+
343
+ pattern read service/+/%c
344
+ topic write service/+
345
+ topic write service/+/+
346
+
347
+ # user ACL
348
+ user example
349
+ topic read event/+
350
+ pattern read event/+/%c
351
+ topic write event/+
352
+ topic write event/+/+
353
+ topic read service/+
354
+ pattern read service/+/%c
355
+ topic write service/+
356
+ topic write service/+/+
357
+ ```
358
+
359
+ ...and an `example` user (with password `example`) in `mosquitto-pwd.txt` like:
360
+
361
+ ```
362
+ example:$6$awYNe6oCAi+xlvo5$mWIUqyy4I0O3nJ99lP1mkRVqsDGymF8en5NChQQxf7KrVJLUp1SzrrVDe94wWWJa3JGIbOXD9wfFGZdi948e6A==
363
+ ```
364
+
365
+ Alternatively, you can use the [NPM package mosquitto](https://npmjs.com/mosquitto)
366
+ for an equal setup.
367
+
368
+ Example
369
+ -------
370
+
371
+ You can test-drive MQTT+ with a complete [sample](sample/sample.ts) to see
372
+ it in action and tracing its communication (the typing of the `MQTTp`
373
+ class with `API` is optional, but strongly suggested):
374
+
375
+ ```ts
376
+ import Mosquitto from "mosquitto"
377
+ import MQTT from "mqtt"
378
+ import MQTTp from "mqtt-plus"
379
+
380
+ const mosquitto = new Mosquitto()
381
+ await mosquitto.start()
382
+ await new Promise((resolve) => { setTimeout(resolve, 500) })
383
+
384
+ const mqtt = MQTT.connect("mqtt://127.0.0.1:1883", {
385
+ username: "example",
386
+ password: "example"
387
+ })
388
+
389
+ type API = {
390
+ "example/sample": (a1: string, a2: number) => void
391
+ "example/hello": (a1: string, a2: number) => string
392
+ }
393
+
394
+ const mqttp = new MQTTp<API>(mqtt, { codec: "json" })
395
+
396
+ type Sample = (a: string, b: number) => string
397
+
398
+ mqtt.on("error", (err) => { console.log("ERROR", err) })
399
+ mqtt.on("offline", () => { console.log("OFFLINE") })
400
+ mqtt.on("close", () => { console.log("CLOSE") })
401
+ mqtt.on("reconnect", () => { console.log("RECONNECT") })
402
+ mqtt.on("message", (topic, message) => { console.log("RECEIVED", topic, message.toString()) })
403
+
404
+ mqtt.on("connect", () => {
405
+ console.log("CONNECT")
406
+ mqttp.register("example/hello", (a1, a2) => {
407
+ console.log("example/hello: request: ", a1, a2)
408
+ return `${a1}:${a2}`
409
+ })
410
+ mqttp.call("example/hello", "world", 42).then((result) => {
411
+ console.log("example/hello success: ", result)
412
+ mqtt.end()
413
+ await mosquitto.stop()
414
+ }).catch((err) => {
415
+ console.log("example/hello error: ", err)
416
+ })
417
+ })
418
+ ```
419
+
420
+ The output will be:
421
+
422
+ ```
423
+ $ node sample.ts
424
+ CONNECT
425
+ example/sample: info: world 42 undefined
426
+ RECEIVED example/sample/event-notice {"id":"GraDZnA4BLrF66g9qmpPX","sender":"2IBMSk0NPnrz1AeTERoea","event":"example/sample","params":["world",42]}
427
+ RECEIVED example/hello/service-request {"id":"vwLzfQDu2uEeOdOfIlT42","sender":"2IBMSk0NPnrz1AeTERoea","service":"example/hello","params":["world",42]}
428
+ example/hello: request: world 42 undefined
429
+ RECEIVED example/hello/service-response/2IBMSk0NPnrz1AeTERoea {"id":"vwLzfQDu2uEeOdOfIlT42","sender":"2IBMSk0NPnrz1AeTERoea","receiver":"2IBMSk0NPnrz1AeTERoea","result":"world:42"}
430
+ example/hello success: world:42
431
+ CLOSE
432
+ ```
433
+
434
+ License
435
+ -------
436
+
437
+ Copyright (c) 2018-2025 Dr. Ralf S. Engelschall (http://engelschall.com/)
438
+
439
+ Permission is hereby granted, free of charge, to any person obtaining
440
+ a copy of this software and associated documentation files (the
441
+ "Software"), to deal in the Software without restriction, including
442
+ without limitation the rights to use, copy, modify, merge, publish,
443
+ distribute, sublicense, and/or sell copies of the Software, and to
444
+ permit persons to whom the Software is furnished to do so, subject to
445
+ the following conditions:
446
+
447
+ The above copyright notice and this permission notice shall be included
448
+ in all copies or substantial portions of the Software.
449
+
450
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
451
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
452
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
453
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
454
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
455
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
456
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
457
+
@@ -0,0 +1,6 @@
1
+ export default class Codec {
2
+ private type;
3
+ constructor(type: "cbor" | "json");
4
+ encode(data: unknown): Buffer | string;
5
+ decode(data: Buffer | string): unknown;
6
+ }
@@ -0,0 +1,74 @@
1
+ /*
2
+ ** MQTT+ -- MQTT Communication Patterns
3
+ ** Copyright (c) 2018-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ **
5
+ ** Permission is hereby granted, free of charge, to any person obtaining
6
+ ** a copy of this software and associated documentation files (the
7
+ ** "Software"), to deal in the Software without restriction, including
8
+ ** without limitation the rights to use, copy, modify, merge, publish,
9
+ ** distribute, sublicense, and/or sell copies of the Software, and to
10
+ ** permit persons to whom the Software is furnished to do so, subject to
11
+ ** the following conditions:
12
+ **
13
+ ** The above copyright notice and this permission notice shall be included
14
+ ** in all copies or substantial portions of the Software.
15
+ **
16
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ import CBOR from "cbor";
25
+ /* the encoder/decoder abstraction */
26
+ export default class Codec {
27
+ constructor(type) {
28
+ this.type = type;
29
+ }
30
+ encode(data) {
31
+ let result;
32
+ if (this.type === "cbor") {
33
+ try {
34
+ result = CBOR.encode(data);
35
+ }
36
+ catch (_ex) {
37
+ throw new Error("failed to encode CBOR format");
38
+ }
39
+ }
40
+ else if (this.type === "json") {
41
+ try {
42
+ result = JSON.stringify(data);
43
+ }
44
+ catch (_ex) {
45
+ throw new Error("failed to encode JSON format");
46
+ }
47
+ }
48
+ else
49
+ throw new Error("invalid format");
50
+ return result;
51
+ }
52
+ decode(data) {
53
+ let result;
54
+ if (this.type === "cbor" && typeof data === "object" && data instanceof Buffer) {
55
+ try {
56
+ result = CBOR.decode(data);
57
+ }
58
+ catch (_ex) {
59
+ throw new Error("failed to decode CBOR format");
60
+ }
61
+ }
62
+ else if (this.type === "json" && typeof data === "string") {
63
+ try {
64
+ result = JSON.parse(data);
65
+ }
66
+ catch (_ex) {
67
+ throw new Error("failed to decode JSON format");
68
+ }
69
+ }
70
+ else
71
+ throw new Error("invalid format or wrong data type");
72
+ return result;
73
+ }
74
+ }
@@ -0,0 +1,31 @@
1
+ export declare class Base {
2
+ id: string;
3
+ sender?: string | undefined;
4
+ receiver?: string | undefined;
5
+ constructor(id: string, sender?: string | undefined, receiver?: string | undefined);
6
+ }
7
+ export declare class EventEmission extends Base {
8
+ event: string;
9
+ params?: any[] | undefined;
10
+ constructor(id: string, event: string, params?: any[] | undefined, sender?: string, receiver?: string);
11
+ }
12
+ export declare class ServiceRequest extends Base {
13
+ service: string;
14
+ params?: any[] | undefined;
15
+ constructor(id: string, service: string, params?: any[] | undefined, sender?: string, receiver?: string);
16
+ }
17
+ export declare class ServiceResponseSuccess extends Base {
18
+ result: any;
19
+ constructor(id: string, result: any, sender?: string, receiver?: string);
20
+ }
21
+ export declare class ServiceResponseError extends Base {
22
+ error: string;
23
+ constructor(id: string, error: string, sender?: string, receiver?: string);
24
+ }
25
+ export default class Msg {
26
+ makeEventEmission(id: string, event: string, params?: any[], sender?: string, receiver?: string): EventEmission;
27
+ makeServiceRequest(id: string, service: string, params?: any[], sender?: string, receiver?: string): ServiceRequest;
28
+ makeServiceResponseSuccess(id: string, result: any, sender?: string, receiver?: string): ServiceResponseSuccess;
29
+ makeServiceResponseError(id: string, error: string, sender?: string, receiver?: string): ServiceResponseError;
30
+ parse(obj: any): EventEmission | ServiceRequest | ServiceResponseSuccess | ServiceResponseError;
31
+ }