scoundrel-remote-eval 1.0.7 → 1.0.9
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/build/client/connections/web-socket/index.d.ts +34 -0
- package/build/client/connections/web-socket/index.d.ts.map +1 -0
- package/build/client/connections/web-socket/index.js +68 -0
- package/build/client/index.d.ts +180 -0
- package/build/client/index.d.ts.map +1 -0
- package/build/client/index.js +413 -0
- package/build/client/reference-proxy.d.ts +7 -0
- package/build/client/reference-proxy.d.ts.map +1 -0
- package/build/client/reference-proxy.js +45 -0
- package/build/client/reference.d.ts +50 -0
- package/build/client/reference.d.ts.map +1 -0
- package/build/client/reference.js +63 -0
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +1 -0
- package/build/logger.d.ts +39 -0
- package/build/logger.d.ts.map +1 -0
- package/build/logger.js +64 -0
- package/build/python-web-socket-runner.d.ts +27 -0
- package/build/python-web-socket-runner.d.ts.map +1 -0
- package/build/python-web-socket-runner.js +94 -0
- package/build/server/connections/web-socket/client.d.ts +26 -0
- package/build/server/connections/web-socket/client.d.ts.map +1 -0
- package/build/server/connections/web-socket/client.js +39 -0
- package/build/server/connections/web-socket/index.d.ts +19 -0
- package/build/server/connections/web-socket/index.d.ts.map +1 -0
- package/build/server/connections/web-socket/index.js +29 -0
- package/build/server/index.d.ts +20 -0
- package/build/server/index.d.ts.map +1 -0
- package/build/server/index.js +26 -0
- package/package.json +17 -4
- package/spec/reference-with-proxy-spec.js +0 -87
- package/spec/support/jasmine.json +0 -13
- package/spec/web-socket-javascript-spec.js +0 -64
- package/spec/web-socket-python-spec.js +0 -55
- package/src/client/connections/web-socket/index.js +0 -51
- package/src/client/index.js +0 -423
- package/src/client/reference-proxy.js +0 -29
- package/src/client/reference.js +0 -67
- package/src/index.js +0 -0
- package/src/logger.js +0 -56
- package/src/python-web-socket-runner.js +0 -87
- package/src/server/connections/web-socket/client.js +0 -28
- package/src/server/connections/web-socket/index.js +0 -22
- package/src/server/index.js +0 -21
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-proxy.d.ts","sourceRoot":"","sources":["../../src/client/reference-proxy.js"],"names":[],"mappings":";AA8CA;;;GAGG;AACH,+CAHW,GAAG,oBAGwE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @param {import("./reference.js").default} reference
|
|
4
|
+
* @param {string} prop
|
|
5
|
+
* @returns {(...args: any[]) => Promise<any>}
|
|
6
|
+
*/
|
|
7
|
+
const proxyMethodSpawner = (reference, prop) => (...args) => reference.callMethodWithReference(prop, ...args);
|
|
8
|
+
const proxyObjectHandler = {
|
|
9
|
+
/**
|
|
10
|
+
* @param {import("./reference.js").default|(() => import("./reference.js").default)} reference
|
|
11
|
+
* @param {string} prop
|
|
12
|
+
* @returns {any}
|
|
13
|
+
*/
|
|
14
|
+
get(reference, prop) {
|
|
15
|
+
if (typeof reference == "function")
|
|
16
|
+
reference = reference();
|
|
17
|
+
if (prop == "__serialize") {
|
|
18
|
+
const method = reference.serialize;
|
|
19
|
+
const boundMethod = method.bind(reference);
|
|
20
|
+
return boundMethod;
|
|
21
|
+
}
|
|
22
|
+
return proxyMethodSpawner(reference, prop);
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* @param {import("./reference.js").default|(() => import("./reference.js").default)} receiver
|
|
26
|
+
* @param {string} prop
|
|
27
|
+
* @param {any} newValue
|
|
28
|
+
*/
|
|
29
|
+
set(receiver, prop, newValue) {
|
|
30
|
+
throw new Error("set property isn't supported yet");
|
|
31
|
+
// @ts-expect-error
|
|
32
|
+
if (typeof receiver == "function")
|
|
33
|
+
receiver = receiver(); // eslint-disable-line no-unreachable
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
if (!(prop in receiver))
|
|
36
|
+
throw new PropertyNotFoundError(`Property not found: ${prop}`); // eslint-disable-line no-undef
|
|
37
|
+
return Reflect.set(receiver, prop, newValue);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* @param {any} wrappedObject
|
|
42
|
+
* @returns {Proxy}
|
|
43
|
+
*/
|
|
44
|
+
const referenceProxy = (wrappedObject) => new Proxy(wrappedObject, proxyObjectHandler);
|
|
45
|
+
export default referenceProxy;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export default class Reference {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new Reference
|
|
4
|
+
*
|
|
5
|
+
* @param {any} client The client instance
|
|
6
|
+
* @param {string} id The reference ID
|
|
7
|
+
*/
|
|
8
|
+
constructor(client: any, id: string);
|
|
9
|
+
client: any;
|
|
10
|
+
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* Calls a method on the reference
|
|
13
|
+
*
|
|
14
|
+
* @param {string} methodName
|
|
15
|
+
* @param {...any} args
|
|
16
|
+
* @returns {Promise<any>}
|
|
17
|
+
*/
|
|
18
|
+
callMethod(methodName: string, ...args: any[]): Promise<any>;
|
|
19
|
+
/**
|
|
20
|
+
* Calls a method on the reference using another reference as argument
|
|
21
|
+
*
|
|
22
|
+
* @param {string} methodName
|
|
23
|
+
* @param {...any} args
|
|
24
|
+
* @returns {Promise<any>}
|
|
25
|
+
*/
|
|
26
|
+
callMethodWithReference(methodName: string, ...args: any[]): Promise<any>;
|
|
27
|
+
/**
|
|
28
|
+
* Reads an attribute from the reference
|
|
29
|
+
*
|
|
30
|
+
* @param {string} attributeName
|
|
31
|
+
* @param {...any} args
|
|
32
|
+
* @returns {Promise<any>}
|
|
33
|
+
*/
|
|
34
|
+
readAttribute(attributeName: string, ...args: any[]): Promise<any>;
|
|
35
|
+
/**
|
|
36
|
+
* Reads an attribute from the reference using another reference as argument
|
|
37
|
+
*
|
|
38
|
+
* @param {string} attributeName
|
|
39
|
+
* @param {...any} args
|
|
40
|
+
* @returns {Promise<any>}
|
|
41
|
+
*/
|
|
42
|
+
readAttributeWithReference(attributeName: string, ...args: any[]): Promise<any>;
|
|
43
|
+
/**
|
|
44
|
+
* Serializes the reference and returns the result directly
|
|
45
|
+
*
|
|
46
|
+
* @returns {Promise<any>}
|
|
47
|
+
*/
|
|
48
|
+
serialize(): Promise<any>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=reference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/client/reference.js"],"names":[],"mappings":"AAEA;IACE;;;;;OAKG;IACH,oBAHW,GAAG,MACH,MAAM,EAOhB;IAJC,YAAoB;IACpB,WAAY;IAKd;;;;;;OAMG;IACH,uBAJW,MAAM,WACF,GAAG,EAAA,GACL,OAAO,CAAC,GAAG,CAAC,CAIxB;IAED;;;;;;OAMG;IACH,oCAJW,MAAM,WACF,GAAG,EAAA,GACL,OAAO,CAAC,GAAG,CAAC,CAIxB;IAED;;;;;;OAMG;IACH,6BAJW,MAAM,WACF,GAAG,EAAA,GACL,OAAO,CAAC,GAAG,CAAC,CAIxB;IAED;;;;;;OAMG;IACH,0CAJW,MAAM,WACF,GAAG,EAAA,GACL,OAAO,CAAC,GAAG,CAAC,CAIxB;IAED;;;;OAIG;IACH,aAFa,OAAO,CAAC,GAAG,CAAC,CAIxB;CACF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export default class Reference {
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new Reference
|
|
5
|
+
*
|
|
6
|
+
* @param {any} client The client instance
|
|
7
|
+
* @param {string} id The reference ID
|
|
8
|
+
*/
|
|
9
|
+
constructor(client, id) {
|
|
10
|
+
this.client = client;
|
|
11
|
+
this.id = id;
|
|
12
|
+
if (!id)
|
|
13
|
+
throw new Error(`Invalid ID given: ${id}`);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Calls a method on the reference
|
|
17
|
+
*
|
|
18
|
+
* @param {string} methodName
|
|
19
|
+
* @param {...any} args
|
|
20
|
+
* @returns {Promise<any>}
|
|
21
|
+
*/
|
|
22
|
+
async callMethod(methodName, ...args) {
|
|
23
|
+
return await this.client.callMethodOnReference(this.id, methodName, ...args);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Calls a method on the reference using another reference as argument
|
|
27
|
+
*
|
|
28
|
+
* @param {string} methodName
|
|
29
|
+
* @param {...any} args
|
|
30
|
+
* @returns {Promise<any>}
|
|
31
|
+
*/
|
|
32
|
+
async callMethodWithReference(methodName, ...args) {
|
|
33
|
+
return await this.client.callMethodOnReferenceWithReference(this.id, methodName, ...args);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reads an attribute from the reference
|
|
37
|
+
*
|
|
38
|
+
* @param {string} attributeName
|
|
39
|
+
* @param {...any} args
|
|
40
|
+
* @returns {Promise<any>}
|
|
41
|
+
*/
|
|
42
|
+
async readAttribute(attributeName, ...args) {
|
|
43
|
+
return await this.client.readAttributeOnReference(this.id, attributeName, ...args);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reads an attribute from the reference using another reference as argument
|
|
47
|
+
*
|
|
48
|
+
* @param {string} attributeName
|
|
49
|
+
* @param {...any} args
|
|
50
|
+
* @returns {Promise<any>}
|
|
51
|
+
*/
|
|
52
|
+
async readAttributeWithReference(attributeName, ...args) {
|
|
53
|
+
return await this.client.readAttributeOnReferenceWithReference(this.id, attributeName, ...args);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Serializes the reference and returns the result directly
|
|
57
|
+
*
|
|
58
|
+
* @returns {Promise<any>}
|
|
59
|
+
*/
|
|
60
|
+
async serialize() {
|
|
61
|
+
return await this.client.serializeReference(this.id);
|
|
62
|
+
}
|
|
63
|
+
}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":""}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export default class Logger {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new Logger instance
|
|
4
|
+
*
|
|
5
|
+
* @param {string} scopeName The name of the scope for the logger
|
|
6
|
+
*/
|
|
7
|
+
constructor(scopeName: string);
|
|
8
|
+
debug: boolean;
|
|
9
|
+
scopeName: string;
|
|
10
|
+
/**
|
|
11
|
+
* Enables or disables debug logging
|
|
12
|
+
*
|
|
13
|
+
* @param {boolean} newValue
|
|
14
|
+
*/
|
|
15
|
+
setDebug(newValue: boolean): void;
|
|
16
|
+
/**
|
|
17
|
+
* Logs an error message to the console if debug is enabled
|
|
18
|
+
*
|
|
19
|
+
* @param {...any} args
|
|
20
|
+
*/
|
|
21
|
+
error(...args: any[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* Logs a message to the console if debug is enabled
|
|
24
|
+
* @param {...any} args
|
|
25
|
+
*/
|
|
26
|
+
log(...args: any[]): void;
|
|
27
|
+
/**
|
|
28
|
+
* Logs a warning message to the console if debug is enabled
|
|
29
|
+
* @param {...any} args
|
|
30
|
+
*/
|
|
31
|
+
warn(...args: any[]): void;
|
|
32
|
+
/**
|
|
33
|
+
* Sends the log message to the console
|
|
34
|
+
* @param {string} logType
|
|
35
|
+
* @param {...any} args
|
|
36
|
+
*/
|
|
37
|
+
_sendToConsole(logType: string, ...args: any[]): void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.js"],"names":[],"mappings":"AAEA;IACE;;;;OAIG;IACH,uBAFW,MAAM,EAKhB;IAFC,eAAkB;IAClB,kBAA0B;IAG5B;;;;OAIG;IACH,mBAFW,OAAO,QAIjB;IAED;;;;OAIG;IACH,eAFe,GAAG,EAAA,QAIjB;IAED;;;OAGG;IACH,aAFe,GAAG,EAAA,QAIjB;IAED;;;OAGG;IACH,cAFe,GAAG,EAAA,QAIjB;IAED;;;;OAIG;IACH,wBAHW,MAAM,WACF,GAAG,EAAA,QAkBjB;CACF"}
|
package/build/logger.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export default class Logger {
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new Logger instance
|
|
5
|
+
*
|
|
6
|
+
* @param {string} scopeName The name of the scope for the logger
|
|
7
|
+
*/
|
|
8
|
+
constructor(scopeName) {
|
|
9
|
+
this.debug = false;
|
|
10
|
+
this.scopeName = scopeName;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Enables or disables debug logging
|
|
14
|
+
*
|
|
15
|
+
* @param {boolean} newValue
|
|
16
|
+
*/
|
|
17
|
+
setDebug(newValue) {
|
|
18
|
+
this.debug = newValue;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Logs an error message to the console if debug is enabled
|
|
22
|
+
*
|
|
23
|
+
* @param {...any} args
|
|
24
|
+
*/
|
|
25
|
+
error(...args) {
|
|
26
|
+
return this._sendToConsole("error", ...args);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Logs a message to the console if debug is enabled
|
|
30
|
+
* @param {...any} args
|
|
31
|
+
*/
|
|
32
|
+
log(...args) {
|
|
33
|
+
return this._sendToConsole("log", ...args);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Logs a warning message to the console if debug is enabled
|
|
37
|
+
* @param {...any} args
|
|
38
|
+
*/
|
|
39
|
+
warn(...args) {
|
|
40
|
+
return this._sendToConsole("warn", ...args);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Sends the log message to the console
|
|
44
|
+
* @param {string} logType
|
|
45
|
+
* @param {...any} args
|
|
46
|
+
*/
|
|
47
|
+
_sendToConsole(logType, ...args) {
|
|
48
|
+
if (!this.debug) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (args.length == 1 && typeof args[0] == "function") {
|
|
52
|
+
const callbackArgs = args[0]();
|
|
53
|
+
if (Array.isArray(callbackArgs)) {
|
|
54
|
+
console[logType](this.scopeName, ...callbackArgs);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console[logType](this.scopeName, callbackArgs);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console[logType](this.scopeName, ...args);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default class PythonWebSocketRunner {
|
|
2
|
+
/** @type {Error | null} */
|
|
3
|
+
waitForPidRejectError: Error | null;
|
|
4
|
+
/** @type {((value: any) => void) | null} */
|
|
5
|
+
waitForPidResolve: ((value: any) => void) | null;
|
|
6
|
+
/** @type {((value: any) => void) | null} */
|
|
7
|
+
waitForPidReject: ((value: any) => void) | null;
|
|
8
|
+
runAndWaitForPid(): Promise<any>;
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
onProcessExit: () => void;
|
|
11
|
+
/**
|
|
12
|
+
* @param {number} code
|
|
13
|
+
* @param {string} signal
|
|
14
|
+
*/
|
|
15
|
+
onChildExit: (code: number, signal: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* @param {string | Buffer} data
|
|
18
|
+
*/
|
|
19
|
+
onChildStderr: (data: string | Buffer) => void;
|
|
20
|
+
/**
|
|
21
|
+
* @param {string | Buffer} data
|
|
22
|
+
*/
|
|
23
|
+
onChildStdout: (data: string | Buffer) => void;
|
|
24
|
+
pid: string;
|
|
25
|
+
close(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=python-web-socket-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-web-socket-runner.d.ts","sourceRoot":"","sources":["../src/python-web-socket-runner.js"],"names":[],"mappings":"AAUA;IACE,2BAA2B;IAC3B,uBADW,KAAK,GAAG,IAAI,CACK;IAE5B,4CAA4C;IAC5C,mBADW,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,CAChB;IAExB,4CAA4C;IAC5C,kBADW,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,CACjB;IAMvB,iCAMC;IAED,qBAQC;IAED,0BAKC;IAED;;;OAGG;IACH,cAAe,MAHJ,MAGQ,EAAE,QAFV,MAEgB,UAkB1B;IAED;;OAEG;IACH,gBAAiB,MAFN,MAAM,GAAG,MAEC,UAMpB;IAED;;OAEG;IACH,gBAAiB,MAFN,MAAM,GAAG,MAEC,UAqBpB;IAfG,YAAmB;IAiBvB,cAIC;CACF"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { exec, spawn } from "child_process";
|
|
3
|
+
import Logger from "./logger.js";
|
|
4
|
+
import { realpath } from "fs/promises";
|
|
5
|
+
const logger = new Logger("Scoundrel PythonWebSocketRunner");
|
|
6
|
+
// logger.setDebug(true)
|
|
7
|
+
export default class PythonWebSocketRunner {
|
|
8
|
+
constructor() {
|
|
9
|
+
/** @type {Error | null} */
|
|
10
|
+
this.waitForPidRejectError = null;
|
|
11
|
+
/** @type {((value: any) => void) | null} */
|
|
12
|
+
this.waitForPidResolve = null;
|
|
13
|
+
/** @type {((value: any) => void) | null} */
|
|
14
|
+
this.waitForPidReject = null;
|
|
15
|
+
this.onProcessExit = () => {
|
|
16
|
+
if (this.pid) {
|
|
17
|
+
this.close();
|
|
18
|
+
logger.log(() => `onProcessExit: Killing Python process with PID ${this.pid}`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* @param {number} code
|
|
23
|
+
* @param {string} signal
|
|
24
|
+
*/
|
|
25
|
+
this.onChildExit = (code, signal) => {
|
|
26
|
+
logger.log(() => `Child process exited with code ${code} and signal ${signal}`);
|
|
27
|
+
if (this.waitForPidRejectError) {
|
|
28
|
+
if (!this.waitForPidReject) {
|
|
29
|
+
throw new Error("waitForPidReject is undefined while waitForPidRejectError is set");
|
|
30
|
+
}
|
|
31
|
+
this.waitForPidReject(this.waitForPidRejectError);
|
|
32
|
+
this.waitForPidResolve = null;
|
|
33
|
+
this.waitForPidReject = null;
|
|
34
|
+
this.waitForPidRejectError = null;
|
|
35
|
+
}
|
|
36
|
+
else if (this.waitForPidReject) {
|
|
37
|
+
this.waitForPidReject(new Error(`Python process exited before PID was received (code: ${code}, signal: ${signal})`));
|
|
38
|
+
this.waitForPidResolve = null;
|
|
39
|
+
this.waitForPidReject = null;
|
|
40
|
+
this.waitForPidRejectError = null;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* @param {string | Buffer} data
|
|
45
|
+
*/
|
|
46
|
+
this.onChildStderr = (data) => {
|
|
47
|
+
logger.error(() => `stderr: ${data}`);
|
|
48
|
+
if (this.waitForPidReject) {
|
|
49
|
+
this.waitForPidRejectError = new Error(`Python process stderr before PID was received: ${data}`);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* @param {string | Buffer} data
|
|
54
|
+
*/
|
|
55
|
+
this.onChildStdout = (data) => {
|
|
56
|
+
logger.log(() => `stdout: ${data}`);
|
|
57
|
+
const match = (`${data}`).match(/^Started with PID (\d+) on (.+):(.+)\n$/);
|
|
58
|
+
if (match) {
|
|
59
|
+
this.pid = match[1];
|
|
60
|
+
logger.log(() => `Registered PID ${this.pid}`);
|
|
61
|
+
if (this.waitForPidResolve) {
|
|
62
|
+
if (!this.waitForPidResolve) {
|
|
63
|
+
throw new Error("waitForPidResolve is undefined while waitForPidRejectError is set");
|
|
64
|
+
}
|
|
65
|
+
this.waitForPidResolve(null);
|
|
66
|
+
this.waitForPidResolve = null;
|
|
67
|
+
this.waitForPidReject = null;
|
|
68
|
+
this.waitForPidRejectError = null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
process.on("exit", this.onProcessExit);
|
|
73
|
+
}
|
|
74
|
+
runAndWaitForPid() {
|
|
75
|
+
return new Promise((resolve, reject) => {
|
|
76
|
+
this.waitForPidResolve = resolve;
|
|
77
|
+
this.waitForPidReject = reject;
|
|
78
|
+
this.run();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async run() {
|
|
82
|
+
const filePath = `${process.cwd()}/../python/server/web-socket.py`;
|
|
83
|
+
const fileRealPath = await realpath(filePath);
|
|
84
|
+
const child = spawn("python3", [fileRealPath]);
|
|
85
|
+
child.on("exit", this.onChildExit);
|
|
86
|
+
child.stdout.on("data", this.onChildStdout);
|
|
87
|
+
child.stderr.on("data", this.onChildStderr);
|
|
88
|
+
}
|
|
89
|
+
close() {
|
|
90
|
+
if (this.pid) {
|
|
91
|
+
exec(`kill ${this.pid}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default class WebSocketClient {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new WebSocketClient
|
|
4
|
+
* @param {import("ws").WebSocket} ws The WebSocket instance
|
|
5
|
+
*/
|
|
6
|
+
constructor(ws: any);
|
|
7
|
+
ws: any;
|
|
8
|
+
/**
|
|
9
|
+
* @param {(data: any) => void} callback
|
|
10
|
+
*/
|
|
11
|
+
onCommand(callback: (data: any) => void): void;
|
|
12
|
+
onCommandCallback: (data: any) => void;
|
|
13
|
+
/**
|
|
14
|
+
* @param {Error} error
|
|
15
|
+
*/
|
|
16
|
+
onError: (error: Error) => void;
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} rawData
|
|
19
|
+
*/
|
|
20
|
+
onMessage: (rawData: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* @param {any} data
|
|
23
|
+
*/
|
|
24
|
+
send(data: any): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/server/connections/web-socket/client.js"],"names":[],"mappings":"AAEA;IACE;;;OAGG;IACH,qBAKC;IAJC,QAAY;IAMd;;OAEG;IACH,oBAFW,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,QAI7B;IADC,0BAHgB,GAAG,KAAK,IAAI,CAGK;IAGnC;;OAEG;IACH,UAAW,OAFA,KAEK,UAEf;IAED;;OAEG;IACH,YAAa,SAFF,MAES,UAMnB;IAED;;OAEG;IACH,WAFW,GAAG,iBAIb;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export default class WebSocketClient {
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new WebSocketClient
|
|
5
|
+
* @param {import("ws").WebSocket} ws The WebSocket instance
|
|
6
|
+
*/
|
|
7
|
+
constructor(ws) {
|
|
8
|
+
/**
|
|
9
|
+
* @param {Error} error
|
|
10
|
+
*/
|
|
11
|
+
this.onError = (error) => {
|
|
12
|
+
console.error("WebSocketClient error", error);
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} rawData
|
|
16
|
+
*/
|
|
17
|
+
this.onMessage = (rawData) => {
|
|
18
|
+
const data = JSON.parse(rawData);
|
|
19
|
+
if (!this.onCommandCallback)
|
|
20
|
+
throw new Error("Command callback hasn't been set");
|
|
21
|
+
this.onCommandCallback(data);
|
|
22
|
+
};
|
|
23
|
+
this.ws = ws;
|
|
24
|
+
ws.on("error", this.onError);
|
|
25
|
+
ws.on("message", this.onMessage);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @param {(data: any) => void} callback
|
|
29
|
+
*/
|
|
30
|
+
onCommand(callback) {
|
|
31
|
+
this.onCommandCallback = callback;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @param {any} data
|
|
35
|
+
*/
|
|
36
|
+
async send(data) {
|
|
37
|
+
await this.ws.send(JSON.stringify(data));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default class WebSocket {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new WebSocket connection handler
|
|
4
|
+
* @param {import("ws").Server} webSocketServer The WebSocket server instance
|
|
5
|
+
*/
|
|
6
|
+
constructor(webSocketServer: any);
|
|
7
|
+
wss: any;
|
|
8
|
+
close(): void;
|
|
9
|
+
/**
|
|
10
|
+
* @param {import("ws").WebSocket} ws
|
|
11
|
+
*/
|
|
12
|
+
onConnection: (ws: any) => void;
|
|
13
|
+
/**
|
|
14
|
+
* @param {(client: import("./client.js").default) => void} callback
|
|
15
|
+
*/
|
|
16
|
+
onNewClient(callback: (client: import("./client.js").default) => void): void;
|
|
17
|
+
onNewClientCallback: (client: import("./client.js").default) => void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/connections/web-socket/index.js"],"names":[],"mappings":"AAIA;IACE;;;OAGG;IACH,kCAGC;IAFC,SAA0B;IAI5B,cAA4B;IAE5B;;OAEG;IACH,eAAgB,OAAE,UAIjB;IAED;;OAEG;IACH,sBAFW,CAAC,MAAM,EAAE,OAAO,aAAa,EAAE,OAAO,KAAK,IAAI,QAMzD;IADC,8BALkB,OAAO,aAAa,EAAE,OAAO,KAAK,IAAI,CAKrB;CAEtC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import WebSocketClient from "./client.js";
|
|
3
|
+
export default class WebSocket {
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new WebSocket connection handler
|
|
6
|
+
* @param {import("ws").Server} webSocketServer The WebSocket server instance
|
|
7
|
+
*/
|
|
8
|
+
constructor(webSocketServer) {
|
|
9
|
+
/**
|
|
10
|
+
* @param {import("ws").WebSocket} ws
|
|
11
|
+
*/
|
|
12
|
+
this.onConnection = (ws) => {
|
|
13
|
+
if (!this.onNewClientCallback)
|
|
14
|
+
throw new Error("'onNewClient' hasn't been called");
|
|
15
|
+
this.onNewClientCallback(new WebSocketClient(ws));
|
|
16
|
+
};
|
|
17
|
+
this.wss = webSocketServer;
|
|
18
|
+
this.wss.on("connection", this.onConnection);
|
|
19
|
+
}
|
|
20
|
+
close() { this.wss.close(); }
|
|
21
|
+
/**
|
|
22
|
+
* @param {(client: import("./client.js").default) => void} callback
|
|
23
|
+
*/
|
|
24
|
+
onNewClient(callback) {
|
|
25
|
+
if (!callback)
|
|
26
|
+
throw new Error("No callback was given");
|
|
27
|
+
this.onNewClientCallback = callback;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default class ScoundrelServer {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new Scoundrel server
|
|
4
|
+
* @param {import("./connections/web-socket/index.js").default} backend The backend connection handler
|
|
5
|
+
*/
|
|
6
|
+
constructor(backend: import("./connections/web-socket/index.js").default);
|
|
7
|
+
backend: import("./connections/web-socket/index.js").default;
|
|
8
|
+
/** @type {Client[]} */
|
|
9
|
+
clients: Client[];
|
|
10
|
+
events: EventEmitter<any>;
|
|
11
|
+
close(): void;
|
|
12
|
+
getClients(): Client[];
|
|
13
|
+
/**
|
|
14
|
+
* @param {import("./connections/web-socket/client.js").default} clientBackend
|
|
15
|
+
*/
|
|
16
|
+
onNewClient: (clientBackend: import("./connections/web-socket/client.js").default) => void;
|
|
17
|
+
}
|
|
18
|
+
import Client from "../client/index.js";
|
|
19
|
+
import EventEmitter from "events";
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.js"],"names":[],"mappings":"AAKA;IACE;;;OAGG;IACH,qBAFW,OAAO,mCAAmC,EAAE,OAAO,EAU7D;IAPC,6DAAsB;IAGtB,uBAAuB;IACvB,SADW,MAAM,EAAE,CACF;IAEjB,0BAAgC;IAGlC,cAAgC;IAChC,uBAAoC;IAEpC;;OAEG;IACH,cAAe,eAFJ,OAAO,oCAAoC,EAAE,OAE5B,UAK3B;CACF;mBA9BkB,oBAAoB;yBACd,QAAQ"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import Client from "../client/index.js";
|
|
3
|
+
import EventEmitter from "events";
|
|
4
|
+
export default class ScoundrelServer {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new Scoundrel server
|
|
7
|
+
* @param {import("./connections/web-socket/index.js").default} backend The backend connection handler
|
|
8
|
+
*/
|
|
9
|
+
constructor(backend) {
|
|
10
|
+
/**
|
|
11
|
+
* @param {import("./connections/web-socket/client.js").default} clientBackend
|
|
12
|
+
*/
|
|
13
|
+
this.onNewClient = (clientBackend) => {
|
|
14
|
+
const client = new Client(clientBackend);
|
|
15
|
+
this.clients.push(client);
|
|
16
|
+
this.events.emit("newClient", client);
|
|
17
|
+
};
|
|
18
|
+
this.backend = backend;
|
|
19
|
+
this.backend.onNewClient(this.onNewClient);
|
|
20
|
+
/** @type {Client[]} */
|
|
21
|
+
this.clients = [];
|
|
22
|
+
this.events = new EventEmitter();
|
|
23
|
+
}
|
|
24
|
+
close() { this.backend.close(); }
|
|
25
|
+
getClients() { return this.clients; }
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scoundrel-remote-eval",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.9",
|
|
5
5
|
"description": "",
|
|
6
|
-
"main": "
|
|
6
|
+
"main": "build/index.js",
|
|
7
|
+
"types": "build/index.d.ts",
|
|
8
|
+
"files": ["build/**"],
|
|
7
9
|
"scripts": {
|
|
8
|
-
"
|
|
10
|
+
"build": "rm -rf build && tsc",
|
|
11
|
+
"lint": "eslint",
|
|
12
|
+
"prepublishOnly": "npm run build",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"test": "jasmine",
|
|
15
|
+
"watch": "tsc -w"
|
|
9
16
|
},
|
|
10
17
|
"repository": {
|
|
11
18
|
"type": "git",
|
|
@@ -21,7 +28,13 @@
|
|
|
21
28
|
},
|
|
22
29
|
"homepage": "https://github.com/kaspernj/scoundrel#readme",
|
|
23
30
|
"devDependencies": {
|
|
24
|
-
"
|
|
31
|
+
"@eslint/js": "^9.39.2",
|
|
32
|
+
"@types/jasmine": "^5.1.13",
|
|
33
|
+
"@types/node": "^25.0.2",
|
|
34
|
+
"eslint": "^9.39.2",
|
|
35
|
+
"globals": "^16.5.0",
|
|
36
|
+
"jasmine": "^5.1.0",
|
|
37
|
+
"typescript": "^5.9.3"
|
|
25
38
|
},
|
|
26
39
|
"dependencies": {
|
|
27
40
|
"ws": "^8.14.2"
|