scoundrel-remote-eval 1.0.8 → 1.0.10
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 +186 -0
- package/build/client/index.d.ts.map +1 -0
- package/build/client/index.js +452 -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 +41 -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 +27 -0
- package/build/server/index.d.ts.map +1 -0
- package/build/server/index.js +34 -0
- package/build/utils/single-event-emitter.d.ts +46 -0
- package/build/utils/single-event-emitter.d.ts.map +1 -0
- package/build/utils/single-event-emitter.js +86 -0
- package/package.json +9 -3
- package/eslint.config.js +0 -18
- package/spec/reference-with-proxy-spec.js +0 -101
- package/spec/support/jasmine.json +0 -13
- package/spec/web-socket-javascript-spec.js +0 -66
- package/spec/web-socket-python-spec.js +0 -57
- package/src/client/connections/web-socket/index.js +0 -88
- package/src/client/index.js +0 -469
- package/src/client/reference-proxy.js +0 -53
- package/src/client/reference.js +0 -69
- package/src/index.js +0 -0
- package/src/logger.js +0 -70
- package/src/python-web-socket-runner.js +0 -116
- package/src/server/connections/web-socket/client.js +0 -46
- package/src/server/connections/web-socket/index.js +0 -34
- package/src/server/index.js +0 -33
- package/tsconfig.json +0 -13
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @param {import("./reference.js").default} reference
|
|
5
|
-
* @param {string} prop
|
|
6
|
-
* @returns {(...args: any[]) => Promise<any>}
|
|
7
|
-
*/
|
|
8
|
-
const proxyMethodSpawner = (reference, prop) => (...args) => reference.callMethodWithReference(prop, ...args)
|
|
9
|
-
|
|
10
|
-
const proxyObjectHandler = {
|
|
11
|
-
/**
|
|
12
|
-
* @param {import("./reference.js").default|(() => import("./reference.js").default)} reference
|
|
13
|
-
* @param {string} prop
|
|
14
|
-
* @returns {any}
|
|
15
|
-
*/
|
|
16
|
-
get(reference, prop) {
|
|
17
|
-
if (typeof reference == "function") reference = reference()
|
|
18
|
-
|
|
19
|
-
if (prop == "__serialize") {
|
|
20
|
-
const method = reference.serialize
|
|
21
|
-
const boundMethod = method.bind(reference)
|
|
22
|
-
|
|
23
|
-
return boundMethod
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return proxyMethodSpawner(reference, prop)
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {import("./reference.js").default|(() => import("./reference.js").default)} receiver
|
|
31
|
-
* @param {string} prop
|
|
32
|
-
* @param {any} newValue
|
|
33
|
-
*/
|
|
34
|
-
set(receiver, prop, newValue) {
|
|
35
|
-
throw new Error("set property isn't supported yet")
|
|
36
|
-
|
|
37
|
-
// @ts-expect-error
|
|
38
|
-
if (typeof receiver == "function") receiver = receiver() // eslint-disable-line no-unreachable
|
|
39
|
-
|
|
40
|
-
// @ts-expect-error
|
|
41
|
-
if (!(prop in receiver)) throw new PropertyNotFoundError(`Property not found: ${prop}`) // eslint-disable-line no-undef
|
|
42
|
-
|
|
43
|
-
return Reflect.set(receiver, prop, newValue)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @param {any} wrappedObject
|
|
49
|
-
* @returns {Proxy}
|
|
50
|
-
*/
|
|
51
|
-
const referenceProxy = (wrappedObject) => new Proxy(wrappedObject, proxyObjectHandler)
|
|
52
|
-
|
|
53
|
-
export default referenceProxy
|
package/src/client/reference.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
export default class Reference {
|
|
4
|
-
/**
|
|
5
|
-
* Creates a new Reference
|
|
6
|
-
*
|
|
7
|
-
* @param {any} client The client instance
|
|
8
|
-
* @param {string} id The reference ID
|
|
9
|
-
*/
|
|
10
|
-
constructor(client, id) {
|
|
11
|
-
this.client = client
|
|
12
|
-
this.id = id
|
|
13
|
-
|
|
14
|
-
if (!id) throw new Error(`Invalid ID given: ${id}`)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Calls a method on the reference
|
|
19
|
-
*
|
|
20
|
-
* @param {string} methodName
|
|
21
|
-
* @param {...any} args
|
|
22
|
-
* @returns {Promise<any>}
|
|
23
|
-
*/
|
|
24
|
-
async callMethod(methodName, ...args) {
|
|
25
|
-
return await this.client.callMethodOnReference(this.id, methodName, ...args)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Calls a method on the reference using another reference as argument
|
|
30
|
-
*
|
|
31
|
-
* @param {string} methodName
|
|
32
|
-
* @param {...any} args
|
|
33
|
-
* @returns {Promise<any>}
|
|
34
|
-
*/
|
|
35
|
-
async callMethodWithReference(methodName, ...args) {
|
|
36
|
-
return await this.client.callMethodOnReferenceWithReference(this.id, methodName, ...args)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Reads an attribute from the reference
|
|
41
|
-
*
|
|
42
|
-
* @param {string} attributeName
|
|
43
|
-
* @param {...any} args
|
|
44
|
-
* @returns {Promise<any>}
|
|
45
|
-
*/
|
|
46
|
-
async readAttribute(attributeName, ...args) {
|
|
47
|
-
return await this.client.readAttributeOnReference(this.id, attributeName, ...args)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Reads an attribute from the reference using another reference as argument
|
|
52
|
-
*
|
|
53
|
-
* @param {string} attributeName
|
|
54
|
-
* @param {...any} args
|
|
55
|
-
* @returns {Promise<any>}
|
|
56
|
-
*/
|
|
57
|
-
async readAttributeWithReference(attributeName, ...args) {
|
|
58
|
-
return await this.client.readAttributeOnReferenceWithReference(this.id, attributeName, ...args)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Serializes the reference and returns the result directly
|
|
63
|
-
*
|
|
64
|
-
* @returns {Promise<any>}
|
|
65
|
-
*/
|
|
66
|
-
async serialize() {
|
|
67
|
-
return await this.client.serializeReference(this.id)
|
|
68
|
-
}
|
|
69
|
-
}
|
package/src/index.js
DELETED
|
File without changes
|
package/src/logger.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
export default class Logger {
|
|
4
|
-
/**
|
|
5
|
-
* Creates a new Logger instance
|
|
6
|
-
*
|
|
7
|
-
* @param {string} scopeName The name of the scope for the logger
|
|
8
|
-
*/
|
|
9
|
-
constructor(scopeName) {
|
|
10
|
-
this.debug = false
|
|
11
|
-
this.scopeName = scopeName
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Enables or disables debug logging
|
|
16
|
-
*
|
|
17
|
-
* @param {boolean} newValue
|
|
18
|
-
*/
|
|
19
|
-
setDebug(newValue) {
|
|
20
|
-
this.debug = newValue
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Logs an error message to the console if debug is enabled
|
|
25
|
-
*
|
|
26
|
-
* @param {...any} args
|
|
27
|
-
*/
|
|
28
|
-
error(...args) {
|
|
29
|
-
return this._sendToConsole("error", ...args)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Logs a message to the console if debug is enabled
|
|
34
|
-
* @param {...any} args
|
|
35
|
-
*/
|
|
36
|
-
log(...args) {
|
|
37
|
-
return this._sendToConsole("log", ...args)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Logs a warning message to the console if debug is enabled
|
|
42
|
-
* @param {...any} args
|
|
43
|
-
*/
|
|
44
|
-
warn(...args) {
|
|
45
|
-
return this._sendToConsole("warn", ...args)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Sends the log message to the console
|
|
50
|
-
* @param {string} logType
|
|
51
|
-
* @param {...any} args
|
|
52
|
-
*/
|
|
53
|
-
_sendToConsole(logType, ...args) {
|
|
54
|
-
if (!this.debug) {
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (args.length == 1 && typeof args[0] == "function") {
|
|
59
|
-
const callbackArgs = args[0]()
|
|
60
|
-
|
|
61
|
-
if (Array.isArray(callbackArgs)) {
|
|
62
|
-
console[logType](this.scopeName, ...callbackArgs)
|
|
63
|
-
} else {
|
|
64
|
-
console[logType](this.scopeName, callbackArgs)
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
console[logType](this.scopeName, ...args)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import {exec, spawn} from "child_process"
|
|
4
|
-
import Logger from "./logger.js"
|
|
5
|
-
import {realpath} from "fs/promises"
|
|
6
|
-
|
|
7
|
-
const logger = new Logger("Scoundrel PythonWebSocketRunner")
|
|
8
|
-
|
|
9
|
-
// logger.setDebug(true)
|
|
10
|
-
|
|
11
|
-
export default class PythonWebSocketRunner {
|
|
12
|
-
/** @type {Error | null} */
|
|
13
|
-
waitForPidRejectError = null
|
|
14
|
-
|
|
15
|
-
/** @type {((value: any) => void) | null} */
|
|
16
|
-
waitForPidResolve = null
|
|
17
|
-
|
|
18
|
-
/** @type {((value: any) => void) | null} */
|
|
19
|
-
waitForPidReject = null
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
process.on("exit", this.onProcessExit)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
runAndWaitForPid() {
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
this.waitForPidResolve = resolve
|
|
28
|
-
this.waitForPidReject = reject
|
|
29
|
-
this.run()
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async run() {
|
|
34
|
-
const filePath = `${process.cwd()}/../python/server/web-socket.py`
|
|
35
|
-
const fileRealPath = await realpath(filePath)
|
|
36
|
-
const child = spawn("python3", [fileRealPath])
|
|
37
|
-
|
|
38
|
-
child.on("exit", this.onChildExit)
|
|
39
|
-
child.stdout.on("data", this.onChildStdout)
|
|
40
|
-
child.stderr.on("data", this.onChildStderr)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
onProcessExit = () => {
|
|
44
|
-
if (this.pid) {
|
|
45
|
-
this.close()
|
|
46
|
-
logger.log(() => `onProcessExit: Killing Python process with PID ${this.pid}`)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @param {number} code
|
|
52
|
-
* @param {string} signal
|
|
53
|
-
*/
|
|
54
|
-
onChildExit = (code, signal) => {
|
|
55
|
-
logger.log(() => `Child process exited with code ${code} and signal ${signal}`)
|
|
56
|
-
|
|
57
|
-
if (this.waitForPidRejectError) {
|
|
58
|
-
if (!this.waitForPidReject) {
|
|
59
|
-
throw new Error("waitForPidReject is undefined while waitForPidRejectError is set")
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
this.waitForPidReject(this.waitForPidRejectError)
|
|
63
|
-
this.waitForPidResolve = null
|
|
64
|
-
this.waitForPidReject = null
|
|
65
|
-
this.waitForPidRejectError = null
|
|
66
|
-
} else if (this.waitForPidReject) {
|
|
67
|
-
this.waitForPidReject(new Error(`Python process exited before PID was received (code: ${code}, signal: ${signal})`))
|
|
68
|
-
this.waitForPidResolve = null
|
|
69
|
-
this.waitForPidReject = null
|
|
70
|
-
this.waitForPidRejectError = null
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @param {string | Buffer} data
|
|
76
|
-
*/
|
|
77
|
-
onChildStderr = (data) => {
|
|
78
|
-
logger.error(() => `stderr: ${data}`)
|
|
79
|
-
|
|
80
|
-
if (this.waitForPidReject) {
|
|
81
|
-
this.waitForPidRejectError = new Error(`Python process stderr before PID was received: ${data}`)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @param {string | Buffer} data
|
|
87
|
-
*/
|
|
88
|
-
onChildStdout = (data) => {
|
|
89
|
-
logger.log(() => `stdout: ${data}`)
|
|
90
|
-
|
|
91
|
-
const match = (`${data}`).match(/^Started with PID (\d+) on (.+):(.+)\n$/)
|
|
92
|
-
|
|
93
|
-
if (match) {
|
|
94
|
-
this.pid = match[1]
|
|
95
|
-
|
|
96
|
-
logger.log(() => `Registered PID ${this.pid}`)
|
|
97
|
-
|
|
98
|
-
if (this.waitForPidResolve) {
|
|
99
|
-
if (!this.waitForPidResolve) {
|
|
100
|
-
throw new Error("waitForPidResolve is undefined while waitForPidRejectError is set")
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
this.waitForPidResolve(null)
|
|
104
|
-
this.waitForPidResolve = null
|
|
105
|
-
this.waitForPidReject = null
|
|
106
|
-
this.waitForPidRejectError = null
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
close() {
|
|
112
|
-
if (this.pid) {
|
|
113
|
-
exec(`kill ${this.pid}`)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
export default class WebSocketClient {
|
|
4
|
-
/**
|
|
5
|
-
* Creates a new WebSocketClient
|
|
6
|
-
* @param {import("ws").WebSocket} ws The WebSocket instance
|
|
7
|
-
*/
|
|
8
|
-
constructor(ws) {
|
|
9
|
-
this.ws = ws
|
|
10
|
-
|
|
11
|
-
ws.on("error", this.onError)
|
|
12
|
-
ws.on("message", this.onMessage)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param {(data: any) => void} callback
|
|
17
|
-
*/
|
|
18
|
-
onCommand(callback) {
|
|
19
|
-
this.onCommandCallback = callback
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param {Error} error
|
|
24
|
-
*/
|
|
25
|
-
onError = (error) => {
|
|
26
|
-
console.error("WebSocketClient error", error)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {string} rawData
|
|
31
|
-
*/
|
|
32
|
-
onMessage = (rawData) => {
|
|
33
|
-
const data = JSON.parse(rawData)
|
|
34
|
-
|
|
35
|
-
if (!this.onCommandCallback) throw new Error("Command callback hasn't been set")
|
|
36
|
-
|
|
37
|
-
this.onCommandCallback(data)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {any} data
|
|
42
|
-
*/
|
|
43
|
-
async send(data) {
|
|
44
|
-
await this.ws.send(JSON.stringify(data))
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import WebSocketClient from "./client.js"
|
|
4
|
-
|
|
5
|
-
export default class WebSocket {
|
|
6
|
-
/**
|
|
7
|
-
* Creates a new WebSocket connection handler
|
|
8
|
-
* @param {import("ws").Server} webSocketServer The WebSocket server instance
|
|
9
|
-
*/
|
|
10
|
-
constructor(webSocketServer) {
|
|
11
|
-
this.wss = webSocketServer
|
|
12
|
-
this.wss.on("connection", this.onConnection)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
close() { this.wss.close() }
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @param {import("ws").WebSocket} ws
|
|
19
|
-
*/
|
|
20
|
-
onConnection = (ws) => {
|
|
21
|
-
if (!this.onNewClientCallback) throw new Error("'onNewClient' hasn't been called")
|
|
22
|
-
|
|
23
|
-
this.onNewClientCallback(new WebSocketClient(ws))
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {(client: import("./client.js").default) => void} callback
|
|
28
|
-
*/
|
|
29
|
-
onNewClient(callback) {
|
|
30
|
-
if (!callback) throw new Error("No callback was given")
|
|
31
|
-
|
|
32
|
-
this.onNewClientCallback = callback
|
|
33
|
-
}
|
|
34
|
-
}
|
package/src/server/index.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import Client from "../client/index.js"
|
|
4
|
-
import EventEmitter from "events"
|
|
5
|
-
|
|
6
|
-
export default class ScoundrelServer {
|
|
7
|
-
/**
|
|
8
|
-
* Creates a new Scoundrel server
|
|
9
|
-
* @param {import("./connections/web-socket/index.js").default} backend The backend connection handler
|
|
10
|
-
*/
|
|
11
|
-
constructor(backend) {
|
|
12
|
-
this.backend = backend
|
|
13
|
-
this.backend.onNewClient(this.onNewClient)
|
|
14
|
-
|
|
15
|
-
/** @type {Client[]} */
|
|
16
|
-
this.clients = []
|
|
17
|
-
|
|
18
|
-
this.events = new EventEmitter()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
close() { this.backend.close() }
|
|
22
|
-
getClients() { return this.clients }
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {import("./connections/web-socket/client.js").default} clientBackend
|
|
26
|
-
*/
|
|
27
|
-
onNewClient = (clientBackend) => {
|
|
28
|
-
const client = new Client(clientBackend)
|
|
29
|
-
|
|
30
|
-
this.clients.push(client)
|
|
31
|
-
this.events.emit("newClient", client)
|
|
32
|
-
}
|
|
33
|
-
}
|