Browse Source

fix

master
peter 5 years ago
parent
commit
41a5d14fd8

+ 19
- 0
lib/RPCaller.min.js
File diff suppressed because it is too large
View File


+ 96
- 0
lib/src/backend/RPCSocketServer.d.ts View File

1
+import { Socket } from "./RPCSocketServer";
2
+declare type rpcType = 'hook' | 'unhook' | 'call';
3
+declare type visibility = 'public' | 'private';
4
+export declare type Outcome = "Success" | "Error";
5
+export declare class Response {
6
+    message?: string | undefined;
7
+    constructor(message?: string | undefined);
8
+}
9
+export declare class SuccessResponse extends Response {
10
+    result: Outcome;
11
+    constructor(message?: string);
12
+}
13
+export declare class ErrorResponse extends Response {
14
+    result: Outcome;
15
+    constructor(message?: string);
16
+}
17
+export declare class SubscriptionResponse extends SuccessResponse {
18
+    uid: string;
19
+    constructor(uid: string, message?: string);
20
+}
21
+export declare type UnhookFunction = (uid: string) => Promise<SuccessResponse | ErrorResponse>;
22
+export declare type callbackFunction = (...args: any[]) => Promise<SubscriptionResponse | ErrorResponse>;
23
+export declare type AsyncFunction = (...args: any[]) => Promise<any>;
24
+export interface RPCExporter {
25
+    name: string;
26
+    exportRPCs(): socketioRPC[];
27
+}
28
+declare type baseRPC = {
29
+    type: rpcType;
30
+    name: string;
31
+    visibility: visibility;
32
+};
33
+declare type hookRPC = baseRPC & {
34
+    type: 'hook';
35
+    func: callbackFunction;
36
+    unhook: UnhookFunction;
37
+};
38
+declare type unhookRPC = baseRPC & {
39
+    type: 'unhook';
40
+    func: UnhookFunction;
41
+};
42
+declare type callRPC = baseRPC & {
43
+    type: 'call';
44
+    func: (...args: any[]) => Promise<any>;
45
+};
46
+export declare type socketioRPC = callRPC | unhookRPC | hookRPC;
47
+export declare type baseInfo = {
48
+    owner: string;
49
+    argNames: string[];
50
+};
51
+declare type HookInfo = baseRPC & baseInfo & {
52
+    type: 'hook';
53
+    generator: (socket: any) => callbackFunction;
54
+    unhook: UnhookFunction;
55
+};
56
+declare type UnhookInfo = baseRPC & baseInfo & {
57
+    type: 'unhook';
58
+    func: UnhookFunction;
59
+};
60
+declare type CallInfo = baseRPC & baseInfo & {
61
+    type: 'call';
62
+    func: AsyncFunction;
63
+};
64
+declare type RpcInfo = HookInfo | UnhookInfo | CallInfo;
65
+export declare type ExtendedRpcInfo = RpcInfo & {
66
+    uniqueName: string;
67
+};
68
+export declare const rpcToRpcinfo: (rpc: socketioRPC, owner: string) => RpcInfo;
69
+export declare const rpcHooker: (socket: Socket, owner: string, RPCs: socketioRPC[], makeUnique?: boolean) => ExtendedRpcInfo[];
70
+declare type OnFunction = (type: 'error' | 'close', f: (e?: any) => void) => Socket;
71
+export declare type Socket = {
72
+    port: number;
73
+    hook: (rpcname: string, ...args: any[]) => Socket;
74
+    unhook: (rpcname: string) => Socket;
75
+    call: (rpcname: string, ...args: any[]) => Promise<any>;
76
+    fire: (rpcname: string, ...args: any[]) => Promise<any>;
77
+    on: OnFunction;
78
+    destroy: () => void;
79
+    close: () => void;
80
+};
81
+export declare type RPCSocketConf = {
82
+    connectionHandler: (socket: Socket) => void;
83
+    errorHandler: (socket: Socket) => (error: any) => void;
84
+    closeHandler: (socket: Socket) => () => void;
85
+};
86
+export declare class RPCSocketServer {
87
+    private port;
88
+    private rpcExporters;
89
+    private conf;
90
+    private io;
91
+    private wsServer;
92
+    constructor(port: number, rpcExporters?: RPCExporter[], conf?: RPCSocketConf);
93
+    private startWebsocket;
94
+    protected initApis(socket: any): void;
95
+}
96
+export {};

+ 152
- 0
lib/src/backend/RPCSocketServer.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+const http = require("http");
4
+const bsock = require("bsock");
5
+const uuid = require("uuid/v4");
6
+/* Responses */
7
+class Response {
8
+    constructor(message) {
9
+        this.message = message;
10
+    }
11
+}
12
+exports.Response = Response;
13
+class SuccessResponse extends Response {
14
+    constructor(message) {
15
+        super(message);
16
+        this.result = "Success";
17
+    }
18
+}
19
+exports.SuccessResponse = SuccessResponse;
20
+class ErrorResponse extends Response {
21
+    constructor(message = "Unknown error") {
22
+        super(message);
23
+        this.result = "Error";
24
+    }
25
+}
26
+exports.ErrorResponse = ErrorResponse;
27
+class SubscriptionResponse extends SuccessResponse {
28
+    constructor(uid, message) {
29
+        super(message);
30
+        this.uid = uid;
31
+    }
32
+}
33
+exports.SubscriptionResponse = SubscriptionResponse;
34
+exports.rpcToRpcinfo = (rpc, owner) => {
35
+    switch (rpc.type) {
36
+        case "call":
37
+            return {
38
+                owner: owner,
39
+                argNames: extractArgs(rpc.func),
40
+                type: rpc.type,
41
+                visibility: rpc.visibility,
42
+                name: rpc.name,
43
+                func: rpc.func,
44
+            };
45
+        case "unhook":
46
+            return {
47
+                owner: owner,
48
+                argNames: extractArgs(rpc.func),
49
+                type: rpc.type,
50
+                visibility: rpc.visibility,
51
+                name: rpc.name,
52
+                func: rpc.func,
53
+            };
54
+        case "hook":
55
+            const generator = hookGenerator(rpc);
56
+            return {
57
+                owner: owner,
58
+                argNames: extractArgs(generator(undefined)),
59
+                type: rpc.type,
60
+                visibility: rpc.visibility,
61
+                name: rpc.name,
62
+                unhook: rpc.unhook,
63
+                generator: generator,
64
+            };
65
+    }
66
+};
67
+exports.rpcHooker = (socket, owner, RPCs, makeUnique = true) => {
68
+    const suffix = makeUnique ? "-" + uuid().substr(0, 4) : "";
69
+    return RPCs.map(rpc => exports.rpcToRpcinfo(rpc, owner))
70
+        .map(info => {
71
+        const ret = info;
72
+        ret.uniqueName = info.name + suffix;
73
+        switch (info.type) {
74
+            case "hook":
75
+                socket.hook(ret.uniqueName, info.generator(socket));
76
+                break;
77
+            default:
78
+                socket.hook(ret.uniqueName, info.func);
79
+        }
80
+        socket.on('close', () => socket.unhook(info.name));
81
+        return ret;
82
+    });
83
+};
84
+const hookGenerator = (rpc) => {
85
+    const argsArr = extractArgs(rpc.func);
86
+    argsArr.pop();
87
+    const args = argsArr.join(',');
88
+    return eval(`(socket) => async (` + args + `) => { 
89
+        const res = await rpc.func(` + args + (args.length !== 0 ? ',' : '') + ` (x) => {
90
+            socket.call(res.uid, x)
91
+        })
92
+        if(res.result == 'Success'){
93
+            socket.on('close', async () => {
94
+                const unhookRes = await rpc.unhook(res.uid)
95
+                console.log("Specific close handler for", rpc.name, res.uid, unhookRes)
96
+            })
97
+
98
+        }
99
+        return res
100
+    }`);
101
+};
102
+const extractArgs = (f) => {
103
+    let fn = String(f);
104
+    let args = fn.substr(0, fn.indexOf(")"));
105
+    args = args.substr(fn.indexOf("(") + 1);
106
+    let ret = args.split(",");
107
+    return ret;
108
+};
109
+class RPCSocketServer {
110
+    constructor(port, rpcExporters = [], conf = {
111
+        errorHandler: (socket) => (error) => { socket.destroy(); console.error(error); },
112
+        closeHandler: (socket) => () => { console.log("Socket closing"); },
113
+        connectionHandler: (socket) => { console.log("New websocket connection in port " + socket.port); }
114
+    }) {
115
+        this.port = port;
116
+        this.rpcExporters = rpcExporters;
117
+        this.conf = conf;
118
+        this.io = bsock.createServer();
119
+        this.wsServer = http.createServer();
120
+        this.startWebsocket();
121
+    }
122
+    startWebsocket() {
123
+        try {
124
+            this.io.attach(this.wsServer);
125
+            this.io.on('socket', (socket) => {
126
+                socket.on('error', this.conf.errorHandler(socket));
127
+                socket.on('close', this.conf.closeHandler(socket));
128
+                this.initApis(socket);
129
+            });
130
+            this.wsServer.listen(this.port);
131
+        }
132
+        catch (e) {
133
+            //@ts-ignore
134
+            this.errorHandler(undefined)("Unable to connect to socket");
135
+        }
136
+    }
137
+    initApis(socket) {
138
+        const adminRPCs = [
139
+            {
140
+                name: 'info',
141
+                type: 'call',
142
+                visibility: 'private',
143
+                func: async () => rpcInfos
144
+            }
145
+        ];
146
+        const rpcInfos = [
147
+            ...exports.rpcHooker(socket, "Admin", adminRPCs, false),
148
+            ...this.rpcExporters.flatMap(exporter => exports.rpcHooker(socket, exporter.name, exporter.exportRPCs()))
149
+        ];
150
+    }
151
+}
152
+exports.RPCSocketServer = RPCSocketServer;

