@scrypted/server 0.0.131 → 0.0.135

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.

Potentially problematic release.


This version of @scrypted/server might be problematic. Click here for more details.

Files changed (53) hide show
  1. package/.vscode/settings.json +1 -1
  2. package/dist/event-registry.js +1 -1
  3. package/dist/event-registry.js.map +1 -1
  4. package/dist/infer-defaults.js +1 -1
  5. package/dist/infer-defaults.js.map +1 -1
  6. package/dist/media-helpers.js +20 -15
  7. package/dist/media-helpers.js.map +1 -1
  8. package/dist/plugin/descriptor.js +1 -1
  9. package/dist/plugin/descriptor.js.map +1 -1
  10. package/dist/plugin/media.js +207 -101
  11. package/dist/plugin/media.js.map +1 -1
  12. package/dist/plugin/plugin-device.js +5 -1
  13. package/dist/plugin/plugin-device.js.map +1 -1
  14. package/dist/plugin/plugin-host-api.js +1 -1
  15. package/dist/plugin/plugin-host-api.js.map +1 -1
  16. package/dist/plugin/plugin-host.js +15 -6
  17. package/dist/plugin/plugin-host.js.map +1 -1
  18. package/dist/plugin/plugin-remote.js +10 -3
  19. package/dist/plugin/plugin-remote.js.map +1 -1
  20. package/dist/plugin/system.js +1 -1
  21. package/dist/plugin/system.js.map +1 -1
  22. package/dist/runtime.js +36 -8
  23. package/dist/runtime.js.map +1 -1
  24. package/dist/services/plugin.js +3 -11
  25. package/dist/services/plugin.js.map +1 -1
  26. package/dist/state.js +1 -1
  27. package/dist/state.js.map +1 -1
  28. package/package.json +5 -4
  29. package/python/plugin-remote.py +5 -5
  30. package/src/db-types.ts +1 -1
  31. package/src/event-registry.ts +1 -1
  32. package/src/http-interfaces.ts +1 -1
  33. package/src/infer-defaults.ts +1 -1
  34. package/src/media-helpers.ts +16 -15
  35. package/src/plugin/descriptor.ts +1 -1
  36. package/src/plugin/media.ts +232 -116
  37. package/src/plugin/plugin-api.ts +1 -1
  38. package/src/plugin/plugin-console.ts +1 -1
  39. package/src/plugin/plugin-device.ts +7 -2
  40. package/src/plugin/plugin-host-api.ts +1 -1
  41. package/src/plugin/plugin-host.ts +17 -7
  42. package/src/plugin/plugin-http.ts +1 -1
  43. package/src/plugin/plugin-lazy-remote.ts +1 -1
  44. package/src/plugin/plugin-remote-worker.ts +1 -1
  45. package/src/plugin/plugin-remote.ts +12 -4
  46. package/src/plugin/plugin-repl.ts +1 -1
  47. package/src/plugin/system.ts +1 -1
  48. package/src/runtime.ts +42 -10
  49. package/src/services/plugin.ts +3 -11
  50. package/src/state.ts +1 -1
  51. package/dist/convert.js +0 -117
  52. package/dist/convert.js.map +0 -1
  53. package/src/convert.ts +0 -122
package/src/runtime.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Level } from './level';
2
2
  import { PluginHost } from './plugin/plugin-host';
3
- import { ScryptedNativeId, Device, EngineIOHandler, HttpRequest, HttpRequestHandler, OauthClient, PushHandler, ScryptedDevice, ScryptedInterface, ScryptedInterfaceProperty } from '@scrypted/sdk/types';
3
+ import { ScryptedNativeId, Device, EngineIOHandler, HttpRequest, HttpRequestHandler, OauthClient, PushHandler, ScryptedDevice, ScryptedInterface, ScryptedInterfaceProperty } from '@scrypted/types';
4
4
  import { PluginDeviceProxyHandler } from './plugin/plugin-device';
5
5
  import { Plugin, PluginDevice, ScryptedAlert } from './db-types';
6
6
  import { getState, ScryptedStateManager, setState } from './state';
@@ -313,6 +313,18 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
313
313
  }
314
314
  }
315
315
 
