From 3caef12e4e718a3ec8450e7f3b0e5b7dbc29c728 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Fri, 8 Oct 2021 20:33:05 -0700 Subject: [PATCH] server: console fixes --- server/package-lock.json | 66 +++++++++++++++++++++++------- server/package.json | 1 + server/src/plugin/plugin-host.ts | 17 +++++--- server/src/plugin/plugin-remote.ts | 13 ++++-- server/src/rpc.ts | 2 +- server/src/runtime.ts | 5 ++- 6 files changed, 78 insertions(+), 26 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index 34d88471e..cc796d832 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -59,6 +59,7 @@ "@koush/opencv4nodejs": "^5.6.7", "@tensorflow/tfjs-node": "^3.9.0", "@tensorflow/tfjs-node-gpu": "^3.9.0", + "canvas": "^2.8.0", "ffmpeg-for-homebridge": "^0.0.9", "mdns": "^2.7.2", "serialport": "^9.2.0" @@ -1588,11 +1589,11 @@ } }, "node_modules/axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "dependencies": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.0" } }, "node_modules/balanced-match": { @@ -1733,6 +1734,21 @@ "node": ">= 0.8" } }, + "node_modules/canvas": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", + "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.14.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2366,11 +2382,22 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", - "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==", + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", + "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, "node_modules/form-data": { @@ -5811,11 +5838,11 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.0" } }, "balanced-match": { @@ -5931,6 +5958,17 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "canvas": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", + "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", + "optional": true, + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.14.0", + "simple-get": "^3.0.3" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6448,9 +6486,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", - "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", + "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" }, "form-data": { "version": "3.0.1", diff --git a/server/package.json b/server/package.json index cda8a01ef..ab04a705b 100644 --- a/server/package.json +++ b/server/package.json @@ -36,6 +36,7 @@ "@koush/opencv4nodejs": "^5.6.7", "@tensorflow/tfjs-node": "^3.9.0", "@tensorflow/tfjs-node-gpu": "^3.9.0", + "canvas": "^2.8.0", "ffmpeg-for-homebridge": "^0.0.9", "mdns": "^2.7.2", "serialport": "^9.2.0" diff --git a/server/src/plugin/plugin-host.ts b/server/src/plugin/plugin-host.ts index 4ed9d3cf0..1d01243a0 100644 --- a/server/src/plugin/plugin-host.ts +++ b/server/src/plugin/plugin-host.ts @@ -433,7 +433,8 @@ export function startPluginClusterWorker() { return ds?.id; } - const getConsole = (hook: (stdout: PassThrough, stderr: PassThrough) => Promise, also?: Console, alsoPrefix?: string) => { + const getConsole = (hook: (stdout: PassThrough, stderr: PassThrough) => Promise, + also?: Console, alsoPrefix?: string) => { const stdout = new PassThrough(); const stderr = new PassThrough(); @@ -459,23 +460,27 @@ export function startPluginClusterWorker() { for (const m of methods) { const old = (ret as any)[m].bind(ret); (ret as any)[m] = (...args: any[]) => { - (console as any)[m](...args); - old(...args); - + // prefer the mixin version for local/remote console dump. if (also && alsoPrefix && printers.includes(m)) { (also as any)[m](alsoPrefix, ...args); } + else { + (console as any)[m](...args); + } + // call through to old method to ensure it gets written + // to log buffer. + old(...args); } } return ret; } - const getDeviceConsole = (nativeId?: ScryptedNativeId) => { + const getDeviceConsole = (nativeId?: ScryptedNativeId, disableEcho?: boolean) => { return getConsole(async (stdout, stderr) => { stdout.on('data', data => events.emit('stdout', data, nativeId)); stderr.on('data', data => events.emit('stderr', data, nativeId)); - }); + }, undefined, undefined); } const getMixinConsole = (mixinId: string, nativeId?: ScryptedNativeId) => { diff --git a/server/src/plugin/plugin-remote.ts b/server/src/plugin/plugin-remote.ts index f22e5b37e..e47ab1f46 100644 --- a/server/src/plugin/plugin-remote.ts +++ b/server/src/plugin/plugin-remote.ts @@ -326,10 +326,15 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp // JSON stringify over rpc turns undefined into null. if (nativeId === null) nativeId = undefined; - deviceManager.nativeIds.set(nativeId?.toString(), { - id, - storage, - }); + if (id) { + deviceManager.nativeIds.set(nativeId?.toString(), { + id, + storage, + }); + } + else { + deviceManager.nativeIds.delete(nativeId); + } }, async updateDescriptor(id: string, state: { [property: string]: SystemDeviceState }) { diff --git a/server/src/rpc.ts b/server/src/rpc.ts index c3063c3c5..7e2215dfd 100644 --- a/server/src/rpc.ts +++ b/server/src/rpc.ts @@ -403,7 +403,7 @@ export class RpcPeer { if (rpcApply.method) { const method = target[rpcApply.method]; if (!method) - throw new Error(`target ${target?.constructor.name} does not have method ${rpcApply.method}`); + throw new Error(`target ${target?.constructor?.name} does not have method ${rpcApply.method}`); value = await target[rpcApply.method](...args); } else { diff --git a/server/src/runtime.ts b/server/src/runtime.ts index 1885a0c5e..ea9066bad 100644 --- a/server/src/runtime.ts +++ b/server/src/runtime.ts @@ -539,12 +539,15 @@ export class ScryptedRuntime { } this.stateManager.removeDevice(device._id); + const plugin = this.plugins[device.pluginId]; // remove the plugin too if (!device.nativeId) { - const plugin = this.plugins[device.pluginId]; plugin?.kill(); await this.datastore.removeId(Plugin, device.pluginId); } + else { + await plugin.remote.setNativeId(device.nativeId, undefined, undefined); + } } upsertDevice(pluginId: string, device: Device, invalidate?: boolean): Promise {