+ 20
- 0
lib/src/frontend/RPCaller.d.ts View File

1
+declare type RPCReceiver = {
2
+    [RPCGroup in string]: any;
3
+};
4
+/**
5
+ * Dynamic library to communicate with FrontblockService remotely
6
+ *
7
+ * This will be automatically injected into the webpages served by FrontblockService
8
+ * Will ask it's service for available RPCs and parse them into methods of this object
9
+ * for convenient access.
10
+ */
11
+export declare class RPCaller implements RPCReceiver {
12
+    private socket;
13
+    constructor(port: number, server: string, tls?: boolean);
14
+    connect(): Promise<void>;
15
+    info(): Promise<any>;
16
+    private callGenerator;
17
+    private hookGenerator;
18
+    private unhookGenerator;
19
+}
20
+export {};

+ 71
- 0
lib/src/frontend/RPCaller.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var bsock = require('bsock');
4
+//fix args with defaults like "force = true" -> "force"
5
+function stripAfterEquals(str) {
6
+    return str.split("=")[0];
7
+}
8
+/**
9
+ * Dynamic library to communicate with FrontblockService remotely
10
+ *
11
+ * This will be automatically injected into the webpages served by FrontblockService
12
+ * Will ask it's service for available RPCs and parse them into methods of this object
13
+ * for convenient access.
14
+ */
15
+class RPCaller {
16
+    constructor(port, server, tls = false) {
17
+        this.socket = bsock.connect(port, server, tls);
18
+    }
19
+    async connect() {
20
+        const info = await this.info();
21
+        info.forEach(i => {
22
+            let f;
23
+            switch (i.type) {
24
+                case 'call':
25
+                    f = this.callGenerator(i.uniqueName, i.argNames);
26
+                    break;
27
+                case 'hook':
28
+                    f = this.hookGenerator(i.uniqueName, i.argNames);
29
+                    break;
30
+                case 'unhook':
31
+                    f = this.unhookGenerator(i.uniqueName, i.argNames);
32
+                    break;
33
+            }
34
+            if (this[i.owner] == null)
35
+                this[i.owner] = {};
36
+            this[i.owner][i.name] = f;
37
+            this[i.owner][i.name].bind(this);
38
+        });
39
+    }
40
+    async info() {
41
+        return await this.socket.call('info');
42
+    }
43
+    callGenerator(fnName, fnArgs) {
44
+        const headerArgs = fnArgs.join(",");
45
+        const argParams = fnArgs.map(stripAfterEquals).join(",");
46
+        return eval('( () => async (' + headerArgs + ') => { return await this.socket.call("' + fnName + '", ' + argParams + ')} )()');
47
+    }
48
+    hookGenerator(fnName, fnArgs) {
49
+        const headerArgs = fnArgs.join(",");
50
+        const argParams = fnArgs.map(stripAfterEquals).join(",");
51
+        return eval(`( () => async (` + headerArgs + (headerArgs.length !== 0 ? "," : "") + ` callback) => {
52
+                            const r = await this.socket.call("` + fnName + `", ` + argParams + `)
53
+                            if(r.uid != null){
54
+                                this.socket.hook(res.uid, callback)
55
+                            }
56
+                            return res
57
+                        } )()`);
58
+    }
59
+    unhookGenerator(fnName, fnArgs) {
60
+        const headerArgs = fnArgs.join(",");
61
+        const argParams = fnArgs.map(stripAfterEquals).join(",");
62
+        if (fnArgs.length != 1)
63
+            console.error("UnhookFunction", fnName, "specified more than one argument: (" + headerArgs + ")");
64
+        return eval(`( () => async (` + headerArgs + `) => {
65
+                            const r = await this.socket.call("` + fnName + `", ` + argParams + `)
66
+                            this.socket.unhook(` + argParams + `)
67
+                            return res
68
+                        } )()`);
69
+    }
70
+}
71
+exports.RPCaller = RPCaller;

+ 1
- 0
lib/test/test.d.ts View File

1
+export {};

+ 19
- 0
lib/test/test.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+const RPCSocketServer_1 = require("../src/backend/RPCSocketServer");
4
+//@ts-ignore
5
+const RPCaller_1 = require("../src/frontend/RPCaller");
6
+new RPCSocketServer_1.RPCSocketServer(20000, [{
7
+        name: "HelloWorldRPCGroup",
8
+        exportRPCs: () => [{
9
+                type: 'call',
10
+                name: 'echo',
11
+                func: async (s) => s,
12
+                visibility: 'private'
13
+            }]
14
+    }]);
15
+const caller = new RPCaller_1.RPCaller(20000, 'localhost');
16
+caller.connect().then(_ => {
17
+    caller.info().then(console.log);
18
+    caller["HelloWorldRPCGroup"].echo("x").then(console.log);
19
+});

+ 1
- 0
node_modules/.bin/uuid View File

1
+../uuid/bin/uuid

+ 5
- 0
node_modules/uuid/AUTHORS View File

1
+Robert Kieffer <robert@broofa.com>
2
+Christoph Tavan <dev@tavan.de>
3
+AJ ONeal <coolaj86@gmail.com>
4
+Vincent Voyer <vincent@zeroload.net>
5
+Roman Shtylman <shtylman@gmail.com>

+ 112
- 0
node_modules/uuid/CHANGELOG.md View File

