mqtt-plus 0.9.6 → 0.9.7
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 +83 -93
- package/doc/mqtt-plus-3-resource-transfer.d2 +32 -0
- package/dst-stage1/mqtt-plus-api.d.ts +1 -6
- package/dst-stage1/mqtt-plus-base.js +1 -1
- package/dst-stage1/mqtt-plus-info.d.ts +4 -5
- package/dst-stage1/mqtt-plus-msg.d.ts +8 -13
- package/dst-stage1/mqtt-plus-msg.js +11 -30
- package/dst-stage1/mqtt-plus-resource.d.ts +29 -5
- package/dst-stage1/mqtt-plus-resource.js +241 -67
- package/dst-stage1/mqtt-plus-service.d.ts +2 -2
- package/dst-stage1/mqtt-plus-service.js +2 -2
- package/dst-stage1/mqtt-plus-stream.d.ts +4 -0
- package/dst-stage1/mqtt-plus-stream.js +54 -15
- package/dst-stage1/mqtt-plus-util.d.ts +2 -0
- package/dst-stage1/mqtt-plus-util.js +34 -0
- package/dst-stage1/mqtt-plus.d.ts +1 -0
- package/dst-stage1/mqtt-plus.js +1 -0
- package/dst-stage2/mqtt-plus.cjs.js +254 -190
- package/dst-stage2/mqtt-plus.esm.js +255 -191
- package/dst-stage2/mqtt-plus.umd.js +13 -13
- package/etc/tsc.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/mqtt-plus-api.ts +0 -8
- package/src/mqtt-plus-base.ts +1 -3
- package/src/mqtt-plus-codec.ts +1 -1
- package/src/mqtt-plus-info.ts +8 -6
- package/src/mqtt-plus-msg.ts +17 -46
- package/src/mqtt-plus-resource.ts +325 -81
- package/src/mqtt-plus-service.ts +2 -2
- package/src/mqtt-plus.ts +1 -0
- package/tst/mqtt-plus.spec.ts +70 -62
- package/doc/mqtt-plus-2-stream-transfer.d2 +0 -22
- package/doc/mqtt-plus-2-stream-transfer.svg +0 -108
- package/doc/mqtt-plus-4-resource-transfer.d2 +0 -23
- package/src/mqtt-plus-stream.ts +0 -222
- /package/doc/{mqtt-plus-3-service-call.d2 → mqtt-plus-2-service-call.d2} +0 -0
- /package/doc/{mqtt-plus-3-service-call.svg → mqtt-plus-2-service-call.svg} +0 -0
- /package/doc/{mqtt-plus-4-resource-transfer.svg → mqtt-plus-3-resource-transfer.svg} +0 -0
package/README.md
CHANGED
|
@@ -42,22 +42,6 @@ communication patterns with type safety:
|
|
|
42
42
|
|
|
43
43
|

|
|
44
44
|
|
|
45
|
-
- **Stream Transfer**:
|
|
46
|
-
|
|
47
|
-
Stream Transfer is a *uni-directional* communication pattern.
|
|
48
|
-
A stream is the combination of a stream name, a `Readable` stream object and optionally zero or more arguments.
|
|
49
|
-
You *attach* to a stream.
|
|
50
|
-
When a stream is *transferred*, either a single particular attacher (in case of
|
|
51
|
-
a directed stream transfer) or all attachers are called and receive the
|
|
52
|
-
arguments as extra information. The `Readable` stream is available via
|
|
53
|
-
`info.stream` in the attacher callback.
|
|
54
|
-
|
|
55
|
-
In contrast to the regular MQTT message publish/subscribe, this
|
|
56
|
-
pattern allows to transfer arbitrary amounts of arbitrary data by
|
|
57
|
-
chunking the data via a stream.
|
|
58
|
-
|
|
59
|
-

|
|
60
|
-
|
|
61
45
|
- **Service Call**:
|
|
62
46
|
|
|
63
47
|
Service Call is a *bi-directional* communication pattern.
|
|
@@ -73,18 +57,24 @@ communication patterns with type safety:
|
|
|
73
57
|
Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call)
|
|
74
58
|
(RPC) style communication.
|
|
75
59
|
|
|
76
|
-

|
|
77
61
|
|
|
78
62
|
- **Resource Transfer**:
|
|
79
63
|
|
|
80
64
|
Resource Transfer is a *bi-directional* communication pattern.
|
|
81
65
|
A Resource is the combination of a resource name and optionally zero or more arguments.
|
|
82
66
|
You *provision* for a resource transfer.
|
|
83
|
-
When a resource is *fetched
|
|
67
|
+
When a resource is *fetched*, a single particular provisioner (in case
|
|
84
68
|
of a directed resource transfer) or one arbitrary provisioner is called and
|
|
85
|
-
sends
|
|
69
|
+
sends the resource and its arguments.
|
|
70
|
+
When a resource is *pushed*, the provisioner receives the resource data
|
|
71
|
+
as a stream with arguments.
|
|
86
72
|
|
|
87
|
-
|
|
73
|
+
In contrast to the regular MQTT message publish/subscribe, this
|
|
74
|
+
pattern allows to transfer arbitrary amounts of arbitrary data by
|
|
75
|
+
chunking the data via a stream.
|
|
76
|
+
|
|
77
|
+

