diff --git a/server/package-lock.json b/server/package-lock.json index 6727b3234..105c69e5b 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/server", - "version": "0.5.3", + "version": "0.5.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/server", - "version": "0.5.3", + "version": "0.5.4", "license": "ISC", "dependencies": { "@ffmpeg-installer/ffmpeg": "^1.1.0", diff --git a/server/package.json b/server/package.json index a7cead28f..462ce2471 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/server", - "version": "0.5.3", + "version": "0.5.4", "description": "", "dependencies": { "@ffmpeg-installer/ffmpeg": "^1.1.0", diff --git a/server/python/plugin-remote.py b/server/python/plugin-remote.py index 86e3f25af..7277bed19 100644 --- a/server/python/plugin-remote.py +++ b/server/python/plugin-remote.py @@ -209,13 +209,15 @@ class PluginRemote: systemState: Mapping[str, Mapping[str, SystemDeviceState]] = {} nativeIds: Mapping[str, DeviceStorage] = {} pluginId: str + hostInfo: Any mediaManager: MediaManager loop: AbstractEventLoop consoles: Mapping[str, Future[Tuple[StreamReader, StreamWriter]]] = {} - def __init__(self, api, pluginId, loop: AbstractEventLoop): + def __init__(self, api, pluginId, hostInfo, loop: AbstractEventLoop): self.api = api self.pluginId = pluginId + self.hostInfo = hostInfo self.loop = loop self.__dict__['__proxy_oneway_methods'] = [ 'notify', @@ -463,8 +465,8 @@ async def async_main(loop: AbstractEventLoop): peer.constructorSerializerMap[bytes] = 'Buffer' peer.constructorSerializerMap[bytearray] = 'Buffer' peer.params['print'] = print - peer.params['getRemote'] = lambda api, pluginId: PluginRemote( - api, pluginId, loop) + peer.params['getRemote'] = lambda api, pluginId, hostInfo: PluginRemote( + api, pluginId, hostInfo, loop) async def get_update_stats(): update_stats = await peer.getParam('updateStats') diff --git a/server/src/plugin/plugin-api.ts b/server/src/plugin/plugin-api.ts index 74a37ecf1..5d0c8faa4 100644 --- a/server/src/plugin/plugin-api.ts +++ b/server/src/plugin/plugin-api.ts @@ -8,6 +8,10 @@ export interface PluginLogger { clearAlerts(): Promise; } +export interface PluginHostInfo { + serverVersion: string; +} + export interface PluginAPI { setState(nativeId: ScryptedNativeId, key: string, value: any): Promise; onDevicesChanged(deviceManifest: DeviceManifest): Promise; @@ -154,7 +158,6 @@ export class PluginAPIProxy extends PluginAPIManagedListeners implements PluginA } export interface PluginRemoteLoadZipOptions { - serverVersion?: string; /** * The filename to load the script as. Use for debugger source mapping. */ diff --git a/server/src/plugin/plugin-host.ts b/server/src/plugin/plugin-host.ts index d5647c051..b706f9c3e 100644 --- a/server/src/plugin/plugin-host.ts +++ b/server/src/plugin/plugin-host.ts @@ -217,7 +217,7 @@ export class PluginHost { logger.log('i', `loading ${this.pluginName}`); logger.log('i', 'pid ' + this.worker?.pid); - const remotePromise = setupPluginRemote(this.peer, this.api, self.pluginId, () => this.scrypted.stateManager.getSystemState()); + const remotePromise = setupPluginRemote(this.peer, this.api, self.pluginId, { serverVersion }, () => this.scrypted.stateManager.getSystemState()); const init = (async () => { const remote = await remotePromise; @@ -242,7 +242,6 @@ export class PluginHost { try { const isPython = runtime === 'python'; const loadZipOptions: PluginRemoteLoadZipOptions = { - serverVersion: serverVersion, // if debugging, use a normalized path for sourcemap resolution, otherwise // prefix with module path. filename: isPython @@ -396,7 +395,7 @@ export class PluginHost { socket.on('close', kill); socket.on('error', kill); - return setupPluginRemote(rpcPeer, api, null, () => this.scrypted.stateManager.getSystemState()); + return setupPluginRemote(rpcPeer, api, null, { serverVersion }, () => this.scrypted.stateManager.getSystemState()); } async createRpcPeer(duplex: Duplex) { @@ -410,6 +409,6 @@ export class PluginHost { }; duplex.on('close', kill); - return setupPluginRemote(rpcPeer, api, null, () => this.scrypted.stateManager.getSystemState()); + return setupPluginRemote(rpcPeer, api, null, { serverVersion }, () => this.scrypted.stateManager.getSystemState()); } } diff --git a/server/src/plugin/plugin-remote-worker.ts b/server/src/plugin/plugin-remote-worker.ts index a32ba3a2f..42e613c6f 100644 --- a/server/src/plugin/plugin-remote-worker.ts +++ b/server/src/plugin/plugin-remote-worker.ts @@ -22,6 +22,8 @@ interface PluginStats { memoryUsage: NodeJS.MemoryUsage; } +const serverVersion = require('../../package.json').version; + export function startPluginRemote(pluginId: string, peerSend: (message: RpcMessage, reject?: (e: Error) => void, serializationContext?: any) => void) { const peer = new RpcPeer('unknown', 'host', peerSend); @@ -371,7 +373,7 @@ export function startPluginRemote(pluginId: string, peerSend: (message: RpcMessa } const forkApi = new PluginForkAPI(api); - const remote = await setupPluginRemote(threadPeer, forkApi, pluginId, () => systemManager.getSystemState()); + const remote = await setupPluginRemote(threadPeer, forkApi, pluginId, { serverVersion }, () => systemManager.getSystemState()); forks.add(remote); ntw.worker.on('exit', () => { threadPeer.kill('worker exited'); diff --git a/server/src/plugin/plugin-remote.ts b/server/src/plugin/plugin-remote.ts index d5104b992..da3352336 100644 --- a/server/src/plugin/plugin-remote.ts +++ b/server/src/plugin/plugin-remote.ts @@ -2,7 +2,7 @@ import { Device, DeviceManager, DeviceManifest, DeviceState, EndpointManager, Ev import { RpcPeer, RPCResultError } from '../rpc'; import { AccessControls } from './acl'; import { BufferSerializer } from './buffer-serializer'; -import { PluginAPI, PluginLogger, PluginRemote, PluginRemoteLoadZipOptions } from './plugin-api'; +import { PluginAPI, PluginHostInfo, PluginLogger, PluginRemote, PluginRemoteLoadZipOptions } from './plugin-api'; import { createWebSocketClass, WebSocketConnectCallbacks, WebSocketConnection, WebSocketMethods, WebSocketSerializer } from './plugin-remote-websocket'; import { checkProperty } from './plugin-state-check'; import { SystemManagerImpl } from './system'; @@ -352,7 +352,7 @@ class StorageImpl implements Storage { } } -export async function setupPluginRemote(peer: RpcPeer, api: PluginAPI, pluginId: string, getSystemState: () => { [id: string]: { [property: string]: SystemDeviceState } }): Promise { +export async function setupPluginRemote(peer: RpcPeer, api: PluginAPI, pluginId: string, hostInfo: PluginHostInfo, getSystemState: () => { [id: string]: { [property: string]: SystemDeviceState } }): Promise { try { // the host/remote connection can be from server to plugin (node to node), // core plugin to web (node to browser). @@ -361,7 +361,7 @@ export async function setupPluginRemote(peer: RpcPeer, api: PluginAPI, pluginId: if (!peer.constructorSerializerMap.get(Buffer)) peer.addSerializer(Buffer, 'Buffer', new BufferSerializer()); const getRemote = await peer.getParam('getRemote'); - const remote = await getRemote(api, pluginId) as PluginRemote; + const remote = await getRemote(api, pluginId, hostInfo) as PluginRemote; const accessControls: AccessControls = peer.tags.acl; @@ -463,7 +463,7 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp let done: (scrypted: ScryptedStatic) => void; const retPromise = new Promise(resolve => done = resolve); - peer.params.getRemote = async (api: PluginAPI, pluginId: string) => { + peer.params.getRemote = async (api: PluginAPI, pluginId: string, hostInfo: PluginHostInfo) => { websocketSerializer.WebSocket = createWebSocketClass((connection, callbacks) => { const { url } = connection; if (url.startsWith('io://') || url.startsWith('ws://')) { @@ -506,7 +506,8 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp log, pluginHostAPI: api, pluginRemoteAPI: undefined, - } + serverVersion: hostInfo?.serverVersion, + }; delete peer.params.getRemote; @@ -637,7 +638,6 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp }; params.pluginRuntimeAPI = ret; - ret.serverVersion = zipOptions.serverVersion; return options.onLoadZip(ret, params, packageJson, zipData, zipOptions); },