1
+# Changelog
2
+
3
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+### [3.3.3](https://github.com/kelektiv/node-uuid/compare/v3.3.2...v3.3.3) (2019-08-19)
6
+
7
+<a name="3.3.2"></a>
8
+## [3.3.2](https://github.com/kelektiv/node-uuid/compare/v3.3.1...v3.3.2) (2018-06-28)
9
+
10
+
11
+### Bug Fixes
12
+
13
+* typo ([305d877](https://github.com/kelektiv/node-uuid/commit/305d877))
14
+
15
+
16
+
17
+<a name="3.3.1"></a>
18
+## [3.3.1](https://github.com/kelektiv/node-uuid/compare/v3.3.0...v3.3.1) (2018-06-28)
19
+
20
+
21
+### Bug Fixes
22
+
23
+* fix [#284](https://github.com/kelektiv/node-uuid/issues/284) by setting function name in try-catch ([f2a60f2](https://github.com/kelektiv/node-uuid/commit/f2a60f2))
24
+
25
+
26
+
27
+<a name="3.3.0"></a>
28
+# [3.3.0](https://github.com/kelektiv/node-uuid/compare/v3.2.1...v3.3.0) (2018-06-22)
29
+
30
+
31
+### Bug Fixes
32
+
33
+* assignment to readonly property to allow running in strict mode ([#270](https://github.com/kelektiv/node-uuid/issues/270)) ([d062fdc](https://github.com/kelektiv/node-uuid/commit/d062fdc))
34
+* fix [#229](https://github.com/kelektiv/node-uuid/issues/229) ([c9684d4](https://github.com/kelektiv/node-uuid/commit/c9684d4))
35
+* Get correct version of IE11 crypto ([#274](https://github.com/kelektiv/node-uuid/issues/274)) ([153d331](https://github.com/kelektiv/node-uuid/commit/153d331))
36
+* mem issue when generating uuid ([#267](https://github.com/kelektiv/node-uuid/issues/267)) ([c47702c](https://github.com/kelektiv/node-uuid/commit/c47702c))
37
+
38
+### Features
39
+
40
+* enforce Conventional Commit style commit messages ([#282](https://github.com/kelektiv/node-uuid/issues/282)) ([cc9a182](https://github.com/kelektiv/node-uuid/commit/cc9a182))
41
+
42
+
43
+<a name="3.2.1"></a>
44
+## [3.2.1](https://github.com/kelektiv/node-uuid/compare/v3.2.0...v3.2.1) (2018-01-16)
45
+
46
+
47
+### Bug Fixes
48
+
49
+* use msCrypto if available. Fixes [#241](https://github.com/kelektiv/node-uuid/issues/241) ([#247](https://github.com/kelektiv/node-uuid/issues/247)) ([1fef18b](https://github.com/kelektiv/node-uuid/commit/1fef18b))
50
+
51
+
52
+
53
+<a name="3.2.0"></a>
54
+# [3.2.0](https://github.com/kelektiv/node-uuid/compare/v3.1.0...v3.2.0) (2018-01-16)
55
+
56
+
57
+### Bug Fixes
58
+
59
+* remove mistakenly added typescript dependency, rollback version (standard-version will auto-increment) ([09fa824](https://github.com/kelektiv/node-uuid/commit/09fa824))
60
+* use msCrypto if available. Fixes [#241](https://github.com/kelektiv/node-uuid/issues/241) ([#247](https://github.com/kelektiv/node-uuid/issues/247)) ([1fef18b](https://github.com/kelektiv/node-uuid/commit/1fef18b))
61
+
62
+
63
+### Features
64
+
65
+* Add v3 Support ([#217](https://github.com/kelektiv/node-uuid/issues/217)) ([d94f726](https://github.com/kelektiv/node-uuid/commit/d94f726))
66
+
67
+
68
+# [3.1.0](https://github.com/kelektiv/node-uuid/compare/v3.1.0...v3.0.1) (2017-06-17)
69
+
70
+### Bug Fixes
71
+
72
+* (fix) Add .npmignore file to exclude test/ and other non-essential files from packing. (#183)
73
+* Fix typo (#178)
74
+* Simple typo fix (#165)
75
+
76
+### Features
77
+* v5 support in CLI (#197)
78
+* V5 support (#188)
79
+
80
+
81
+# 3.0.1 (2016-11-28)
82
+
83
+* split uuid versions into separate files
84
+
85
+
86
+# 3.0.0 (2016-11-17)
87
+
88
+* remove .parse and .unparse
89
+
90
+
91
+# 2.0.0
92
+
93
+* Removed uuid.BufferClass
94
+
95
+
96
+# 1.4.0
97
+
98
+* Improved module context detection
99
+* Removed public RNG functions
100
+
101
+
102
+# 1.3.2
103
+
104
+* Improve tests and handling of v1() options (Issue #24)
105
+* Expose RNG option to allow for perf testing with different generators
106
+
107
+
108
+# 1.3.0
109
+
110
+* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!
111
+* Support for node.js crypto API
112
+* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code

+ 21
- 0
node_modules/uuid/LICENSE.md View File

1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2010-2016 Robert Kieffer and other contributors
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.

+ 293
- 0
node_modules/uuid/README.md View File

1
+<!--
2
+  -- This file is auto-generated from README_js.md. Changes should be made there.
3
+  -->
4
+
5
+# uuid [![Build Status](https://secure.travis-ci.org/kelektiv/node-uuid.svg?branch=master)](http://travis-ci.org/kelektiv/node-uuid) #
6
+
7
+Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.
8
+
9
+Features:
10
+
11
+* Support for version 1, 3, 4 and 5 UUIDs
12
+* Cross-platform
13
+* Uses cryptographically-strong random number APIs (when available)
14
+* Zero-dependency, small footprint (... but not [this small](https://gist.github.com/982883))
15
+
16
+[**Deprecation warning**: The use of `require('uuid')` is deprecated and will not be
17
+supported after version 3.x of this module.  Instead, use `require('uuid/[v1|v3|v4|v5]')` as shown in the examples below.]
18
+
19
+## Quickstart - CommonJS (Recommended)
20
+
21
+```shell
22
+npm install uuid
23
+```
24
+
25
+Then generate your uuid version of choice ...
26
+
27
+Version 1 (timestamp):
28
+
29
+```javascript
30
+const uuidv1 = require('uuid/v1');
31
+uuidv1(); // ⇨ '2c5ea4c0-4067-11e9-8bad-9b1deb4d3b7d'
32
+
33
+```
34
+
35
+Version 3 (namespace):
36
+
37
+```javascript
38
+const uuidv3 = require('uuid/v3');
39
+
40
+// ... using predefined DNS namespace (for domain names)
41
+uuidv3('hello.example.com', uuidv3.DNS); // ⇨ '9125a8dc-52ee-365b-a5aa-81b0b3681cf6'
42
+
43
+// ... using predefined URL namespace (for, well, URLs)
44
+uuidv3('http://example.com/hello', uuidv3.URL); // ⇨ 'c6235813-3ba4-3801-ae84-e0a6ebb7d138'
45
+
46
+// ... using a custom namespace
47
+//
48
+// Note: Custom namespaces should be a UUID string specific to your application!
49
+// E.g. the one here was generated using this modules `uuid` CLI.
50
+const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
51
+uuidv3('Hello, World!', MY_NAMESPACE); // ⇨ 'e8b5a51d-11c8-3310-a6ab-367563f20686'
52
+
53
+```
54
+
55
+Version 4 (random):
56
+
57
+```javascript
58
+const uuidv4 = require('uuid/v4');
59
+uuidv4(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'
60
+
61
+```
62
+
63
+Version 5 (namespace):
64
+
65
+```javascript
66
+const uuidv5 = require('uuid/v5');
67
+
68
+// ... using predefined DNS namespace (for domain names)
69
+uuidv5('hello.example.com', uuidv5.DNS); // ⇨ 'fdda765f-fc57-5604-a269-52a7df8164ec'
70
+
71
+// ... using predefined URL namespace (for, well, URLs)
72
+uuidv5('http://example.com/hello', uuidv5.URL); // ⇨ '3bbcee75-cecc-5b56-8031-b6641c1ed1f1'
73
+
74
+// ... using a custom namespace
75
+//
76
+// Note: Custom namespaces should be a UUID string specific to your application!
77
+// E.g. the one here was generated using this modules `uuid` CLI.
78
+const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
79
+uuidv5('Hello, World!', MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681'
80
+
81
+```
82
+
83
+## Quickstart - Browser-ready Versions
84
+
85
+Browser-ready versions of this module are available via [wzrd.in](https://github.com/jfhbrook/wzrd.in).
86
+
87
+For version 1 uuids:
88
+
89
+```html
90
+<script src="http://wzrd.in/standalone/uuid%2Fv1@latest"></script>
91
+<script>
92
+uuidv1(); // -> v1 UUID
93
+</script>
94
+```
95
+
96
+For version 3 uuids:
97
+
98
+```html
99
+<script src="http://wzrd.in/standalone/uuid%2Fv3@latest"></script>
100
+<script>
101
+uuidv3('http://example.com/hello', uuidv3.URL); // -> v3 UUID
102
+</script>
103
+```
104
+
105
+For version 4 uuids:
106
+
107
+```html
108
+<script src="http://wzrd.in/standalone/uuid%2Fv4@latest"></script>
109
+<script>
110
+uuidv4(); // -> v4 UUID
111
+</script>
112
+```
113
+
114
+For version 5 uuids:
115
+
116
+```html
117
+<script src="http://wzrd.in/standalone/uuid%2Fv5@latest"></script>
118
+<script>
119
+uuidv5('http://example.com/hello', uuidv5.URL); // -> v5 UUID
120
+</script>
121
+```
122
+
123
+## API
124
+
125
+### Version 1
126
+
127
+```javascript
128
+const uuidv1 = require('uuid/v1');
129
+
130
+// Incantations
131
+uuidv1();
132
+uuidv1(options);
133
+uuidv1(options, buffer, offset);
134
+```
135
+
136
+Generate and return a RFC4122 v1 (timestamp-based) UUID.
137
+
138
+* `options` - (Object) Optional uuid state to apply. Properties may include:
139
+
140
+  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID.  See note 1.
141
+  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.
142
+  * `msecs` - (Number) Time in milliseconds since unix Epoch.  Default: The current time is used.
143
+  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.
144
+
145
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
146
+* `offset` - (Number) Starting index in `buffer` at which to begin writing.
147
+
148
+Returns `buffer`, if specified, otherwise the string form of the UUID
149
+
150
+Note: The default [node id](https://tools.ietf.org/html/rfc4122#section-4.1.6) (the last 12 digits in the UUID) is generated once, randomly, on process startup, and then remains unchanged for the duration of the process.
151
+
152
+Example: Generate string UUID with fully-specified options
153
+
154
+```javascript
155
+const v1options = {
156
+  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
157
+  clockseq: 0x1234,
158
+  msecs: new Date('2011-11-01').getTime(),
159
+  nsecs: 5678
160
+};
161
+uuidv1(v1options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'
162
+
163
+```
164
+
165
+Example: In-place generation of two binary IDs
166
+
167
+```javascript
168
+// Generate two ids in an array
169
+const arr = new Array();
170
+uuidv1(null, arr, 0);  // ⇨ [ 44, 94, 164, 192, 64, 103, 17, 233, 146, 52, 155, 29, 235, 77, 59, 125 ]
171
+uuidv1(null, arr, 16); // ⇨ [ 44, 94, 164, 192, 64, 103, 17, 233, 146, 52, 155, 29, 235, 77, 59, 125, 44, 94, 164, 193, 64, 103, 17, 233, 146, 52, 155, 29, 235, 77, 59, 125 ]
172
+
173
+```
174
+
175
+### Version 3
176
+
177
+```javascript
178
+const uuidv3 = require('uuid/v3');
179
+
180
+// Incantations
181
+uuidv3(name, namespace);
182
+uuidv3(name, namespace, buffer);
183
+uuidv3(name, namespace, buffer, offset);
184
+```
185
+
186
+Generate and return a RFC4122 v3 UUID.
187
+
188
+* `name` - (String | Array[]) "name" to create UUID with
189
+* `namespace` - (String | Array[]) "namespace" UUID either as a String or Array[16] of byte values
190
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
191
+* `offset` - (Number) Starting index in `buffer` at which to begin writing. Default = 0
192
+
193
+Returns `buffer`, if specified, otherwise the string form of the UUID
194
+
195
+Example:
196
+
197
+```javascript
198
+uuidv3('hello world', MY_NAMESPACE);  // ⇨ '042ffd34-d989-321c-ad06-f60826172424'
199
+
200
+```
201
+
202
+### Version 4
203
+
204
+```javascript
205
+const uuidv4 = require('uuid/v4')
206
+
207
+// Incantations
208
+uuidv4();
209
+uuidv4(options);
210
+uuidv4(options, buffer, offset);
211
+```
212
+
213
+Generate and return a RFC4122 v4 UUID.
214
+
215
+* `options` - (Object) Optional uuid state to apply. Properties may include:
216
+  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values
217
+  * `rng` - (Function) Random # generator function that returns an Array[16] of byte values (0-255)
218
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
219
+* `offset` - (Number) Starting index in `buffer` at which to begin writing.
220
+
221
+Returns `buffer`, if specified, otherwise the string form of the UUID
222
+
223
+Example: Generate string UUID with predefined `random` values
224
+
225
+```javascript
226
+const v4options = {
227
+  random: [
228
+    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,
229
+    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36
230
+  ]
231
+};
232
+uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'
233
+
234
+```
235
+
236
+Example: Generate two IDs in a single buffer
237
+
238
+```javascript
239
+const buffer = new Array();
240
+uuidv4(null, buffer, 0);  // ⇨ [ 155, 29, 235, 77, 59, 125, 75, 173, 155, 221, 43, 13, 123, 61, 203, 109 ]
241
+uuidv4(null, buffer, 16); // ⇨ [ 155, 29, 235, 77, 59, 125, 75, 173, 155, 221, 43, 13, 123, 61, 203, 109, 27, 157, 107, 205, 187, 253, 75, 45, 155, 93, 171, 141, 251, 189, 75, 237 ]
242
+
243
+```
244
+
245
+### Version 5
246
+
247
+```javascript
248
+const uuidv5 = require('uuid/v5');
249
+
250
+// Incantations
251
+uuidv5(name, namespace);
252
+uuidv5(name, namespace, buffer);
253
+uuidv5(name, namespace, buffer, offset);
254
+```
255
+
256
+Generate and return a RFC4122 v5 UUID.
257
+
258
+* `name` - (String | Array[]) "name" to create UUID with
259
+* `namespace` - (String | Array[]) "namespace" UUID either as a String or Array[16] of byte values
260
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
261
+* `offset` - (Number) Starting index in `buffer` at which to begin writing. Default = 0
262
+
263
+Returns `buffer`, if specified, otherwise the string form of the UUID
264
+
265
+Example:
266
+
267
+```javascript
268
+uuidv5('hello world', MY_NAMESPACE);  // ⇨ '9f282611-e0fd-5650-8953-89c8e342da0b'
269
+
270
+```
271
+
272
+## Command Line
273
+
274
+UUIDs can be generated from the command line with the `uuid` command.
275
+
276
+```shell
277
+$ uuid
278
+ddeb27fb-d9a0-4624-be4d-4615062daed4
279
+
280
+$ uuid v1
281
+02d37060-d446-11e7-a9fa-7bdae751ebe1
282
+```
283
+
284
+Type `uuid --help` for usage details
285
+
286
+## Testing
287
+
288
+```shell
289
+npm test
290
+```
291
+
292
+----
293
+Markdown generated from [README_js.md](README_js.md) by [![RunMD Logo](http://i.imgur.com/h0FVyzU.png)](https://github.com/broofa/runmd)

+ 65
- 0
node_modules/uuid/bin/uuid View File

1
+#!/usr/bin/env node
2
+var assert = require('assert');
3
+
4
+function usage() {
5
+  console.log('Usage:');
6
+  console.log('  uuid');
7
+  console.log('  uuid v1');
8
+  console.log('  uuid v3 <name> <namespace uuid>');
9
+  console.log('  uuid v4');
10
+  console.log('  uuid v5 <name> <namespace uuid>');
11
+  console.log('  uuid --help');
12
+  console.log('\nNote: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs defined by RFC4122');
13
+}
14
+
15
+var args = process.argv.slice(2);
16
+
17
+if (args.indexOf('--help') >= 0) {
18
+  usage();
19
+  process.exit(0);
20
+}
21
+var version = args.shift() || 'v4';
22
+
23
+switch (version) {
24
+  case 'v1':
25
+    var uuidV1 = require('../v1');
26
+    console.log(uuidV1());
27
+    break;
28
+
29
+  case 'v3':
30
+    var uuidV3 = require('../v3');
31
+
32
+    var name = args.shift();
33
+    var namespace = args.shift();
34
+    assert(name != null, 'v3 name not specified');
35
+    assert(namespace != null, 'v3 namespace not specified');
36
+
37
+    if (namespace == 'URL') namespace = uuidV3.URL;
38
+    if (namespace == 'DNS') namespace = uuidV3.DNS;
39
+
40
+    console.log(uuidV3(name, namespace));
41
+    break;
42
+
43
+  case 'v4':
44
+    var uuidV4 = require('../v4');
45
+    console.log(uuidV4());
46
+    break;
47
+
48
+  case 'v5':
49
+    var uuidV5 = require('../v5');
50
+
51
+    var name = args.shift();
52
+    var namespace = args.shift();
53
+    assert(name != null, 'v5 name not specified');
54
+    assert(namespace != null, 'v5 namespace not specified');
55
+
56
+    if (namespace == 'URL') namespace = uuidV5.URL;
57
+    if (namespace == 'DNS') namespace = uuidV5.DNS;
58
+
59
+    console.log(uuidV5(name, namespace));
60
+    break;
61
+
62
+  default:
63
+    usage();
64
+    process.exit(1);
65
+}

+ 8
- 0
node_modules/uuid/index.js View File

1
+var v1 = require('./v1');
2
+var v4 = require('./v4');
3
+
4
+var uuid = v4;
5
+uuid.v1 = v1;
6
+uuid.v4 = v4;
7
+
8
+module.exports = uuid;

+ 24
- 0
node_modules/uuid/lib/bytesToUuid.js View File

1
+/**
2
+ * Convert array of 16 byte values to UUID string format of the form:
3
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
4
+ */
5
+var byteToHex = [];
6
+for (var i = 0; i < 256; ++i) {
7
+  byteToHex[i] = (i + 0x100).toString(16).substr(1);
8
+}
9
+
10
+function bytesToUuid(buf, offset) {
11
+  var i = offset || 0;
12
+  var bth = byteToHex;
13
+  // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
14
+  return ([bth[buf[i++]], bth[buf[i++]], 
15
+	bth[buf[i++]], bth[buf[i++]], '-',
16
+	bth[buf[i++]], bth[buf[i++]], '-',
17
+	bth[buf[i++]], bth[buf[i++]], '-',
18
+	bth[buf[i++]], bth[buf[i++]], '-',
19
+	bth[buf[i++]], bth[buf[i++]],
20
+	bth[buf[i++]], bth[buf[i++]],
21
+	bth[buf[i++]], bth[buf[i++]]]).join('');
22
+}
23
+
24
+module.exports = bytesToUuid;

+ 216
- 0
node_modules/uuid/lib/md5-browser.js View File

1
+/*
2
+ * Browser-compatible JavaScript MD5
3
+ *
4
+ * Modification of JavaScript MD5
5
+ * https://github.com/blueimp/JavaScript-MD5
6
+ *
7
+ * Copyright 2011, Sebastian Tschan
8
+ * https://blueimp.net
9
+ *
10
+ * Licensed under the MIT license:
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Based on
14
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
15
+ * Digest Algorithm, as defined in RFC 1321.
16
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
17
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
18
+ * Distributed under the BSD License
19
+ * See http://pajhome.org.uk/crypt/md5 for more info.
20
+ */
21
+
22
+'use strict';
23
+
24
+function md5(bytes) {
25
+  if (typeof(bytes) == 'string') {
26
+    var msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
27
+    bytes = new Array(msg.length);
28
+    for (var i = 0; i < msg.length; i++) bytes[i] = msg.charCodeAt(i);
29
+  }
30
+
31
+  return md5ToHexEncodedArray(
32
+    wordsToMd5(
33
+      bytesToWords(bytes)
34
+      , bytes.length * 8)
35
+  );
36
+}
37
+
38
+
39
+/*
40
+* Convert an array of little-endian words to an array of bytes
41
+*/
42
+function md5ToHexEncodedArray(input) {
43
+  var i;
44
+  var x;
45
+  var output = [];
46
+  var length32 = input.length * 32;
47
+  var hexTab = '0123456789abcdef';
48
+  var hex;
49
+
50
+  for (i = 0; i < length32; i += 8) {
51
+    x = (input[i >> 5] >>> (i % 32)) & 0xFF;
52
+
53
+    hex = parseInt(hexTab.charAt((x >>> 4) & 0x0F) + hexTab.charAt(x & 0x0F), 16);
54
+
55
+    output.push(hex);
56
+  }
57
+  return output;
58
+}
59
+
60
+/*
61
+* Calculate the MD5 of an array of little-endian words, and a bit length.
62
+*/
63
+function wordsToMd5(x, len) {
64
+  /* append padding */
65
+  x[len >> 5] |= 0x80 << (len % 32);
66
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
67
+
68
+  var i;
69
+  var olda;
70
+  var oldb;
71
+  var oldc;
72
+  var oldd;
73
+  var a = 1732584193;
74
+  var b = -271733879;
75
+  var c = -1732584194;
76
+
77
+  var d = 271733878;
78
+
79
+  for (i = 0; i < x.length; i += 16) {
80
+    olda = a;
81
+    oldb = b;
82
+    oldc = c;
83
+    oldd = d;
84
+
85
+    a = md5ff(a, b, c, d, x[i], 7, -680876936);
86
+    d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
87
+    c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
88
+    b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
89
+    a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
90
+    d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
91
+    c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
92
+    b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
93
+    a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
94
+    d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
95
+    c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
96
+    b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
97
+    a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
98
+    d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
99
+    c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
100
+    b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
101
+
102
+    a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
103
+    d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
104
+    c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
105
+    b = md5gg(b, c, d, a, x[i], 20, -373897302);
106
+    a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
107
+    d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
108
+    c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
109
+    b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
110
+    a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
111
+    d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
112
+    c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
113
+    b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
114
+    a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
115
+    d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
116
+    c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
117
+    b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
118
+
119
+    a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
120
+    d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
121
+    c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
122
+    b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
123
+    a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
124
+    d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
125
+    c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
126
+    b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
127
+    a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
128
+    d = md5hh(d, a, b, c, x[i], 11, -358537222);
129
+    c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
130
+    b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
131
+    a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
132
+    d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
133
+    c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
134
+    b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
135
+
136
+    a = md5ii(a, b, c, d, x[i], 6, -198630844);
137
+    d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
138
+    c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
139
+    b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
140
+    a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
141
+    d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
142
+    c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
143
+    b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
144
+    a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
145
+    d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
146
+    c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
147
+    b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
148
+    a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
149
+    d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
150
+    c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
151
+    b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
152
+
153
+    a = safeAdd(a, olda);
154
+    b = safeAdd(b, oldb);
155
+    c = safeAdd(c, oldc);
156
+    d = safeAdd(d, oldd);
157
+  }
158
+  return [a, b, c, d];
159
+}
160
+
161
+/*
162
+* Convert an array bytes to an array of little-endian words
163
+* Characters >255 have their high-byte silently ignored.
164
+*/
165
+function bytesToWords(input) {
166
+  var i;
167
+  var output = [];
168
+  output[(input.length >> 2) - 1] = undefined;
169
+  for (i = 0; i < output.length; i += 1) {
170
+    output[i] = 0;
171
+  }
172
+  var length8 = input.length * 8;
173
+  for (i = 0; i < length8; i += 8) {
174
+    output[i >> 5] |= (input[(i / 8)] & 0xFF) << (i % 32);
175
+  }
176
+
177
+  return output;
178
+}
179
+
180
+/*
181
+* Add integers, wrapping at 2^32. This uses 16-bit operations internally
182
+* to work around bugs in some JS interpreters.
183
+*/
184
+function safeAdd(x, y) {
185
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
186
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
187
+  return (msw << 16) | (lsw & 0xFFFF);
188
+}
189
+
190
+/*
191
+* Bitwise rotate a 32-bit number to the left.
192
+*/
193
+function bitRotateLeft(num, cnt) {
194
+  return (num << cnt) | (num >>> (32 - cnt));
195
+}
196
+
197
+/*
198
+* These functions implement the four basic operations the algorithm uses.
199
+*/
200
+function md5cmn(q, a, b, x, s, t) {
201
+  return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
202
+}
203
+function md5ff(a, b, c, d, x, s, t) {
204
+  return md5cmn((b & c) | ((~b) & d), a, b, x, s, t);
205
+}
206
+function md5gg(a, b, c, d, x, s, t) {
207
+  return md5cmn((b & d) | (c & (~d)), a, b, x, s, t);
208
+}
209
+function md5hh(a, b, c, d, x, s, t) {
210
+  return md5cmn(b ^ c ^ d, a, b, x, s, t);
211
+}
212
+function md5ii(a, b, c, d, x, s, t) {
213
+  return md5cmn(c ^ (b | (~d)), a, b, x, s, t);
214
+}
215
+
216
+module.exports = md5;

+ 25
- 0
node_modules/uuid/lib/md5.js View File

1
+'use strict';
2
+
3
+var crypto = require('crypto');
4
+
5
+function md5(bytes) {
6
+  if (typeof Buffer.from === 'function') {
7
+    // Modern Buffer API
8
+    if (Array.isArray(bytes)) {
9
+      bytes = Buffer.from(bytes);
10
+    } else if (typeof bytes === 'string') {
11
+      bytes = Buffer.from(bytes, 'utf8');
12
+    }
13
+  } else {
14
+    // Pre-v4 Buffer API
15
+    if (Array.isArray(bytes)) {
16
+      bytes = new Buffer(bytes);
17
+    } else if (typeof bytes === 'string') {
18
+      bytes = new Buffer(bytes, 'utf8');
19
+    }
20
+  }
21
+
22
+  return crypto.createHash('md5').update(bytes).digest();
23
+}
24
+
25
+module.exports = md5;

+ 34
- 0
node_modules/uuid/lib/rng-browser.js View File

1
+// Unique ID creation requires a high quality random # generator.  In the
2
+// browser this is a little complicated due to unknown quality of Math.random()
3
+// and inconsistent support for the `crypto` API.  We do the best we can via
4
+// feature-detection
5
+
6
+// getRandomValues needs to be invoked in a context where "this" is a Crypto
7
+// implementation. Also, find the complete implementation of crypto on IE11.
8
+var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
9
+                      (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
10
+
11
+if (getRandomValues) {
12
+  // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
13
+  var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
14
+
15
+  module.exports = function whatwgRNG() {
16
+    getRandomValues(rnds8);
17
+    return rnds8;
18
+  };
19
+} else {
20
+  // Math.random()-based (RNG)
21
+  //
22
+  // If all else fails, use Math.random().  It's fast, but is of unspecified
23
+  // quality.
24
+  var rnds = new Array(16);
25
+
26
+  module.exports = function mathRNG() {
27
+    for (var i = 0, r; i < 16; i++) {
28
+      if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
29
+      rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
30
+    }
31
+
32
+    return rnds;
33
+  };
34
+}

+ 8
- 0
node_modules/uuid/lib/rng.js View File

1
+// Unique ID creation requires a high quality random # generator.  In node.js
2
+// this is pretty straight-forward - we use the crypto API.
3
+
4
+var crypto = require('crypto');
5
+
6
+module.exports = function nodeRNG() {
7
+  return crypto.randomBytes(16);
8
+};

+ 89
- 0
node_modules/uuid/lib/sha1-browser.js View File

1
+// Adapted from Chris Veness' SHA1 code at
2
+// http://www.movable-type.co.uk/scripts/sha1.html
3
+'use strict';
4
+
5
+function f(s, x, y, z) {
6
+  switch (s) {
7
+    case 0: return (x & y) ^ (~x & z);
8
+    case 1: return x ^ y ^ z;
9
+    case 2: return (x & y) ^ (x & z) ^ (y & z);
10
+    case 3: return x ^ y ^ z;
11
+  }
12
+}
13
+
14
+function ROTL(x, n) {
15
+  return (x << n) | (x>>> (32 - n));
16
+}
17
+
18
+function sha1(bytes) {
19
+  var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
20
+  var H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
21
+
22
+  if (typeof(bytes) == 'string') {
23
+    var msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
24
+    bytes = new Array(msg.length);
25
+    for (var i = 0; i < msg.length; i++) bytes[i] = msg.charCodeAt(i);
26
+  }
27
+
28
+  bytes.push(0x80);
29
+
30
+  var l = bytes.length/4 + 2;
31
+  var N = Math.ceil(l/16);
32
+  var M = new Array(N);
33
+
34
+  for (var i=0; i<N; i++) {
35
+    M[i] = new Array(16);
36
+    for (var j=0; j<16; j++) {
37
+      M[i][j] =
38
+        bytes[i * 64 + j * 4] << 24 |
39
+        bytes[i * 64 + j * 4 + 1] << 16 |
40
+        bytes[i * 64 + j * 4 + 2] << 8 |
41
+        bytes[i * 64 + j * 4 + 3];
42
+    }
43
+  }
44
+
45
+  M[N - 1][14] = ((bytes.length - 1) * 8) /
46
+    Math.pow(2, 32); M[N - 1][14] = Math.floor(M[N - 1][14]);
47
+  M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff;
48
+
49
+  for (var i=0; i<N; i++) {
50
+    var W = new Array(80);
51
+
52
+    for (var t=0; t<16; t++) W[t] = M[i][t];
53
+    for (var t=16; t<80; t++) {
54
+      W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
55
+    }
56
+
57
+    var a = H[0];
58
+    var b = H[1];
59
+    var c = H[2];
60
+    var d = H[3];
61
+    var e = H[4];
62
+
63
+    for (var t=0; t<80; t++) {
64
+      var s = Math.floor(t/20);
65
+      var T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0;
66
+      e = d;
67
+      d = c;
68
+      c = ROTL(b, 30) >>> 0;
69
+      b = a;
70
+      a = T;
71
+    }
72
+
73
+    H[0] = (H[0] + a) >>> 0;
74
+    H[1] = (H[1] + b) >>> 0;
75
+    H[2] = (H[2] + c) >>> 0;
76
+    H[3] = (H[3] + d) >>> 0;
77
+    H[4] = (H[4] + e) >>> 0;
78
+  }
79
+
80
+  return [
81
+    H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff,
82
+    H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff,
83
+    H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff,
84
+    H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff,
85
+    H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff
86
+  ];
87
+}
88
+
89
+module.exports = sha1;

+ 25
- 0
node_modules/uuid/lib/sha1.js View File

1
+'use strict';
2
+
3
+var crypto = require('crypto');
4
+
5
+function sha1(bytes) {
6
+  if (typeof Buffer.from === 'function') {
7
+    // Modern Buffer API
8
+    if (Array.isArray(bytes)) {
9
+      bytes = Buffer.from(bytes);
10
+    } else if (typeof bytes === 'string') {
11
+      bytes = Buffer.from(bytes, 'utf8');
12
+    }
13
+  } else {
14
+    // Pre-v4 Buffer API
15
+    if (Array.isArray(bytes)) {
16
+      bytes = new Buffer(bytes);
17
+    } else if (typeof bytes === 'string') {
18
+      bytes = new Buffer(bytes, 'utf8');
19
+    }
20
+  }
21
+
22
+  return crypto.createHash('sha1').update(bytes).digest();
23
+}
24
+
25
+module.exports = sha1;

+ 57
- 0
node_modules/uuid/lib/v35.js View File

1
+var bytesToUuid = require('./bytesToUuid');
2
+
3
+function uuidToBytes(uuid) {
4
+  // Note: We assume we're being passed a valid uuid string
5
+  var bytes = [];
6
+  uuid.replace(/[a-fA-F0-9]{2}/g, function(hex) {
7
+    bytes.push(parseInt(hex, 16));
8
+  });
9
+
10
+  return bytes;
11
+}
12
+
13
+function stringToBytes(str) {
14
+  str = unescape(encodeURIComponent(str)); // UTF8 escape
15
+  var bytes = new Array(str.length);
16
+  for (var i = 0; i < str.length; i++) {
17
+    bytes[i] = str.charCodeAt(i);
18
+  }
19
+  return bytes;
20
+}
21
+
22
+module.exports = function(name, version, hashfunc) {
23
+  var generateUUID = function(value, namespace, buf, offset) {
24
+    var off = buf && offset || 0;
25
+
26
+    if (typeof(value) == 'string') value = stringToBytes(value);
27
+    if (typeof(namespace) == 'string') namespace = uuidToBytes(namespace);
28
+
29
+    if (!Array.isArray(value)) throw TypeError('value must be an array of bytes');
30
+    if (!Array.isArray(namespace) || namespace.length !== 16) throw TypeError('namespace must be uuid string or an Array of 16 byte values');
31
+
32
+    // Per 4.3
33
+    var bytes = hashfunc(namespace.concat(value));
34
+    bytes[6] = (bytes[6] & 0x0f) | version;
35
+    bytes[8] = (bytes[8] & 0x3f) | 0x80;
36
+
37
+    if (buf) {
38
+      for (var idx = 0; idx < 16; ++idx) {
39
+        buf[off+idx] = bytes[idx];
40
+      }
41
+    }
42
+
43
+    return buf || bytesToUuid(bytes);
44
+  };
45
+
46
+  // Function#name is not settable on some platforms (#270)
47
+  try {
48
+    generateUUID.name = name;
49
+  } catch (err) {
50
+  }
51
+
52
+  // Pre-defined namespaces, per Appendix C
53
+  generateUUID.DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
54
+  generateUUID.URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
55
+
56
+  return generateUUID;
57
+};

+ 96
- 0
node_modules/uuid/package.json View File

1
+{
2
+  "_from": "uuid",
3
+  "_id": "uuid@3.3.3",
4
+  "_inBundle": false,
5
+  "_integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
6
+  "_location": "/uuid",
7
+  "_phantomChildren": {},
8
+  "_requested": {
9
+    "type": "tag",
10
+    "registry": true,
11
+    "raw": "uuid",
12
+    "name": "uuid",
13
+    "escapedName": "uuid",
14
+    "rawSpec": "",
15
+    "saveSpec": null,
16
+    "fetchSpec": "latest"
17
+  },
18
+  "_requiredBy": [
19
+    "#USER",
20
+    "/"
21
+  ],
22
+  "_resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
23
+  "_shasum": "4568f0216e78760ee1dbf3a4d2cf53e224112866",
24
+  "_spec": "uuid",
25
+  "_where": "/home/cake/rpclib",
26
+  "bin": {
27
+    "uuid": "./bin/uuid"
28
+  },
29
+  "browser": {
30
+    "./lib/rng.js": "./lib/rng-browser.js",
31
+    "./lib/sha1.js": "./lib/sha1-browser.js",
32
+    "./lib/md5.js": "./lib/md5-browser.js"
33
+  },
34
+  "bugs": {
35
+    "url": "https://github.com/kelektiv/node-uuid/issues"
36
+  },
37
+  "bundleDependencies": false,
38
+  "commitlint": {
39
+    "extends": [
40
+      "@commitlint/config-conventional"
41
+    ]
42
+  },
43
+  "contributors": [
44
+    {
45
+      "name": "Robert Kieffer",
46
+      "email": "robert@broofa.com"
47
+    },
48
+    {
49
+      "name": "Christoph Tavan",
50
+      "email": "dev@tavan.de"
51
+    },
52
+    {
53
+      "name": "AJ ONeal",
54
+      "email": "coolaj86@gmail.com"
55
+    },
56
+    {
57
+      "name": "Vincent Voyer",
58
+      "email": "vincent@zeroload.net"
59
+    },
60
+    {
61
+      "name": "Roman Shtylman",
62
+      "email": "shtylman@gmail.com"
63
+    }
64
+  ],
65
+  "deprecated": false,
66
+  "description": "RFC4122 (v1, v4, and v5) UUIDs",
67
+  "devDependencies": {
68
+    "@commitlint/cli": "8.1.0",
69
+    "@commitlint/config-conventional": "8.1.0",
70
+    "eslint": "6.2.0",
71
+    "husky": "3.0.4",
72
+    "mocha": "6.2.0",
73
+    "runmd": "1.2.1",
74
+    "standard-version": "7.0.0"
75
+  },
76
+  "homepage": "https://github.com/kelektiv/node-uuid#readme",
77
+  "keywords": [
78
+    "uuid",
79
+    "guid",
80
+    "rfc4122"
81
+  ],
82
+  "license": "MIT",
83
+  "name": "uuid",
84
+  "repository": {
85
+    "type": "git",
86
+    "url": "git+https://github.com/kelektiv/node-uuid.git"
87
+  },
88
+  "scripts": {
89
+    "commitmsg": "commitlint -E HUSKY_GIT_PARAMS",
90
+    "md": "runmd --watch --output=README.md README_js.md",
91
+    "prepare": "runmd --output=README.md README_js.md",
92
+    "release": "standard-version",
93
+    "test": "mocha test/test.js"
94
+  },
95
+  "version": "3.3.3"
96
+}

+ 109
- 0
node_modules/uuid/v1.js View File

1
+var rng = require('./lib/rng');
2
+var bytesToUuid = require('./lib/bytesToUuid');
3
+
4
+// **`v1()` - Generate time-based UUID**
5
+//
6
+// Inspired by https://github.com/LiosK/UUID.js
7
+// and http://docs.python.org/library/uuid.html
8
+
9
+var _nodeId;
10
+var _clockseq;
11
+
12
+// Previous uuid creation time
13
+var _lastMSecs = 0;
14
+var _lastNSecs = 0;
15
+
16
+// See https://github.com/broofa/node-uuid for API details
17
+function v1(options, buf, offset) {
18
+  var i = buf && offset || 0;
19
+  var b = buf || [];
20
+
21
+  options = options || {};
22
+  var node = options.node || _nodeId;
23
+  var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
24
+
25
+  // node and clockseq need to be initialized to random values if they're not
26
+  // specified.  We do this lazily to minimize issues related to insufficient
27
+  // system entropy.  See #189
28
+  if (node == null || clockseq == null) {
29
+    var seedBytes = rng();
30
+    if (node == null) {
31
+      // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
32
+      node = _nodeId = [
33
+        seedBytes[0] | 0x01,
34
+        seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
35
+      ];
36
+    }
37
+    if (clockseq == null) {
38
+      // Per 4.2.2, randomize (14 bit) clockseq
39
+      clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
40
+    }
41
+  }
42
+
43
+  // UUID timestamps are 100 nano-second units since the Gregorian epoch,
44
+  // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so
45
+  // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
46
+  // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
47
+  var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
48
+
49
+  // Per 4.2.1.2, use count of uuid's generated during the current clock
50
+  // cycle to simulate higher resolution clock
51
+  var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
52
+
53
+  // Time since last uuid creation (in msecs)
54
+  var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
55
+
56
+  // Per 4.2.1.2, Bump clockseq on clock regression
57
+  if (dt < 0 && options.clockseq === undefined) {
58
+    clockseq = clockseq + 1 & 0x3fff;
59
+  }
60
+
61
+  // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
62
+  // time interval
63
+  if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
64
+    nsecs = 0;
65
+  }
66
+
67
+  // Per 4.2.1.2 Throw error if too many uuids are requested
68
+  if (nsecs >= 10000) {
69
+    throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
70
+  }
71
+
72
+  _lastMSecs = msecs;
73
+  _lastNSecs = nsecs;
74
+  _clockseq = clockseq;
75
+
76
+  // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
77
+  msecs += 12219292800000;
78
+
79
+  // `time_low`
80
+  var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
81
+  b[i++] = tl >>> 24 & 0xff;
82
+  b[i++] = tl >>> 16 & 0xff;
83
+  b[i++] = tl >>> 8 & 0xff;
84
+  b[i++] = tl & 0xff;
85
+
86
+  // `time_mid`
87
+  var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
88
+  b[i++] = tmh >>> 8 & 0xff;
89
+  b[i++] = tmh & 0xff;
90
+
91
+  // `time_high_and_version`
92
+  b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
93
+  b[i++] = tmh >>> 16 & 0xff;
94
+
95
+  // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
96
+  b[i++] = clockseq >>> 8 | 0x80;
97
+
98
+  // `clock_seq_low`
99
+  b[i++] = clockseq & 0xff;
100
+
101
+  // `node`
102
+  for (var n = 0; n < 6; ++n) {
103
+    b[i + n] = node[n];
104
+  }
105
+
106
+  return buf ? buf : bytesToUuid(b);
107
+}
108
+
109
+module.exports = v1;

+ 4
- 0
node_modules/uuid/v3.js View File

1
+var v35 = require('./lib/v35.js');
2
+var md5 = require('./lib/md5');
3
+
4
+module.exports = v35('v3', 0x30, md5);

+ 29
- 0
node_modules/uuid/v4.js View File

1
+var rng = require('./lib/rng');
2
+var bytesToUuid = require('./lib/bytesToUuid');
3
+
4
+function v4(options, buf, offset) {
5
+  var i = buf && offset || 0;
6
+
7
+  if (typeof(options) == 'string') {
8
+    buf = options === 'binary' ? new Array(16) : null;
9
+    options = null;
10
+  }
11
+  options = options || {};
12
+
13
+  var rnds = options.random || (options.rng || rng)();
14
+
15
+  // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
16
+  rnds[6] = (rnds[6] & 0x0f) | 0x40;
17
+  rnds[8] = (rnds[8] & 0x3f) | 0x80;
18
+
19
+  // Copy bytes to buffer, if provided
20
+  if (buf) {
21
+    for (var ii = 0; ii < 16; ++ii) {
22
+      buf[i + ii] = rnds[ii];
23
+    }
24
+  }
25
+
26
+  return buf || bytesToUuid(rnds);
27
+}
28
+
29
+module.exports = v4;

+ 3
- 0
node_modules/uuid/v5.js View File

1
+var v35 = require('./lib/v35.js');
2
+var sha1 = require('./lib/sha1');
3
+module.exports = v35('v5', 0x50, sha1);

+ 5
- 0
package-lock.json View File

3944
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
3944
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
3945
       "dev": true
3945
       "dev": true
3946
     },
3946
     },
3947
+    "uuid": {
3948
+      "version": "3.3.3",
3949
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
3950
+      "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
3951
+    },
3947
     "v8-compile-cache": {
3952
     "v8-compile-cache": {
3948
       "version": "2.0.3",
3953
       "version": "2.0.3",
3949
       "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
3954
       "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",

+ 6
- 3
package.json View File

2
   "name": "rpclib",
2
   "name": "rpclib",
3
   "version": "1.0.0",
3
   "version": "1.0.0",
4
   "description": "",
4
   "description": "",
5
-  "main": "index.js",
6
   "scripts": {
5
   "scripts": {
7
-    "test": "echo \"Error: no test specified\" && exit 1"
6
+    "build": "npm run clean; npm run tsc; npm run webpack",
7
+    "tsc": "tsc",
8
+    "webpack": "webpack  --config src/frontend/webpack.prod.js --progress --colors",
9
+    "clean": "rm -rf lib"
8
   },
10
   },
9
   "author": "",
11
   "author": "",
10
   "license": "ISC",
12
   "license": "ISC",
19
     "webpack-cli": "^3.3.5"
21
     "webpack-cli": "^3.3.5"
20
   },
22
   },
21
   "dependencies": {
23
   "dependencies": {
22
-    "bsock": "^0.1.9"
24
+    "bsock": "^0.1.9",
25
+    "uuid": "^3.3.3"
23
   }
26
   }
24
 }
27
 }

src/backend/RPCExporter.ts → src/backend/RPCSocketServer.ts View File

1
-import { SubscriptionResponse, SuccessResponse, ErrorResponse } from "../../../../vendor/generic/Types";
1
+import http = require('http');
2
+import bsock = require('bsock');
3
+
2
 import * as uuid from "uuid/v4"
4
 import * as uuid from "uuid/v4"
5
+import { Socket } from "./RPCSocketServer"
3
 
6
 
4
 type rpcType = 'hook' | 'unhook' | 'call'
7
 type rpcType = 'hook' | 'unhook' | 'call'
5
 type visibility = 'public' | 'private'
8
 type visibility = 'public' | 'private'
6
 
9
 
7
 export type Outcome = "Success" | "Error"
10
 export type Outcome = "Success" | "Error"
8
 
11
 
12
+/* Responses */
13
+export class Response{
14
+    constructor(
15
+        public message?:string
16
+    ){}
17
+}
18
+
19
+export class SuccessResponse extends Response{
20
+    result:Outcome = "Success"
21
+
22
+    constructor(
23
+        message?:string
24
+    ){
25
+        super(message)
26
+    }
27
+}
28
+
29
+export class ErrorResponse extends Response{
30
+    result:Outcome = "Error"
31
+
32
+    constructor(
33
+        message: string = "Unknown error"
34
+    ){
35
+        super(message)
36
+    } 
37
+}
38
+
39
+export class SubscriptionResponse extends SuccessResponse{
40
+    constructor(
41
+        public uid: string,
42
+        message?:string
43
+    ){
44
+        super(message)
45
+    }
46
+}
9
 export type UnhookFunction = (uid:string) => Promise<SuccessResponse | ErrorResponse>
47
 export type UnhookFunction = (uid:string) => Promise<SuccessResponse | ErrorResponse>
10
 export type callbackFunction = (...args) => Promise<SubscriptionResponse | ErrorResponse>
48
 export type callbackFunction = (...args) => Promise<SubscriptionResponse | ErrorResponse>
11
 export type AsyncFunction = (...args) => Promise<any>
49
 export type AsyncFunction = (...args) => Promise<any>
98
     }
136
     }
99
 }
137
 }
100
 
138
 
101
-export const rpcHooker = (socket, owner:string, RPCs: socketioRPC[], makeUnique = true):ExtendedRpcInfo[] => {
139
+export const rpcHooker = (socket: Socket, owner:string, RPCs: socketioRPC[], makeUnique = true):ExtendedRpcInfo[] => {
102
     const suffix = makeUnique?"-"+uuid().substr(0,4):""
140
     const suffix = makeUnique?"-"+uuid().substr(0,4):""
103
     return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
141
     return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
104
     .map(info => {
142
     .map(info => {
137
     }`)
175
     }`)
138
 }
176
 }
139
 
177
 
140
-function extractArgs(f:Function):string[]{
178
+const extractArgs = (f:Function):string[] => {
141
     let fn = String(f)
179
     let fn = String(f)
142
     let args = fn.substr(0, fn.indexOf(")"))
180
     let args = fn.substr(0, fn.indexOf(")"))
143
     args = args.substr(fn.indexOf("(")+1)
181
     args = args.substr(fn.indexOf("(")+1)
144
     let ret = args.split(",")
182
     let ret = args.split(",")
145
     return ret
183
     return ret
184
+}
185
+
186
+
187
+type OnFunction = (type: 'error' | 'close', f: (e?:any)=>void) => Socket
188
+
189
+export type Socket = {
190
+    port: number
191
+    hook: (rpcname: string, ...args: any[]) => Socket
192
+    unhook: (rpcname:string) => Socket
193
+    call: (rpcname:string, ...args: any[]) => Promise<any>
194
+    fire: (rpcname:string, ...args: any[]) => Promise<any>
195
+    on: OnFunction
196
+    destroy: ()=>void
197
+    close: ()=>void
198
+}
199
+
200
+export type RPCSocketConf = {
201
+    connectionHandler: (socket:Socket) => void
202
+    errorHandler: (socket:Socket) => (error:any) => void
203
+    closeHandler: (socket:Socket) => () =>  void
204
+}
205
+
206
+export class RPCSocketServer{
207
+    
208
+    private io = bsock.createServer()
209
+    private wsServer = http.createServer()
210
+
211
+    constructor(
212
+        private port:number,
213
+        private rpcExporters: RPCExporter[] = [],
214
+        private conf: RPCSocketConf = {
215
+            errorHandler: (socket:Socket) => (error:any) => { socket.destroy(); console.error(error) },
216
+            closeHandler: (socket:Socket) => () => { console.log("Socket closing") },
217
+            connectionHandler: (socket:Socket) => { console.log("New websocket connection in port "+socket.port) }
218
+        }
219
+    ){
220
+        this.startWebsocket()
221
+    }
222
+
223
+    private startWebsocket(){
224
+        try{
225
+            this.io.attach(this.wsServer)
226
+            this.io.on('socket', (socket:Socket) => {
227
+                socket.on('error', this.conf.errorHandler(socket))
228
+                socket.on('close', this.conf.closeHandler(socket))
229
+                this.initApis(socket)
230
+            })
231
+            this.wsServer.listen(this.port)
232
+        }catch(e){
233
+            //@ts-ignore
234
+            this.errorHandler(undefined)("Unable to connect to socket")
235
+        }
236
+    }
237
+
238
+    protected initApis(socket){
239
+        const adminRPCs:socketioRPC[] = [
240
+            {
241
+                name: 'info',
242
+                type: 'call',
243
+                visibility: 'private',
244
+                func: async () => rpcInfos
245
+            }
246
+        ]
247
+
248
+        const rpcInfos:ExtendedRpcInfo[] = [
249
+            ...rpcHooker(socket, "Admin", adminRPCs, false),
250
+            ...this.rpcExporters.flatMap(exporter => rpcHooker(socket, exporter.name, exporter.exportRPCs()))
251
+        ]
252
+    }
146
 }
253
 }

src/frontend/RPCallable.ts → src/frontend/RPCaller.ts View File

1
-import { parseSubResponse, parseResponse } from "frontblock-generic/Types";
2
-import { ExtendedRpcInfo, UnhookFunction, callbackFunction, AsyncFunction } from "frontblock-generic/RPC";
1
+import { ExtendedRpcInfo, UnhookFunction, callbackFunction, AsyncFunction } from "../backend/RPCSocketServer";
3
 var bsock = require('bsock')
2
 var bsock = require('bsock')
4
 
3
 
5
 //fix args with defaults like "force = true" -> "force"
4
 //fix args with defaults like "force = true" -> "force"
7
     return str.split("=")[0]
6
     return str.split("=")[0]
8
 }
7
 }
9
 
8
 
9
+type RPCReceiver = {
10
+    [RPCGroup in string]: any
11
+}
12
+
10
 /**
13
 /**
11
  * Dynamic library to communicate with FrontblockService remotely
14
  * Dynamic library to communicate with FrontblockService remotely
12
  *
15
  *
14
  * Will ask it's service for available RPCs and parse them into methods of this object
17
  * Will ask it's service for available RPCs and parse them into methods of this object
15
  * for convenient access.
18
  * for convenient access.
16
  */
19
  */
17
-export class RPCallable{
20
+export class RPCaller implements RPCReceiver{
18
     private socket
21
     private socket
19
     
22
     
20
-    constructor(){
21
-        this.socket = bsock.connect(20000, 'localhost', false/*tls*/)
22
-        this.init()
23
+    constructor(port:number, server: string, tls: boolean = false){
24
+        this.socket = bsock.connect(port, server, tls)
23
     }
25
     }
24
 
26
 
25
-    // need this-context for eval-magic below 
26
-    // DO NOT REMOVE. They're not really unused
27
-    private parseSubResponse = parseSubResponse
28
-    private parseResponse = parseResponse
29
-
30
-    private async init(){
27
+    async connect(){
31
         const info:ExtendedRpcInfo[] = await this.info()
28
         const info:ExtendedRpcInfo[] = await this.info()
32
         info.forEach(i => {
29
         info.forEach(i => {
33
             let f: any
30
             let f: any
64
         const argParams = fnArgs.map(stripAfterEquals).join(",")
61
         const argParams = fnArgs.map(stripAfterEquals).join(",")
65
         return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
62
         return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
66
                             const r = await this.socket.call("`+fnName+`", `+argParams+`)
63
                             const r = await this.socket.call("`+fnName+`", `+argParams+`)
67
-                            const res = await this.parseSubResponse(r);
68
-                            if(res.uid != null){
64
+                            if(r.uid != null){
69
                                 this.socket.hook(res.uid, callback)
65
                                 this.socket.hook(res.uid, callback)
70
                             }
66
                             }
71
                             return res
67
                             return res
80
 
76
 
81
         return eval( `( () => async (`+headerArgs+`) => {
77
         return eval( `( () => async (`+headerArgs+`) => {
82
                             const r = await this.socket.call("`+fnName+`", `+argParams+`)
78
                             const r = await this.socket.call("`+fnName+`", `+argParams+`)
83
-                            const res = await this.parseResponse(r)
84
                             this.socket.unhook(`+argParams+`)
79
                             this.socket.unhook(`+argParams+`)
85
                             return res
80
                             return res
86
                         } )()` )
81
                         } )()` )
87
     }
82
     }
88
 
83
 
89
-}
90
-
91
-window['rpc'] = new RPCallable()
84
+}

+ 3
- 9
src/frontend/webpack.prod.js View File

4
 module.exports = {
4
 module.exports = {
5
   mode: 'production',
5
   mode: 'production',
6
   target: "web",
6
   target: "web",
7
-  entry: path.resolve(__dirname, 'module.ts'),
7
+  entry: path.resolve(__dirname, 'RPCaller.ts'),
8
   output: {
8
   output: {
9
-      path: path.resolve(__dirname, '../../dist'),
10
-      filename: 'FrontendPlugin.js',
9
+      path: path.resolve(__dirname, '../../lib'),
10
+      filename: 'RPCaller.min.js',
11
       libraryTarget: 'commonjs',
11
       libraryTarget: 'commonjs',
12
   },
12
   },
13
   resolve: {
13
   resolve: {
30
     ],
30
     ],
31
   },
31
   },
32
   externals: {
32
   externals: {
33
-    '@angular/core': '@angular/core',
34
-    '@angular/common': '@angular/common',
35
-    '@angular/router': '@angular/router',
36
-    '@angular/animations': '@angular/animations',
37
-    '@angular/forms': '@angular/forms',
38
-    '@clr/angular': '@clr/angular'
39
   }
33
   }
40
 }
34
 }

+ 19
- 0
test/test.ts View File

1
+import { RPCSocketServer } from '../src/backend/RPCSocketServer'
2
+//@ts-ignore
3
+import {RPCaller} from '../src/frontend/RPCaller'
4
+
5
+new RPCSocketServer(20000, [{
6
+    name: "HelloWorldRPCGroup",
7
+    exportRPCs: () => [{
8
+        type: 'call',
9
+        name: 'echo',
10
+        func: async (s:string) => s,
11
+        visibility: 'private'
12
+    }]
13
+}] )
14
+
15
+const caller = new RPCaller(20000, 'localhost')
16
+caller.connect().then(_ => {
17
+    caller.info().then(console.log)
18
+    caller["HelloWorldRPCGroup"].echo("x").then(console.log)
19
+})

+ 2
- 2
tsconfig.json View File

9
       "strict": true,
9
       "strict": true,
10
       "experimentalDecorators": true
10
       "experimentalDecorators": true
11
     },
11
     },
12
-    "include": ["src/backend/**/*"],
13
-    "exclude": ["node_modules", "**/__tests__/*"],
12
+    "include": ["src/backend/**/*", "test/**/*"],
13
+    "exclude": ["node_modules", "**/__tests__/*", "src/frontend/**/*"]
14
 }
14
 }

Loading…
Cancel
Save