|
|
88
78
|
|
|
89
79
|
Usage
|
|
90
80
|
-----
|
|
@@ -92,7 +82,7 @@ Usage
|
|
|
92
82
|
### API:
|
|
93
83
|
|
|
94
84
|
The API type defines the available endpoints. Use the marker types
|
|
95
|
-
`Event<T>`, `
|
|
85
|
+
`Event<T>`, `Service<T>`, and `Resource<T>` to declare the communication
|
|
96
86
|
pattern of each endpoint:
|
|
97
87
|
|
|
98
88
|
```ts
|
|
@@ -100,16 +90,15 @@ import type * as MQTTpt from "mqtt-plus"
|
|
|
100
90
|
|
|
101
91
|
export type API = {
|
|
102
92
|
"example/sample": MQTTpt.Event<(a1: string, a2: number) => void>
|
|
103
|
-
"example/upload": MQTTpt.Stream<(name: string) => void>
|
|
104
93
|
"example/hello": MQTTpt.Service<(a1: string, a2: number) => string>
|
|
105
94
|
"example/resource": MQTTpt.Resource<(filename: string) => void>
|
|
106
95
|
}
|
|
107
96
|
```
|
|
108
97
|
|
|
109
98
|
The marker types ensure that `subscribe()` and `emit()` only accept
|
|
110
|
-
`Event<T>` endpoints, `
|
|
111
|
-
`
|
|
112
|
-
`
|
|
99
|
+
`Event<T>` endpoints, `register()` and `call()` only accept
|
|
100
|
+
`Service<T>` endpoints, and `provision()`, `fetch()` and `push()` only
|
|
101
|
+
accept `Resource<T>` endpoints.
|
|
113
102
|
|
|
114
103
|
### Server:
|
|
115
104
|
|
|
@@ -178,18 +167,27 @@ The **MQTT+** API provides the following methods:
|
|
|
178
167
|
The `mqtt` is the [MQTT.js](https://www.npmjs.com/package/mqtt) instance,
|
|
179
168
|
which has to be established separately.
|
|
180
169
|
|
|
170
|
+
Use `destroy()` to clean up when the instance is no longer needed.
|
|
171
|
+
|
|
181
172
|
The optional `options` object supports the following fields:
|
|
182
173
|
- `id`: Custom MQTT peer identifier (default: auto-generated NanoID).
|
|
183
174
|
- `codec`: Encoding format (default: `cbor`).
|
|
184
175
|
- `timeout`: Communication timeout in milliseconds (default: `10000`).
|
|
185
|
-
- `chunkSize`: Chunk size in bytes for
|
|
176
|
+
- `chunkSize`: Chunk size in bytes for resource transfers (default: `16384`).
|
|
186
177
|
- `topicMake`: Custom topic generation function.
|
|
187
|
-
The `operation` parameter is one of: `event-emission`, `
|
|
178
|
+
The `operation` parameter is one of: `event-emission`, `service-call-request`, `service-call-response`, `resource-transfer-request`, `resource-transfer-response`.
|
|
188
179
|
(default: `` (name, operation, peerId) => `${name}/${operation}` + (peerId ? `/${peerId}` : "/any") ``)
|
|
189
180
|
- `topicMatch`: Custom topic matching function.
|
|
190
181
|
Returns `{ name, operation, peerId? }` or `null` if no match. The `peerId` is `undefined` for broadcast topics (ending with `/any`).
|
|
191
182
|
(default: `` (topic) => { const m = topic.match(/^(.+)\/([^/]+)\/([^/]+)$/); return m ? { name: m[1], operation: m[2], peerId: m[3] === "any" ? undefined : m[3] } : null } ``)
|
|
192
183
|
|
|
184
|
+
- **Destruction**:<br/>
|
|
185
|
+
|
|
186
|
+
destroy(): void
|
|
187
|
+
|
|
188
|
+
Clean up the MQTT+ instance by removing all event listeners.
|
|
189
|
+
Call this method when the instance is no longer needed.
|
|
190
|
+
|
|
193
191
|
- **Event Subscription**:<br/>
|
|
194
192
|
|
|
195
193
|
/* (simplified TypeScript API method signature) */
|
|
@@ -213,30 +211,6 @@ The **MQTT+** API provides the following methods:
|
|
|
213
211
|
`${event}/event-emission/${peerId}`) are subscribed. Returns a
|
|
214
212
|
`Subscription` object with an `unsubscribe()` method.
|
|
215
213
|
|
|
216
|
-
- **Stream Attachment**:<br/>
|
|
217
|
-
|
|
218
|
-
/* (simplified TypeScript API method signature) */
|
|
219
|
-
attach(
|
|
220
|
-
stream: string,
|
|
221
|
-
options?: MQTT::IClientSubscribeOptions
|
|
222
|
-
callback: (
|
|
223
|
-
...params: any[],
|
|
224
|
-
info: { sender: string, receiver?: string, stream: stream.Readable }
|
|
225
|
-
) => void
|
|
226
|
-
): Promise<Attachment>
|
|
227
|
-
|
|
228
|
-
Attach to (observe) a stream.
|
|
229
|
-
The `stream` has to be a valid MQTT topic name.
|
|
230
|
-
The optional `options` allows setting MQTT.js `subscribe()` options like `qos`.
|
|
231
|
-
The `callback` is called with the `params` passed to a remote `transfer()`.
|
|
232
|
-
The `info.stream` provides a Node.js `Readable` stream for consuming the transferred data.
|
|
233
|
-
There is no return value of `callback`.
|
|
234
|
-
|
|
235
|
-
Internally, on the MQTT broker, the topics generated by
|
|
236
|
-
`topicMake(stream, "stream-transfer")` (default: `${stream}/stream-transfer/any` and
|
|
237
|
-
`${stream}/stream-transfer/${peerId}`) are subscribed. Returns an
|
|
238
|
-
`Attachment` object with an `unattach()` method.
|
|
239
|
-
|
|
240
214
|
- **Service Registration**:<br/>
|
|
241
215
|
|
|
242
216
|
/* (simplified TypeScript API method signature) */
|
|
@@ -268,20 +242,32 @@ The **MQTT+** API provides the following methods:
|
|
|
268
242
|
options?: MQTT::IClientSubscribeOptions
|
|
269
243
|
callback: (
|
|
270
244
|
...params: any[],
|
|
271
|
-
info: {
|
|
245
|
+
info: {
|
|
246
|
+
sender: string,
|
|
247
|
+
receiver?: string,
|
|
248
|
+
resource: Buffer | Readable | null,
|
|
249
|
+
stream?: Readable,
|
|
250
|
+
buffer?: Promise<Buffer>
|
|
251
|
+
}
|
|
272
252
|
) => void
|
|
273
253
|
): Promise<Provisioning>
|
|
274
254
|
|
|
275
|
-
Provision a resource.
|
|
255
|
+
Provision a resource for both fetch requests and pushed data.
|
|
276
256
|
The `resource` has to be a valid MQTT topic name.
|
|
277
257
|
The optional `options` allows setting MQTT.js `subscribe()` options like `qos`.
|
|
278
|
-
|
|
279
|
-
The `callback`
|
|
258
|
+
|
|
259
|
+
For **fetch requests**: The `callback` is called with the `params` passed to a remote `fetch()`.
|
|
260
|
+
The `callback` should set `info.resource` to a `Buffer` or `Readable` containing the resource data.
|
|
261
|
+
|
|
262
|
+
For **pushed data**: The `callback` is called with the `params` passed to a remote `push()`.
|
|
263
|
+
The `info.stream` provides a Node.js `Readable` stream for consuming the pushed data.
|
|
264
|
+
The `info.buffer` provides a lazy `Promise<Buffer>` that resolves to the complete data once the stream ends.
|
|
280
265
|
|
|
281
266
|
Internally, on the MQTT broker, the topics by
|
|
282
|
-
`topicMake(resource, "resource-transfer-request")` (
|
|
283
|
-
`${resource}/resource-transfer-request/${peerId}
|
|
284
|
-
|
|
267
|
+
`topicMake(resource, "resource-transfer-request")` and `topicMake(resource, "resource-transfer-response")`
|
|
268
|
+
(default: `${resource}/resource-transfer-request/any`, `${resource}/resource-transfer-request/${peerId}`,
|
|
269
|
+
`${resource}/resource-transfer-response/any`, and `${resource}/resource-transfer-response/${peerId}`)
|
|
270
|
+
are subscribed. Returns a `Provisioning` object with an `unprovision()` method.
|
|
285
271
|
|
|
286
272
|
- **Event Emission**:<br/>
|
|
287
273
|
|
|
@@ -303,33 +289,6 @@ The **MQTT+** API provides the following methods:
|
|
|
303
289
|
Internally, publishes to the MQTT topic by `topicMake(event, "event-emission", peerId)`
|
|
304
290
|
(default: `${event}/event-emission/any` or `${event}/event-emission/${peerId}`).
|
|
305
291
|
|
|
306
|
-
- **Stream Transfer**:<br/>
|
|
307
|
-
|
|
308
|
-
/* (simplified TypeScript API method signature) */
|
|
309
|
-
transfer(
|
|
310
|
-
stream: string,
|
|
311
|
-
readable: stream.Readable,
|
|
312
|
-
receiver?: Receiver,
|
|
313
|
-
options?: MQTT::IClientPublishOptions,
|
|
314
|
-
...params: any[]
|
|
315
|
-
): Promise<void>
|
|
316
|
-
|
|
317
|
-
Transfer a stream to all attachers or a specific attacher.
|
|
318
|
-
The `readable` is a Node.js `Readable` stream providing the data to transfer.
|
|
319
|
-
The optional `receiver` directs the transfer to a specific attacher only.
|
|
320
|
-
The optional `options` allows setting MQTT.js `publish()` options like `qos` or `retain`.
|
|
321
|
-
|
|
322
|
-
The data is read from `readable` in chunks (default: 16KB,
|
|
323
|
-
configurable via `chunkSize` option) and sent over MQTT until the
|
|
324
|
-
stream is closed. The returned `Promise` resolves when the entire
|
|
325
|
-
stream has been transferred.
|
|
326
|
-
|
|
327
|
-
The remote `attach()` `callback` is called with `params` and an `info` object
|
|
328
|
-
containing a `stream.Readable` for consuming the transferred data.
|
|
329
|
-
|
|
330
|
-
Internally, publishes to the MQTT topic by `topicMake(stream, "stream-transfer", peerId)`
|
|
331
|
-
(default: `${stream}/stream-transfer/any` or `${stream}/stream-transfer/${peerId}`).
|
|
332
|
-
|
|
333
292
|
- **Service Call**:<br/>
|
|
334
293
|
|
|
335
294
|
/* (simplified TypeScript API method signature) */
|
|
@@ -352,36 +311,67 @@ The **MQTT+** API provides the following methods:
|
|
|
352
311
|
(default: `${service}/service-call-response/${peerId}`) is temporarily subscribed
|
|
353
312
|
for receiving the response.
|
|
354
313
|
|
|
355
|
-
- **Resource
|
|
314
|
+
- **Resource Fetch**:<br/>
|
|
356
315
|
|
|
357
316
|
/* (simplified TypeScript API method signature) */
|
|
358
317
|
fetch(
|
|
359
|
-
|
|
318
|
+
resource: string,
|
|
360
319
|
receiver?: Receiver,
|
|
361
320
|
options?: MQTT::IClientSubscribeOptions,
|
|
362
321
|
...params: any[]
|
|
363
|
-
): Promise<Buffer>
|
|
322
|
+
): Promise<{ stream: Readable, buffer: Promise<Buffer> }>
|
|
364
323
|
|
|
365
324
|
Fetches a resource from any resource provisioner or from a specific provisioner.
|
|
366
325
|
The optional `receiver` directs the call to a specific provisioner only.
|
|
367
326
|
The optional `options` allows setting MQTT.js `publish()` options like `qos` or `retain`.
|
|
368
327
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
328
|
+
Returns an object with a `stream` (`Readable`) for consuming the transferred data
|
|
329
|
+
and a lazy `buffer` (`Promise<Buffer>`) that resolves to the complete data once the stream ends.
|
|
330
|
+
|
|
331
|
+
The remote `provision()` `callback` is called with `params` and
|
|
332
|
+
should set `info.resource` to a `Buffer` or `Readable` containing the resource data.
|
|
333
|
+
If the remote `callback` throws an exception, this destroys the stream with the error.
|
|
372
334
|
|
|
373
335
|
Internally, on the MQTT broker, the topic by
|
|
374
336
|
`topicMake(resource, "resource-transfer-response", peerId)` (default:
|
|
375
337
|
`${resource}/resource-transfer-response/${peerId}`) is temporarily subscribed
|
|
376
338
|
for receiving the response.
|
|
377
339
|
|
|
340
|
+
- **Resource Push**:<br/>
|
|
341
|
+
|
|
342
|
+
/* (simplified TypeScript API method signature) */
|
|
343
|
+
push(
|
|
344
|
+
resource: string,
|
|
345
|
+
streamOrBuffer: Readable | Buffer,
|
|
346
|
+
receiver?: Receiver,
|
|
347
|
+
options?: MQTT::IClientPublishOptions,
|
|
348
|
+
...params: any[]
|
|
349
|
+
): Promise<void>
|
|
350
|
+
|
|
351
|
+
Pushes a resource to all provisioners or a specific provisioner.
|
|
352
|
+
The `streamOrBuffer` is either a Node.js `Readable` stream or a `Buffer` providing the data to push.
|
|
353
|
+
The optional `receiver` directs the push to a specific provisioner only.
|
|
354
|
+
The optional `options` allows setting MQTT.js `publish()` options like `qos` or `retain`.
|
|
355
|
+
|
|
356
|
+
The data is read from `streamOrBuffer` in chunks (default: 16KB,
|
|
357
|
+
configurable via `chunkSize` option) and sent over MQTT until the
|
|
358
|
+
stream is closed or the buffer is fully transferred.
|
|
359
|
+
The returned `Promise` resolves when the entire data has been pushed.
|
|
360
|
+
|
|
361
|
+
The remote `provision()` `callback` is called with `params` and an `info` object
|
|
362
|
+
containing `stream` (`Readable`) for consuming the pushed data and
|
|
363
|
+
`buffer` (lazy `Promise<Buffer>`) that resolves to the complete data once the stream ends.
|
|
364
|
+
|
|
365
|
+
Internally, publishes to the MQTT topic by `topicMake(resource, "resource-transfer-response", peerId)`
|
|
366
|
+
(default: `${resource}/resource-transfer-response/any` or `${resource}/resource-transfer-response/${peerId}`).
|
|
367
|
+
|
|
378
368
|
- **Receiver Wrapping**:<br/>
|
|
379
369
|
|
|
380
370
|
receiver(
|
|
381
371
|
id: string
|
|
382
372
|
): Receiver
|
|
383
373
|
|
|
384
|
-
Wrap a receiver ID string for use with `emit()` or `
|
|
374
|
+
Wrap a receiver ID string for use with `emit()`, `call()`, `fetch()` or `push()` to direct the
|
|
385
375
|
message to a specific receiver. Returns a `Receiver` object.
|
|
386
376
|
|
|
387
377
|
Internals
|
|
@@ -583,7 +573,7 @@ Notice
|
|
|
583
573
|
> or CBOR (default), uses an own packet format (allowing sender and
|
|
584
574
|
> receiver information), uses shorter NanoIDs instead of longer UUIDs
|
|
585
575
|
> for identification of sender, receiver and requests, and additionally
|
|
586
|
-
> provides
|
|
576
|
+
> provides resource transfer support (with fetch and push capabilities).
|
|
587
577
|
|
|
588
578
|
License
|
|
589
579
|
-------
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
shape: sequence_diagram
|
|
3
|
+
|
|
4
|
+
client: "Client"
|
|
5
|
+
broker: "Broker"
|
|
6
|
+
server: "Server"
|
|
7
|
+
|
|
8
|
+
broker.class: brown
|
|
9
|
+
|
|
10
|
+
provision("foo/bar") {
|
|
11
|
+
server -> broker: "op: subscribe\ntopic: foo/bar/resource-transfer-request/any"
|
|
12
|
+
server -> broker: "op: subscribe\ntopic: foo/bar/resource-transfer-response/any"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
push("foo/bar") {
|
|
16
|
+
client -> broker: "op: publish\ntopic: foo/bar/resource-transfer-response/any\ndata: Resource-Transfer-Response #1"
|
|
17
|
+
broker -> server: "op: publish\ntopic: foo/bar/resource-transfer-response/any\ndata: Resource-Transfer-Response #1"
|
|
18
|
+
client -> broker: "op: publish\ntopic: foo/bar/resource-transfer-response/any\ndata: Resource-Transfer-Response #N"
|
|
19
|
+
broker -> server: "op: publish\ntopic: foo/bar/resource-transfer-response/any\ndata: Resource-Transfer-Response #N"
|
|
20
|
+
client -> broker: "op: publish\ntopic: foo/bar/resource-transfer-response/any\ndata: Resource-Transfer-Response EoS"
|
|
21
|
+
broker -> server: "op: publish\ntopic: foo/bar/resource-transfer-response/any\ndata: Resource-Transfer-Response EoS"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fetch("foo/bar") {
|
|
25
|
+
client -> broker: "op: subscribe\ntopic: foo/bar/resource-transfer-response/XXX"
|
|
26
|
+
client -> broker: "op: publish\ntopic: foo/bar/resource-transfer-request/any\ndata: Resource-Transfer-Request"
|
|
27
|
+
broker -> server: "op: publish\ntopic: foo/bar/resource-transfer-request/any\ndata: Resource-Transfer-Request"
|
|
28
|
+
broker <- server: "op: publish\ntopic: foo/bar/resource-transfer-response/XXX\ndata: Resource-Transfer-Response #1"
|
|
29
|
+
client <- broker: "op: publish\ntopic: foo/bar/resource-transfer-response/XXX\ndata: Resource-Transfer-Response #1"
|
|
30
|
+
broker <- server: "op: publish\ntopic: foo/bar/resource-transfer-response/XXX\ndata: Resource-Transfer-Response #N"
|
|
31
|
+
client <- broker: "op: publish\ntopic: foo/bar/resource-transfer-response/XXX\ndata: Resource-Transfer-Response #N"
|
|
32
|
+
}
|
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
type Brand<T> = T & {
|
|
2
2
|
readonly __brand: unique symbol;
|
|
3
3
|
};
|
|
4
|
-
export type APIEndpoint = APIEndpointEvent |
|
|
4
|
+
export type APIEndpoint = APIEndpointEvent | APIEndpointService | APIEndpointResource;
|
|
5
5
|
export type APIEndpointEvent = (...args: any[]) => void;
|
|
6
|
-
export type APIEndpointStream = (...args: any[]) => void;
|
|
7
6
|
export type APIEndpointService = (...args: any[]) => any;
|
|
8
7
|
export type APIEndpointResource = (...args: any[]) => void;
|
|
9
8
|
export type Event<T extends APIEndpointEvent> = Brand<T>;
|
|
10
|
-
export type Stream<T extends APIEndpointStream> = Brand<T>;
|
|
11
9
|
export type Service<T extends APIEndpointService> = Brand<T>;
|
|
12
10
|
export type Resource<T extends APIEndpointResource> = Brand<T>;
|
|
13
11
|
export type APISchema = Record<string, APIEndpoint>;
|
|
14
12
|
export type EventKeys<T> = string extends keyof T ? string : {
|
|
15
13
|
[K in keyof T]: T[K] extends Event<infer _F> ? K : never;
|
|
16
14
|
}[keyof T];
|
|
17
|
-
export type StreamKeys<T> = string extends keyof T ? string : {
|
|
18
|
-
[K in keyof T]: T[K] extends Stream<infer _F> ? K : never;
|
|
19
|
-
}[keyof T];
|
|
20
15
|
export type ServiceKeys<T> = string extends keyof T ? string : {
|
|
21
16
|
[K in keyof T]: T[K] extends Service<infer _F> ? K : never;
|
|
22
17
|
}[keyof T];
|
|
@@ -109,6 +109,6 @@ export class BaseTrait extends ReceiverTrait {
|
|
|
109
109
|
this._dispatchMessage(topic, parsed);
|
|
110
110
|
}
|
|
111
111
|
/* dispatch parsed message to appropriate handler
|
|
112
|
-
(base implementation, to be overridden in
|
|
112
|
+
(base implementation, to be overridden in sub-traits) */
|
|
113
113
|
_dispatchMessage(_topic, _parsed) { }
|
|
114
114
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Readable } from "stream";
|
|
2
2
|
export interface InfoBase {
|
|
3
3
|
sender: string;
|
|
4
4
|
receiver?: string;
|
|
5
5
|
}
|
|
6
6
|
export interface InfoEvent extends InfoBase {
|
|
7
7
|
}
|
|
8
|
-
export interface InfoStream extends InfoBase {
|
|
9
|
-
stream: stream.Readable;
|
|
10
|
-
}
|
|
11
8
|
export interface InfoService extends InfoBase {
|
|
12
9
|
}
|
|
13
10
|
export interface InfoResource extends InfoBase {
|
|
14
|
-
resource: Buffer | null;
|
|
11
|
+
resource: Buffer | Readable | null;
|
|
12
|
+
stream?: Readable;
|
|
13
|
+
buffer?: Promise<Buffer>;
|
|
15
14
|
}
|
|
16
15
|
export type WithInfo<F, I extends InfoBase> = F extends (...args: infer P) => infer R ? (...args: [...P, info: I]) => R : never;
|
|
@@ -12,12 +12,6 @@ export declare class EventEmission extends Base {
|
|
|
12
12
|
params?: any[] | undefined;
|
|
13
13
|
constructor(id: string, event: string, params?: any[] | undefined, sender?: string, receiver?: string);
|
|
14
14
|
}
|
|
15
|
-
export declare class StreamTransfer extends Base {
|
|
16
|
-
stream: string;
|
|
17
|
-
chunk: Buffer | null;
|
|
18
|
-
params?: any[] | undefined;
|
|
19
|
-
constructor(id: string, stream: string, chunk: Buffer | null, params?: any[] | undefined, sender?: string, receiver?: string);
|
|
20
|
-
}
|
|
21
15
|
export declare class ServiceCallRequest extends Base {
|
|
22
16
|
service: string;
|
|
23
17
|
params?: any[] | undefined;
|
|
@@ -34,19 +28,20 @@ export declare class ResourceTransferRequest extends Base {
|
|
|
34
28
|
constructor(id: string, resource: string, params?: any[] | undefined, sender?: string, receiver?: string);
|
|
35
29
|
}
|
|
36
30
|
export declare class ResourceTransferResponse extends Base {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
resource?: string | undefined;
|
|
32
|
+
params?: any[] | undefined;
|
|
33
|
+
chunk?: Buffer | undefined;
|
|
34
|
+
error?: string | undefined;
|
|
35
|
+
final?: boolean | undefined;
|
|
36
|
+
constructor(id: string, resource?: string | undefined, params?: any[] | undefined, chunk?: Buffer | undefined, error?: string | undefined, final?: boolean | undefined, sender?: string, receiver?: string);
|
|
41
37
|
}
|
|
42
38
|
export default class Msg {
|
|
43
39
|
makeEventEmission(id: string, event: string, params?: any[], sender?: string, receiver?: string): EventEmission;
|
|
44
|
-
makeStreamTransfer(id: string, stream: string, chunk: Buffer | null, params?: any[], sender?: string, receiver?: string): StreamTransfer;
|
|
45
40
|
makeServiceCallRequest(id: string, service: string, params?: any[], sender?: string, receiver?: string): ServiceCallRequest;
|
|
46
41
|
makeServiceCallResponse(id: string, result?: any, error?: string, sender?: string, receiver?: string): ServiceCallResponse;
|
|
47
42
|
makeResourceTransferRequest(id: string, resource: string, params?: any[], sender?: string, receiver?: string): ResourceTransferRequest;
|
|
48
|
-
makeResourceTransferResponse(id: string, chunk?: Buffer, error?: string, final?: boolean, sender?: string, receiver?: string): ResourceTransferResponse;
|
|
49
|
-
parse(obj: any): EventEmission |
|
|
43
|
+
makeResourceTransferResponse(id: string, resource?: string, params?: any[], chunk?: Buffer, error?: string, final?: boolean, sender?: string, receiver?: string): ResourceTransferResponse;
|
|
44
|
+
parse(obj: any): EventEmission | ServiceCallRequest | ServiceCallResponse | ResourceTransferRequest | ResourceTransferResponse;
|
|
50
45
|
}
|
|
51
46
|
export declare class MsgTrait<T extends APISchema = APISchema> extends CodecTrait<T> {
|
|
52
47
|
protected msg: Msg;
|
|
@@ -39,15 +39,6 @@ export class EventEmission extends Base {
|
|
|
39
39
|
this.params = params;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
/* stream chunk */
|
|
43
|
-
export class StreamTransfer extends Base {
|
|
44
|
-
constructor(id, stream, chunk, params, sender, receiver) {
|
|
45
|
-
super("stream-transfer", id, sender, receiver);
|
|
46
|
-
this.stream = stream;
|
|
47
|
-
this.chunk = chunk;
|
|
48
|
-
this.params = params;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
42
|
/* service request */
|
|
52
43
|
export class ServiceCallRequest extends Base {
|
|
53
44
|
constructor(id, service, params, sender, receiver) {
|
|
@@ -74,8 +65,10 @@ export class ResourceTransferRequest extends Base {
|
|
|
74
65
|
}
|
|
75
66
|
/* resource response */
|
|
76
67
|
export class ResourceTransferResponse extends Base {
|
|
77
|
-
constructor(id, chunk, error, final, sender, receiver) {
|
|
68
|
+
constructor(id, resource, params, chunk, error, final, sender, receiver) {
|
|
78
69
|
super("resource-transfer-response", id, sender, receiver);
|
|
70
|
+
this.resource = resource;
|
|
71
|
+
this.params = params;
|
|
79
72
|
this.chunk = chunk;
|
|
80
73
|
this.error = error;
|
|
81
74
|
this.final = final;
|
|
@@ -87,10 +80,6 @@ export default class Msg {
|
|
|
87
80
|
makeEventEmission(id, event, params, sender, receiver) {
|
|
88
81
|
return new EventEmission(id, event, params, sender, receiver);
|
|
89
82
|
}
|
|
90
|
-
/* factory for stream chunk */
|
|
91
|
-
makeStreamTransfer(id, stream, chunk, params, sender, receiver) {
|
|
92
|
-
return new StreamTransfer(id, stream, chunk, params, sender, receiver);
|
|
93
|
-
}
|
|
94
83
|
/* factory for service request */
|
|
95
84
|
makeServiceCallRequest(id, service, params, sender, receiver) {
|
|
96
85
|
return new ServiceCallRequest(id, service, params, sender, receiver);
|
|
@@ -104,8 +93,8 @@ export default class Msg {
|
|
|
104
93
|
return new ResourceTransferRequest(id, resource, params, sender, receiver);
|
|
105
94
|
}
|
|
106
95
|
/* factory for resource response */
|
|
107
|
-
makeResourceTransferResponse(id, chunk, error, final, sender, receiver) {
|
|
108
|
-
return new ResourceTransferResponse(id, chunk, error, final, sender, receiver);
|
|
96
|
+
makeResourceTransferResponse(id, resource, params, chunk, error, final, sender, receiver) {
|
|
97
|
+
return new ResourceTransferResponse(id, resource, params, chunk, error, final, sender, receiver);
|
|
109
98
|
}
|
|
110
99
|
/* parse any object into typed object */
|
|
111
100
|
parse(obj) {
|
|
@@ -133,18 +122,6 @@ export default class Msg {
|
|
|
133
122
|
throw new Error("invalid EventEmission object: \"params\" field must be an array");
|
|
134
123
|
return this.makeEventEmission(obj.id, obj.event, obj.params, obj.sender, obj.receiver);
|
|
135
124
|
}
|
|
136
|
-
else if (obj.type === "stream-transfer") {
|
|
137
|
-
/* detect and parse stream chunk */
|
|
138
|
-
if (typeof obj.stream !== "string")
|
|
139
|
-
throw new Error("invalid StreamTransfer object: \"stream\" field must be a string");
|
|
140
|
-
if (anyFieldsExcept(obj, ["type", "id", "stream", "chunk", "params", "sender", "receiver"]))
|
|
141
|
-
throw new Error("invalid StreamTransfer object: contains unknown fields");
|
|
142
|
-
if (obj.chunk !== undefined && typeof obj.chunk !== "object")
|
|
143
|
-
throw new Error("invalid StreamTransfer object: \"chunk\" field must be an object or null");
|
|
144
|
-
if (!validParams(obj))
|
|
145
|
-
throw new Error("invalid StreamTransfer object: \"params\" field must be an array");
|
|
146
|
-
return this.makeStreamTransfer(obj.id, obj.stream, obj.chunk, obj.params, obj.sender, obj.receiver);
|
|
147
|
-
}
|
|
148
125
|
else if (obj.type === "service-call-request") {
|
|
149
126
|
/* detect and parse service request */
|
|
150
127
|
if (typeof obj.service !== "string")
|
|
@@ -172,15 +149,19 @@ export default class Msg {
|
|
|
172
149
|
return this.makeResourceTransferRequest(obj.id, obj.resource, obj.params, obj.sender, obj.receiver);
|
|
173
150
|
}
|
|
174
151
|
else if (obj.type === "resource-transfer-response") {
|
|
152
|
+
if (obj.resource !== undefined && typeof obj.resource !== "string")
|
|
153
|
+
throw new Error("invalid ResourceTransferResponse object: \"resource\" field must be a string");
|
|
175
154
|
if (obj.chunk !== undefined && typeof obj.chunk !== "object")
|
|
176
155
|
throw new Error("invalid ResourceTransferResponse object: \"chunk\" field must be an object");
|
|
177
156
|
if (obj.error !== undefined && typeof obj.error !== "string")
|
|
178
157
|
throw new Error("invalid ResourceTransferResponse object: \"error\" field must be a string");
|
|
179
158
|
if (obj.final !== undefined && typeof obj.final !== "boolean")
|
|
180
159
|
throw new Error("invalid ResourceTransferResponse object: \"final\" field must be a boolean");
|
|
181
|
-
if (
|
|
160
|
+
if (!validParams(obj))
|
|
161
|
+
throw new Error("invalid ResourceTransferResponse object: \"params\" field must be an array");
|
|
162
|
+
if (anyFieldsExcept(obj, ["type", "id", "resource", "params", "chunk", "error", "final", "sender", "receiver"]))
|
|
182
163
|
throw new Error("invalid ResourceTransferResponse object: contains unknown fields");
|
|
183
|
-
return this.makeResourceTransferResponse(obj.id, obj.chunk, obj.error, obj.final, obj.sender, obj.receiver);
|
|
164
|
+
return this.makeResourceTransferResponse(obj.id, obj.resource, obj.params, obj.chunk, obj.error, obj.final, obj.sender, obj.receiver);
|
|
184
165
|
}
|
|
185
166
|
else
|
|
186
167
|
throw new Error("invalid object: not of any known type");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Readable } from "stream";
|
|
1
2
|
import { IClientPublishOptions, IClientSubscribeOptions } from "mqtt";
|
|
2
3
|
import { APISchema, ResourceKeys } from "./mqtt-plus-api";
|
|
3
4
|
import type { WithInfo, InfoResource } from "./mqtt-plus-info";
|
|
@@ -8,12 +9,35 @@ export interface Provisioning {
|
|
|
8
9
|
}
|
|
9
10
|
export declare class ResourceTrait<T extends APISchema = APISchema> extends ServiceTrait<T> {
|
|
10
11
|
private provisionings;
|
|
11
|
-
private
|
|
12
|
+
private callbacks;
|
|
13
|
+
private pushStreams;
|
|
12
14
|
provision<K extends ResourceKeys<T> & string>(resource: K, callback: WithInfo<T[K], InfoResource>): Promise<Provisioning>;
|
|
13
15
|
provision<K extends ResourceKeys<T> & string>(resource: K, options: Partial<IClientSubscribeOptions>, callback: WithInfo<T[K], InfoResource>): Promise<Provisioning>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
private _collectStreamToBuffer;
|
|
17
|
+
private _chunkToBuffer;
|
|
18
|
+
push<K extends ResourceKeys<T> & string>(resource: K, stream: Readable, ...params: Parameters<T[K]>): Promise<void>;
|
|
19
|
+
push<K extends ResourceKeys<T> & string>(resource: K, stream: Readable, receiver: Receiver, ...params: Parameters<T[K]>): Promise<void>;
|
|
20
|
+
push<K extends ResourceKeys<T> & string>(resource: K, stream: Readable, options: IClientPublishOptions, ...params: Parameters<T[K]>): Promise<void>;
|
|
21
|
+
push<K extends ResourceKeys<T> & string>(resource: K, stream: Readable, receiver: Receiver, options: IClientPublishOptions, ...params: Parameters<T[K]>): Promise<void>;
|
|
22
|
+
push<K extends ResourceKeys<T> & string>(resource: K, buffer: Buffer, ...params: Parameters<T[K]>): Promise<void>;
|
|
23
|
+
push<K extends ResourceKeys<T> & string>(resource: K, buffer: Buffer, receiver: Receiver, ...params: Parameters<T[K]>): Promise<void>;
|
|
24
|
+
push<K extends ResourceKeys<T> & string>(resource: K, buffer: Buffer, options: IClientPublishOptions, ...params: Parameters<T[K]>): Promise<void>;
|
|
25
|
+
push<K extends ResourceKeys<T> & string>(resource: K, buffer: Buffer, receiver: Receiver, options: IClientPublishOptions, ...params: Parameters<T[K]>): Promise<void>;
|
|
26
|
+
fetch<K extends ResourceKeys<T> & string>(resource: K, ...params: Parameters<T[K]>): Promise<{
|
|
27
|
+
stream: Readable;
|
|
28
|
+
buffer: Promise<Buffer>;
|
|
29
|
+
}>;
|
|
30
|
+
fetch<K extends ResourceKeys<T> & string>(resource: K, receiver: Receiver, ...params: Parameters<T[K]>): Promise<{
|
|
31
|
+
stream: Readable;
|
|
32
|
+
buffer: Promise<Buffer>;
|
|
33
|
+
}>;
|
|
34
|
+
fetch<K extends ResourceKeys<T> & string>(resource: K, options: IClientPublishOptions, ...params: Parameters<T[K]>): Promise<{
|
|
35
|
+
stream: Readable;
|
|
36
|
+
buffer: Promise<Buffer>;
|
|
37
|
+
}>;
|
|
38
|
+
fetch<K extends ResourceKeys<T> & string>(resource: K, receiver: Receiver, options: IClientPublishOptions, ...params: Parameters<T[K]>): Promise<{
|
|
39
|
+
stream: Readable;
|
|
40
|
+
buffer: Promise<Buffer>;
|
|
41
|
+
}>;
|
|
18
42
|
protected _dispatchMessage(topic: string, parsed: any): void;
|
|
19
43
|
}
|