316
+ async getPackageJson(pluginId: string) {
317
+ let packageJson;
318
+ if (this.plugins[pluginId]) {
319
+ packageJson = this.plugins[pluginId].packageJson;
320
+ }
321
+ else {
322
+ const plugin = await this.datastore.tryGet(Plugin, pluginId);
323
+ packageJson = plugin.packageJson;
324
+ }
325
+ return packageJson;
326
+ }
327
+
316
328
  handleEngineIOEndpoint(req: Request, res: ServerResponse, endpointRequest: HttpRequest, pluginData: HttpPluginData) {
317
329
  const { pluginHost, pluginDevice } = pluginData;
318
330
 
@@ -341,6 +353,11 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
341
353
  const existing = this.plugins[pluginId];
342
354
  if (existing) {
343
355
  delete this.plugins[pluginId];
356
+
357
+ if (existing.worker === PluginHost.sharedWorker) {
358
+ PluginHost.sharedWorkerImmediateRestart = true;
359
+ setTimeout(() => PluginHost.sharedWorkerImmediateRestart = false, 10000);
360
+ }
344
361
  existing.kill();
345
362
  }
346
363
  }
@@ -479,11 +496,14 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
479
496
  }
480
497
 
481
498
  setupPluginHostAutoRestart(pluginHost: PluginHost) {
499
+ const usingSharedWorker = pluginHost.worker === PluginHost.sharedWorker;
500
+
482
501
  pluginHost.worker.once('exit', () => {
483
502
  if (pluginHost.killed)
484
503
  return;
485
504
  pluginHost.kill();
486
- console.error('plugin unexpectedly exited, restarting in 1 minute', pluginHost.pluginId);
505
+ const timeout = usingSharedWorker && PluginHost.sharedWorkerImmediateRestart ? 0 : 60000;
506
+ console.error(`plugin unexpectedly exited, restarting in ${timeout}ms`, pluginHost.pluginId);
487
507
  setTimeout(async () => {
488
508
  const existing = this.plugins[pluginHost.pluginId];
489
509
  if (existing !== pluginHost) {
@@ -503,7 +523,7 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
503
523
  catch (e) {
504
524
  console.error('error restarting plugin', plugin._id, e);
505
525
  }
506
- }, 60000);
526
+ }, timeout);
507
527
  });
508
528
  }
509
529
 
@@ -621,7 +641,12 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
621
641
  const providedRoom = device.room;
622
642
  const isUsingDefaultRoom = getDisplayRoom(pluginDevice) === getProvidedRoomOrDefault(pluginDevice);
623
643
 
624
- const providedInterfaces = PluginDeviceProxyHandler.sortInterfaces(device.interfaces);
644
+ let providedInterfaces = device.interfaces.slice();
645
+ if (!device.nativeId)
646
+ providedInterfaces.push(ScryptedInterface.ScryptedPlugin);
647
+ else
648
+ providedInterfaces = providedInterfaces.filter(iface => iface !== ScryptedInterface.ScryptedPlugin);
649
+ providedInterfaces = PluginDeviceProxyHandler.sortInterfaces(providedInterfaces);
625
650
  // assure final mixin resolved interface list has at least all the
626
651
  // interfaces from the provided. the actual list will resolve lazily.
627
652
  let mixinInterfaces: string[] = [];
@@ -671,10 +696,6 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
671
696
  return ret;
672
697
  }
673
698
 
