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 +457 -0
- package/dst-stage1/mqtt-plus-codec.d.ts +6 -0
- package/dst-stage1/mqtt-plus-codec.js +74 -0
- package/dst-stage1/mqtt-plus-msg.d.ts +31 -0
- package/dst-stage1/mqtt-plus-msg.js +128 -0
- package/dst-stage1/mqtt-plus.d.ts +73 -0
- package/dst-stage1/mqtt-plus.js +408 -0
- package/dst-stage2/mqtt-plus.cjs.js +6422 -0
- package/dst-stage2/mqtt-plus.esm.js +6423 -0
- package/dst-stage2/mqtt-plus.umd.js +19 -0
- package/etc/eslint.mts +94 -0
- package/etc/logo.ai +5106 -2
- package/etc/logo.svg +17 -0
- package/etc/stx.conf +47 -0
- package/etc/tsc.json +27 -0
- package/etc/tsc.tsbuildinfo +1 -0
- package/etc/vite.mts +66 -0
- package/package.json +60 -0
- package/src/mqtt-plus-codec.ts +59 -0
- package/src/mqtt-plus-msg.ts +171 -0
- package/src/mqtt-plus.ts +598 -0
package/etc/logo.svg
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 805 283">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #369;
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
9
|
+
</defs>
|
|
10
|
+
<path class="cls-1" d="M728.126,19.9971v60.9019h58.3037v31.1724h-58.3037v61.4795h-32.6162v-61.4795h-58.3047v-31.1724h58.3047V19.9971h32.6162Z"/>
|
|
11
|
+
<path class="cls-1" d="M429.6187,268.3086c-30.5801-9.0498-54.2949-18.7227-84.251-31.5166-4.9927-2.1846-10.2974-3.1201-15.2905-3.4326-46.4941-3.4326-91.7402-37.7568-91.7402-107.0303,0-61.4727,39.3174-110.4629,105.1582-110.4629,67.0894,0,101.4141,50.5508,101.4141,106.0938,0,45.2461-20.9072,78.6348-45.2466,91.1172v1.248c14.042,4.6807,29.9561,7.8008,45.8706,11.2334l-15.9146,42.75ZM342.2471,188.7373c27.1475,0,43.062-26.2119,43.062-64.5928,0-36.8213-16.2266-63.6562-43.686-63.6562-26.5234,0-43.686,26.835-43.686,63.9688-.312,38.0684,16.5381,64.2803,43.686,64.2803h.624Z"/>
|
|
12
|
+
<path d="M228.4019,126.7417c0-26.8698,7.5125-51.3542,21.4678-70.4055l-1.8526-36.7254h-73.9541l-15.9141,56.1675c-6.2407,22.1553-13.106,51.7993-19.0347,77.3867h-.936c-4.3687-25.5874-10.6094-53.6714-16.5381-77.0747l-13.73-56.4795H32.084l-13.106,210.3164h51.7988l3.4326-75.2021c.936-24.0273,1.8721-55.2314,3.1206-84.8755h.624c4.9927,28.708,11.2334,59.9121,16.8501,82.6909l17.4746,73.0181h43.9976l20.9072-73.3301c6.8647-23.0908,15.6021-54.6069,22.1548-82.3789h.936c0,32.7642.312,60.8481,1.2485,84.8755l2.4961,75.2021h54.6074l-1.2318-24.4186c-17.433-17.6805-28.9928-43.7579-28.9928-78.767Z"/>
|
|
13
|
+
<g>
|
|
14
|
+
<polygon points="568.0386 19.6108 528.2663 19.6108 547.709 67.041 568.0386 67.041 568.9517 67.041 568.9517 229.9272 625.4312 229.9272 625.4312 67.041 680.0386 67.041 680.0386 19.6108 568.0386 19.6108"/>
|
|
15
|
+
<path d="M516.378,19.6108h-113.0977v6.1184c18.5046,9.1639,32.2805,23.7489,41.2421,41.3118h12.4293v52.0095c.0134.7731.0225,1.5469.0225,2.3221,0,.5229-.0169,1.0361-.0225,1.5558v101.9045c.2156.0464.4308.0918.6465.1383l-.6465,1.7366v3.2195h56.4795V67.041h22.3896l-19.4427-47.4302Z"/>
|
|
16
|
+
</g>
|
|
17
|
+
</svg>
|
package/etc/stx.conf
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
|
|
25
|
+
# static code analysis (linting)
|
|
26
|
+
lint
|
|
27
|
+
tsc --project etc/tsc.json --noEmit && \
|
|
28
|
+
eslint --config etc/eslint.mts src/*.ts sample/*.ts
|
|
29
|
+
|
|
30
|
+
# code compilation/transpiling (building)
|
|
31
|
+
build : lint
|
|
32
|
+
VITE_BUILD_FORMATS=es,cjs vite --config etc/vite.mts build --mode production
|
|
33
|
+
VITE_BUILD_FORMATS=umd vite --config etc/vite.mts build --mode production
|
|
34
|
+
|
|
35
|
+
# execute simple sample for testing
|
|
36
|
+
test
|
|
37
|
+
npx tsx sample/sample.ts
|
|
38
|
+
|
|
39
|
+
# cleanup (built artifacts)
|
|
40
|
+
clean
|
|
41
|
+
shx rm -rf dst
|
|
42
|
+
|
|
43
|
+
# cleanup (bootstrap artifacts)
|
|
44
|
+
distclean : clean
|
|
45
|
+
shx rm -f package-lock.json
|
|
46
|
+
shx rm -rf node_modules
|
|
47
|
+
|
package/etc/tsc.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"outDir": "../dst-stage1",
|
|
4
|
+
"target": "es2022",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
|
+
"useDefineForClassFields": false,
|
|
8
|
+
"composite": false,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"strictFunctionTypes": true,
|
|
11
|
+
"resolveJsonModule": false,
|
|
12
|
+
"isolatedModules": false,
|
|
13
|
+
"esModuleInterop": false,
|
|
14
|
+
"lib": [ "es2022", "dom" ],
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"noEmit": false,
|
|
18
|
+
"rootDir": "../src"
|
|
19
|
+
},
|
|
20
|
+
"include": [
|
|
21
|
+
"../src/**/*.ts",
|
|
22
|
+
"../src/**/*.d.ts"
|
|
23
|
+
],
|
|
24
|
+
"exclude": [
|
|
25
|
+
"../node_modules"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/mqtt-plus-codec.ts","../src/mqtt-plus-msg.ts","../src/mqtt-plus.ts"],"version":"5.9.3"}
|
package/etc/vite.mts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
|
|
25
|
+
import * as Vite from "vite"
|
|
26
|
+
import { tscPlugin } from "@wroud/vite-plugin-tsc"
|
|
27
|
+
import { viteSingleFile } from "vite-plugin-singlefile"
|
|
28
|
+
import { nodePolyfills } from "vite-plugin-node-polyfills"
|
|
29
|
+
|
|
30
|
+
const formats = process.env.VITE_BUILD_FORMATS ?? "esm"
|
|
31
|
+
|
|
32
|
+
export default Vite.defineConfig(({ command, mode }) => ({
|
|
33
|
+
logLevel: "info",
|
|
34
|
+
appType: "custom",
|
|
35
|
+
base: "",
|
|
36
|
+
root: "",
|
|
37
|
+
plugins: [
|
|
38
|
+
tscPlugin({
|
|
39
|
+
tscArgs: [ "--project", "etc/tsc.json" ],
|
|
40
|
+
packageManager: "npx",
|
|
41
|
+
prebuild: true
|
|
42
|
+
}),
|
|
43
|
+
...(formats === "umd" ? [ nodePolyfills() ] : []),
|
|
44
|
+
viteSingleFile()
|
|
45
|
+
],
|
|
46
|
+
build: {
|
|
47
|
+
rollupOptions: {
|
|
48
|
+
external: formats === "umd" ? [] : [ "stream" ]
|
|
49
|
+
},
|
|
50
|
+
lib: {
|
|
51
|
+
entry: "dst-stage1/mqtt-plus.js",
|
|
52
|
+
formats: formats.split(","),
|
|
53
|
+
name: "MQTTp",
|
|
54
|
+
fileName: (format) => `mqtt-plus.${format === "es" ? "esm" : format}.js`
|
|
55
|
+
},
|
|
56
|
+
target: formats === "umd" ? "es2022" : "node20",
|
|
57
|
+
outDir: "dst-stage2",
|
|
58
|
+
assetsDir: "",
|
|
59
|
+
emptyOutDir: (mode === "production") && formats !== "umd",
|
|
60
|
+
chunkSizeWarningLimit: 5000,
|
|
61
|
+
assetsInlineLimit: 0,
|
|
62
|
+
sourcemap: (mode === "development"),
|
|
63
|
+
minify: (mode === "production") && formats === "umd",
|
|
64
|
+
reportCompressedSize: (mode === "production")
|
|
65
|
+
}
|
|
66
|
+
}))
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mqtt-plus",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "MQTT Communication Patterns",
|
|
5
|
+
"keywords": [ "mqtt", "event", "service", "rpc", "request", "response" ],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": { "type": "git", "url": "git+https://github.com/rse/mqtt-plus.git" },
|
|
8
|
+
"homepage": "https://github.com/rse/mqtt-plus",
|
|
9
|
+
"bugs": "https://github.com/rse/mqtt-plus/issues",
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "Dr. Ralf S. Engelschall",
|
|
12
|
+
"email": "rse@engelschall.com",
|
|
13
|
+
"url": "http://engelschall.com"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"types": "./dst-stage1/mqtt-plus.d.ts",
|
|
17
|
+
"module": "./dst-stage2/mqtt-plus.esm.js",
|
|
18
|
+
"main": "./dst-stage2/mqtt-plus.cjs.js",
|
|
19
|
+
"browser": "./dst-stage2/mqtt-plus.umd.js",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"import": { "types": "./dst-stage1/mqtt-plus.d.ts", "default": "./dst-stage2/mqtt-plus.esm.js" },
|
|
23
|
+
"require": { "types": "./dst-stage1/mqtt-plus.d.ts", "default": "./dst-stage2/mqtt-plus.cjs.js" }
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@rse/stx": "1.1.4",
|
|
28
|
+
"shx": "0.4.0",
|
|
29
|
+
"eslint": "9.39.2",
|
|
30
|
+
"eslint-plugin-node": "11.1.0",
|
|
31
|
+
"globals": "17.0.0",
|
|
32
|
+
"@eslint/js": "9.39.2",
|
|
33
|
+
"@eslint/eslintrc": "3.3.3",
|
|
34
|
+
"jiti": "2.6.1",
|
|
35
|
+
"tsx": "4.21.0",
|
|
36
|
+
"typescript": "5.9.3",
|
|
37
|
+
"typescript-eslint": "8.51.0",
|
|
38
|
+
"@typescript-eslint/parser": "8.51.0",
|
|
39
|
+
"mqtt": "5.14.1",
|
|
40
|
+
"vite": "7.3.0",
|
|
41
|
+
"vite-plugin-singlefile": "2.3.0",
|
|
42
|
+
"vite-plugin-node-polyfills": "0.24.0",
|
|
43
|
+
"@wroud/vite-plugin-tsc": "0.12.2"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"mqtt": ">=4.0.0"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"nanoid": "5.1.6",
|
|
50
|
+
"cbor": "10.0.11"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=16.0.0"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"prepublishOnly": "npm start build",
|
|
57
|
+
"start": "stx -v4 -c etc/stx.conf",
|
|
58
|
+
"test": "npm start test"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
|
|
25
|
+
import CBOR from "cbor"
|
|
26
|
+
|
|
27
|
+
/* the encoder/decoder abstraction */
|
|
28
|
+
export default class Codec {
|
|
29
|
+
constructor (private type: "cbor" | "json") {}
|
|
30
|
+
encode (data: unknown): Buffer | string {
|
|
31
|
+
let result: Buffer | string
|
|
32
|
+
if (this.type === "cbor") {
|
|
33
|
+
try { result = CBOR.encode(data) }
|
|
34
|
+
catch (_ex) { throw new Error("failed to encode CBOR format") }
|
|
35
|
+
}
|
|
36
|
+
else if (this.type === "json") {
|
|
37
|
+
try { result = JSON.stringify(data) }
|
|
38
|
+
catch (_ex) { throw new Error("failed to encode JSON format") }
|
|
39
|
+
}
|
|
40
|
+
else
|
|
41
|
+
throw new Error("invalid format")
|
|
42
|
+
return result
|
|
43
|
+
}
|
|
44
|
+
decode (data: Buffer | string): unknown {
|
|
45
|
+
let result: unknown
|
|
46
|
+
if (this.type === "cbor" && typeof data === "object" && data instanceof Buffer) {
|
|
47
|
+
try { result = CBOR.decode(data) }
|
|
48
|
+
catch (_ex) { throw new Error("failed to decode CBOR format") }
|
|
49
|
+
}
|
|
50
|
+
else if (this.type === "json" && typeof data === "string") {
|
|
51
|
+
try { result = JSON.parse(data) }
|
|
52
|
+
catch (_ex) { throw new Error("failed to decode JSON format") }
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
throw new Error("invalid format or wrong data type")
|
|
56
|
+
return result
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
@@ -0,0 +1,171 @@
|
|
|
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
|
+
|
|
25
|
+
/* base class */
|
|
26
|
+
export class Base {
|
|
27
|
+
constructor (
|
|
28
|
+
public id: string,
|
|
29
|
+
public sender?: string,
|
|
30
|
+
public receiver?: string
|
|
31
|
+
) {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* event emission */
|
|
35
|
+
export class EventEmission extends Base {
|
|
36
|
+
constructor (
|
|
37
|
+
id: string,
|
|
38
|
+
public event: string,
|
|
39
|
+
public params?: any[],
|
|
40
|
+
sender?: string,
|
|
41
|
+
receiver?: string,
|
|
42
|
+
) { super(id, sender, receiver) }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* service request */
|
|
46
|
+
export class ServiceRequest extends Base {
|
|
47
|
+
constructor (
|
|
48
|
+
id: string,
|
|
49
|
+
public service: string,
|
|
50
|
+
public params?: any[],
|
|
51
|
+
sender?: string,
|
|
52
|
+
receiver?: string,
|
|
53
|
+
) { super(id, sender, receiver) }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* service response success */
|
|
57
|
+
export class ServiceResponseSuccess extends Base {
|
|
58
|
+
constructor (
|
|
59
|
+
id: string,
|
|
60
|
+
public result: any,
|
|
61
|
+
sender?: string,
|
|
62
|
+
receiver?: string
|
|
63
|
+
) { super(id, sender, receiver) }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* service response error */
|
|
67
|
+
export class ServiceResponseError extends Base {
|
|
68
|
+
constructor (
|
|
69
|
+
id: string,
|
|
70
|
+
public error: string,
|
|
71
|
+
sender?: string,
|
|
72
|
+
receiver?: string
|
|
73
|
+
) { super(id, sender, receiver) }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* utility class */
|
|
77
|
+
export default class Msg {
|
|
78
|
+
/* factory for event emission */
|
|
79
|
+
makeEventEmission (
|
|
80
|
+
id: string,
|
|
81
|
+
event: string,
|
|
82
|
+
params?: any[],
|
|
83
|
+
sender?: string,
|
|
84
|
+
receiver?: string
|
|
85
|
+
): EventEmission {
|
|
86
|
+
return new EventEmission(id, event, params, sender, receiver)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* factory for service request */
|
|
90
|
+
makeServiceRequest (
|
|
91
|
+
id: string,
|
|
92
|
+
service: string,
|
|
93
|
+
params?: any[],
|
|
94
|
+
sender?: string,
|
|
95
|
+
receiver?: string
|
|
96
|
+
): ServiceRequest {
|
|
97
|
+
return new ServiceRequest(id, service, params, sender, receiver)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* factory for service response success */
|
|
101
|
+
makeServiceResponseSuccess (
|
|
102
|
+
id: string,
|
|
103
|
+
result: any,
|
|
104
|
+
sender?: string,
|
|
105
|
+
receiver?: string
|
|
106
|
+
): ServiceResponseSuccess {
|
|
107
|
+
return new ServiceResponseSuccess(id, result, sender, receiver)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* factory for service response error */
|
|
111
|
+
makeServiceResponseError (
|
|
112
|
+
id: string,
|
|
113
|
+
error: string,
|
|
114
|
+
sender?: string,
|
|
115
|
+
receiver?: string
|
|
116
|
+
): ServiceResponseError {
|
|
117
|
+
return new ServiceResponseError(id, error, sender, receiver)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* parse any object into typed object */
|
|
121
|
+
parse (obj: any): EventEmission | ServiceRequest | ServiceResponseSuccess | ServiceResponseError {
|
|
122
|
+
if (typeof obj !== "object" || obj === null)
|
|
123
|
+
throw new Error("invalid argument: not an object")
|
|
124
|
+
|
|
125
|
+
/* validate common fields */
|
|
126
|
+
if (!("id" in obj) || typeof obj.id !== "string")
|
|
127
|
+
throw new Error("invalid object: missing or invalid \"id\" field")
|
|
128
|
+
if ("sender" in obj && typeof obj.sender !== "string")
|
|
129
|
+
throw new Error("invalid object: invalid \"sender\" field")
|
|
130
|
+
if ("receiver" in obj && typeof obj.sender !== "string")
|
|
131
|
+
throw new Error("invalid object: invalid \"receiver\" field")
|
|
132
|
+
|
|
133
|
+
/* dispatch according to type indication by field */
|
|
134
|
+
const anyFieldsExcept = (obj: object, allowed: string[]) =>
|
|
135
|
+
Object.keys(obj).some((key) => !allowed.includes(key))
|
|
136
|
+
if ("event" in obj) {
|
|
137
|
+
/* detect and parse event emission */
|
|
138
|
+
if (typeof obj.event !== "string")
|
|
139
|
+
throw new Error("invalid EventEmission object: \"event\" field must be a string")
|
|
140
|
+
if (anyFieldsExcept(obj, [ "type", "id", "event", "params", "sender", "receiver" ]))
|
|
141
|
+
throw new Error("invalid EventEmission object: contains unknown fields")
|
|
142
|
+
if (obj.params !== undefined && (typeof obj.params !== "object" || !Array.isArray(obj.params)))
|
|
143
|
+
throw new Error("invalid EventEmission object: \"params\" field must be an array")
|
|
144
|
+
return this.makeEventEmission(obj.id, obj.event, obj.params, obj.sender, obj.receiver)
|
|
145
|
+
}
|
|
146
|
+
else if ("service" in obj) {
|
|
147
|
+
/* detect and parse service request */
|
|
148
|
+
if (typeof obj.service !== "string")
|
|
149
|
+
throw new Error("invalid ServiceRequest object: \"service\" field must be a string")
|
|
150
|
+
if (anyFieldsExcept(obj, [ "type", "id", "service", "params", "sender", "receiver" ]))
|
|
151
|
+
throw new Error("invalid ServiceRequest object: contains unknown fields")
|
|
152
|
+
if (obj.params !== undefined && (typeof obj.params !== "object" || !Array.isArray(obj.params)))
|
|
153
|
+
throw new Error("invalid ServiceRequest object: \"params\" field must be an array")
|
|
154
|
+
return this.makeServiceRequest(obj.id, obj.service, obj.params, obj.sender, obj.receiver)
|
|
155
|
+
}
|
|
156
|
+
else if ("result" in obj) {
|
|
157
|
+
/* detect and parse service response success */
|
|
158
|
+
if (anyFieldsExcept(obj, [ "type", "id", "result", "sender", "receiver" ]))
|
|
159
|
+
throw new Error("invalid ServiceResponseSuccess object: contains unknown fields")
|
|
160
|
+
return this.makeServiceResponseSuccess(obj.id, obj.result, obj.sender, obj.receiver)
|
|
161
|
+
}
|
|
162
|
+
else if ("error" in obj) {
|
|
163
|
+
/* detect and parse service response error */
|
|
164
|
+
if (anyFieldsExcept(obj, [ "type", "id", "error", "sender", "receiver" ]))
|
|
165
|
+
throw new Error("invalid ServiceResponseError object: contains unknown fields")
|
|
166
|
+
return this.makeServiceResponseError(obj.id, obj.error, obj.sender, obj.receiver)
|
|
167
|
+
}
|
|
168
|
+
else
|
|
169
|
+
throw new Error("invalid object: not of any known type")
|
|
170
|
+
}
|
|
171
|
+
}
|