674
- async migrate(pluginDevice: PluginDevice) {
675
- // nothing right now.
676
- }
677
-
678
699
  killall() {
679
700
  for (const host of Object.values(this.plugins)) {
680
701
  host?.kill();
@@ -689,8 +710,6 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
689
710
  process.on('SIGTERM', () => this.killall());
690
711
 
691
712
  for await (const pluginDevice of this.datastore.getAll(PluginDevice)) {
692
- this.migrate(pluginDevice);
693
-
694
713
  // this may happen due to race condition around deletion/update. investigate.
695
714
  if (!pluginDevice.state) {
696
715
  this.datastore.remove(pluginDevice);
@@ -699,8 +718,21 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
699
718
 
700
719
  this.pluginDevices[pluginDevice._id] = pluginDevice;
701
720
  let mixins: string[] = getState(pluginDevice, ScryptedInterfaceProperty.mixins) || [];
721
+
722
+ let dirty = false;
702
723
  if (mixins.includes(null) || mixins.includes(undefined)) {
724
+ dirty = true;
703
725
  setState(pluginDevice, ScryptedInterfaceProperty.mixins, mixins.filter(e => !!e));
726
+ }
727
+
728
+ const interfaces: string[] = getState(pluginDevice, ScryptedInterfaceProperty.providedInterfaces);
729
+ if (!pluginDevice.nativeId && !interfaces.includes(ScryptedInterface.ScryptedPlugin)) {
730
+ dirty = true;
731
+ interfaces.push(ScryptedInterface.ScryptedPlugin);
732
+ setState(pluginDevice, ScryptedInterfaceProperty.providedInterfaces, PluginDeviceProxyHandler.sortInterfaces(interfaces));
733
+ }
734
+
735
+ if (dirty) {
704
736
  this.datastore.upsert(pluginDevice);
705
737
  }
706
738
  }
@@ -1,4 +1,4 @@
1
- import { ScryptedInterfaceProperty, ScryptedNativeId } from "@scrypted/sdk/types";
1
+ import { ScryptedInterfaceProperty, ScryptedNativeId } from "@scrypted/types";
2
2
  import { ScryptedRuntime } from "../runtime";
3
3
  import { Plugin } from '../db-types';
4
4
  import { getState } from "../state";
@@ -62,15 +62,7 @@ export class PluginComponent {
62
62
  return this.scrypted.plugins[pluginId]?.kill();
63
63
  }
64
64
  async getPackageJson(pluginId: string) {
65
- let packageJson;
66
- if (this.scrypted.plugins[pluginId]) {
67
- packageJson = this.scrypted.plugins[pluginId].packageJson;
68
- }
69
- else {
70
- const plugin = await this.scrypted.datastore.tryGet(Plugin, pluginId);
71
- packageJson = plugin.packageJson;
72
- }
73
- return packageJson;
65
+ return this.scrypted.getPackageJson(pluginId);
74
66
  }
75
67
  async getDeviceInfo(id: string) {
76
68
  const pluginDevice = this.scrypted.findPluginDeviceById(id);
@@ -82,7 +74,7 @@ export class PluginComponent {
82
74
  }
83
75
  }
84
76
  async getPluginInfo(pluginId: string) {
85
- const packageJson = this.getPackageJson(pluginId);
77
+ const packageJson = await this.getPackageJson(pluginId);
86
78
  const host = this.scrypted.plugins[pluginId];
87
79
  let rpcObjects = 0;
88
80
  if (host.peer) {
package/src/state.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ScryptedRuntime } from "./runtime";
2
- import { ScryptedNativeId, EventDetails, EventListenerOptions, EventListenerRegister, Refresh, ScryptedInterface, ScryptedInterfaceProperty, SystemDeviceState } from "@scrypted/sdk/types";
2
+ import { ScryptedNativeId, EventDetails, EventListenerOptions, EventListenerRegister, Refresh, ScryptedInterface, ScryptedInterfaceProperty, SystemDeviceState } from "@scrypted/types";
3
3
  import { RefreshSymbol } from "./plugin/plugin-device";
4
4
  import throttle from 'lodash/throttle';
5
5
  import { sleep } from "./sleep";
package/dist/convert.js DELETED
@@ -1,117 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.convert = exports.ensureBuffer = void 0;
7
- const types_1 = require("@scrypted/sdk/types");
8
- const node_dijkstra_1 = __importDefault(require("node-dijkstra"));
9
- const whatwg_mimetype_1 = __importDefault(require("whatwg-mimetype"));
10
- const axios_1 = __importDefault(require("axios"));
11
- const https_1 = __importDefault(require("https"));
12
- function typeMatches(target, candidate) {
13
- // candidate will accept anything
14
- if (candidate === '*')
15
- return true;
16
- return target === candidate;
17
- }
18
- function mimeMatches(target, candidate) {
19
- return typeMatches(target.type, candidate.type) && typeMatches(target.subtype, candidate.subtype);
20
- }
21
- const httpsAgent = new https_1.default.Agent({
22
- rejectUnauthorized: false
23
- });
24
- async function ensureBuffer(data) {
25
- if (typeof data === 'string') {
26
- const ab = await axios_1.default.get(data, {
27
- responseType: 'arraybuffer',
28
- httpsAgent,
29
- });
30
- return Buffer.from(ab.data);
31
- }
32
- return Buffer.from(data);
33
- }
34
- exports.ensureBuffer = ensureBuffer;
35
- async function convert(converters, mediaObject, toMimeType) {
36
- // console.log('converting', mediaObject.mimeType, toMimeType);
37
- const mediaMime = new whatwg_mimetype_1.default(mediaObject.mimeType);
38
- const outputMime = new whatwg_mimetype_1.default(toMimeType);
39
- if (mimeMatches(mediaMime, outputMime)) {
40
- return {
41
- mimeType: outputMime.essence,
42
- data: await mediaObject.getData(),
43
- };
44
- }
45
- const converterIds = new Map();
46
- const converterReverseids = new Map();
47
- let id = 0;
48
- for (const converter of converters) {
49
- const cid = (id++).toString();
50
- converterIds.set(converter, cid);
51
- converterReverseids.set(cid, converter);
52
- }
53
- const nodes = {};
54
- const mediaNode = {};
55
- nodes['mediaObject'] = mediaNode;
56
- nodes['output'] = {};
57
- for (const converter of converters) {
58
- try {
59
- const inputMime = new whatwg_mimetype_1.default(converter.fromMimeType);
60
- const convertedMime = new whatwg_mimetype_1.default(converter.toMimeType);
61
- const targetId = converterIds.get(converter);
62
- const node = nodes[targetId] = {};
63
- for (const candidate of converters) {
64
- try {
65
- const candidateMime = new whatwg_mimetype_1.default(candidate.fromMimeType);
66
- if (!mimeMatches(convertedMime, candidateMime))
67
- continue;
68
- const candidateId = converterIds.get(candidate);
69
- node[candidateId] = 1;
70
- }
71
- catch (e) {
72
- console.warn('skipping converter due to error', e);
73
- }
74
- }
75
- if (mimeMatches(mediaMime, inputMime)) {
76
- mediaNode[targetId] = 1;
77
- }
78
- if (mimeMatches(convertedMime, outputMime)) {
79
- node['output'] = 1;
80
- }
81
- }
82
- catch (e) {
83
- console.warn('skipping converter due to error', e);
84
- }
85
- }
86
- const graph = new node_dijkstra_1.default();
87
- for (const id of Object.keys(nodes)) {
88
- graph.addNode(id, nodes[id]);
89
- }
90
- const route = graph.path('mediaObject', 'output');
91
- if (!route || !route.length)
92
- throw new Error('no converter found');
93
- // pop off the mediaObject start node, no conversion necessary.
94
- route.shift();
95
- // also remove the output node.
96
- route.splice(route.length - 1);
97
- let value = await mediaObject.getData();
98
- let valueMime = new whatwg_mimetype_1.default(mediaObject.mimeType);
99
- for (const node of route) {
100
- const converter = converterReverseids.get(node);
101
- const targetMime = new whatwg_mimetype_1.default(converter.toMimeType);
102
- const inputMime = new whatwg_mimetype_1.default(converter.fromMimeType);
103
- if (typeof value === 'string' && !inputMime.parameters.has(types_1.ScryptedMimeTypes.AcceptUrlParameter)) {
104
- value = await ensureBuffer(value);
105
- }
106
- value = await converter.convert(value, valueMime.essence);
107
- const type = targetMime.type === '*' ? valueMime.type : targetMime.type;
108
- const subtype = targetMime.subtype === '*' ? valueMime.subtype : targetMime.subtype;
109
- valueMime = new whatwg_mimetype_1.default(`${type}/${subtype}`);
110
- }
111
- return {
112
- data: value,
113
- mimeType: valueMime.essence,
114
- };
115
- }
116
- exports.convert = convert;
117
- //# sourceMappingURL=convert.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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"}
package/src/convert.ts DELETED
@@ -1,122 +0,0 @@
1
- import { BufferConverter, ScryptedMimeTypes } from '@scrypted/sdk/types';
2
- import Graph from 'node-dijkstra';
3
- import MimeType from 'whatwg-mimetype';
4
- import { MediaObjectRemote } from './plugin/plugin-api';
5
- import axios from 'axios';
6
- import https from 'https';
7
-
8
- function typeMatches(target: string, candidate: string): boolean {
9
- // candidate will accept anything
10
- if (candidate === '*')
11
- return true;
12
- return target === candidate;
13
- }
14
-
15
- function mimeMatches(target: MimeType, candidate: MimeType) {
16
- return typeMatches(target.type, candidate.type) && typeMatches(target.subtype, candidate.subtype);
17
- }
18
-
19
- const httpsAgent = new https.Agent({
20
- rejectUnauthorized: false
21
- })
22
-
23
- export async function ensureBuffer(data: Buffer | string): Promise<Buffer> {
24
- if (typeof data === 'string') {
25
- const ab = await axios.get(data as string, {
26
- responseType: 'arraybuffer',
27
- httpsAgent,
28
- });
29
- return Buffer.from(ab.data);
30
- }
31
- return Buffer.from(data);
32
- }
33
-
34
- export async function convert(converters: BufferConverter[], mediaObject: MediaObjectRemote, toMimeType: string): Promise<{ data: Buffer | string, mimeType: string }> {
35
- // console.log('converting', mediaObject.mimeType, toMimeType);
36
- const mediaMime = new MimeType(mediaObject.mimeType);
37
- const outputMime = new MimeType(toMimeType);
38
-
39
- if (mimeMatches(mediaMime, outputMime)) {
40
- return {
41
- mimeType: outputMime.essence,
42
- data: await mediaObject.getData(),
43
- }
44
- }
45
-
46
- const converterIds = new Map<BufferConverter, string>();
47
- const converterReverseids = new Map<string, BufferConverter>();
48
- let id = 0;
49
- for (const converter of converters) {
50
- const cid = (id++).toString();
51
- converterIds.set(converter, cid);
52
- converterReverseids.set(cid, converter);
53
- }
54
-
55
- const nodes: any = {};
56
- const mediaNode: any = {};
57
- nodes['mediaObject'] = mediaNode;
58
- nodes['output'] = {};
59
- for (const converter of converters) {
60
- try {
61
- const inputMime = new MimeType(converter.fromMimeType);
62
- const convertedMime = new MimeType(converter.toMimeType);
63
- const targetId = converterIds.get(converter);
64
- const node: any = nodes[targetId] = {};
65
- for (const candidate of converters) {
66
- try {
67
- const candidateMime = new MimeType(candidate.fromMimeType);
68
- if (!mimeMatches(convertedMime, candidateMime))
69
- continue;
70
- const candidateId = converterIds.get(candidate);
71
- node[candidateId] = 1;
72
- }
73
- catch (e) {
74
- console.warn('skipping converter due to error', e)
75
- }
76
- }
77
-
78
- if (mimeMatches(mediaMime, inputMime)) {
79
- mediaNode[targetId] = 1;
80
- }
81
- if (mimeMatches(convertedMime, outputMime)) {
82
- node['output'] = 1;
83
- }
84
- }
85
- catch (e) {
86
- console.warn('skipping converter due to error', e)
87
- }
88
- }
89
-
90
- const graph = new Graph();
91
- for (const id of Object.keys(nodes)) {
92
- graph.addNode(id, nodes[id]);
93
- }
94
-
95
- const route = graph.path('mediaObject', 'output') as Array<string>;
96
- if (!route || !route.length)
97
- throw new Error('no converter found');
98
- // pop off the mediaObject start node, no conversion necessary.
99
- route.shift();
100
- // also remove the output node.
101
- route.splice(route.length - 1);
102
- let value = await mediaObject.getData();
103
- let valueMime = new MimeType(mediaObject.mimeType);
104
- for (const node of route) {
105
- const converter = converterReverseids.get(node);
106
- const targetMime = new MimeType(converter.toMimeType);
107
- const inputMime = new MimeType(converter.fromMimeType);
108
-
109
- if (typeof value === 'string' && !inputMime.parameters.has(ScryptedMimeTypes.AcceptUrlParameter)) {
110
- value = await ensureBuffer(value);
111
- }
112
- value = await converter.convert(value, valueMime.essence);
113
- const type = targetMime.type === '*' ? valueMime.type : targetMime.type;
114
- const subtype = targetMime.subtype === '*' ? valueMime.subtype : targetMime.subtype;
115
- valueMime = new MimeType(`${type}/${subtype}`);
116
- }
117
-
118
- return {
119
- data: value,
120
- mimeType: valueMime.essence,
121
- };
122
- }