@scrypted/server 0.144.0 → 0.144.2
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/dist/cert.js +1 -1
- package/dist/cert.js.map +1 -1
- package/dist/cluster/cluster-labels.d.ts +3 -3
- package/dist/cluster/cluster-labels.js +2 -2
- package/dist/cluster/cluster-labels.js.map +1 -1
- package/dist/cluster/cluster-setup.d.ts +3 -3
- package/dist/cluster/cluster-setup.js +3 -3
- package/dist/cluster/cluster-setup.js.map +1 -1
- package/dist/db-types.d.ts +4 -4
- package/dist/db-types.js.map +1 -1
- package/dist/event-registry.d.ts +2 -2
- package/dist/event-registry.js +9 -7
- package/dist/event-registry.js.map +1 -1
- package/dist/fetch/index.d.ts +2 -2
- package/dist/fetch/index.js +3 -6
- package/dist/fetch/index.js.map +1 -1
- package/dist/http-interfaces.js +1 -1
- package/dist/http-interfaces.js.map +1 -1
- package/dist/infer-defaults.d.ts +4 -4
- package/dist/infer-defaults.js +8 -4
- package/dist/infer-defaults.js.map +1 -1
- package/dist/ip.js +2 -1
- package/dist/ip.js.map +1 -1
- package/dist/level.d.ts +3 -3
- package/dist/level.js +1 -0
- package/dist/level.js.map +1 -1
- package/dist/listen-zero.js.map +1 -1
- package/dist/mixin/mixin-cycle.js +6 -6
- package/dist/mixin/mixin-cycle.js.map +1 -1
- package/dist/plugin/acl.js.map +1 -1
- package/dist/plugin/cluster.js.map +1 -1
- package/dist/plugin/descriptor.js +1 -1
- package/dist/plugin/descriptor.js.map +1 -1
- package/dist/plugin/device.d.ts +6 -6
- package/dist/plugin/device.js.map +1 -1
- package/dist/plugin/endpoint.js.map +1 -1
- package/dist/plugin/media.js +19 -14
- package/dist/plugin/media.js.map +1 -1
- package/dist/plugin/mediaobject.d.ts +1 -1
- package/dist/plugin/mediaobject.js.map +1 -1
- package/dist/plugin/plugin-api.d.ts +6 -6
- package/dist/plugin/plugin-api.js +2 -2
- package/dist/plugin/plugin-api.js.map +1 -1
- package/dist/plugin/plugin-console.js +11 -10
- package/dist/plugin/plugin-console.js.map +1 -1
- package/dist/plugin/plugin-device.d.ts +3 -3
- package/dist/plugin/plugin-device.js +2 -0
- package/dist/plugin/plugin-device.js.map +1 -1
- package/dist/plugin/plugin-host-api.d.ts +1 -1
- package/dist/plugin/plugin-host-api.js +19 -5
- package/dist/plugin/plugin-host-api.js.map +1 -1
- package/dist/plugin/plugin-host.js +3 -2
- package/dist/plugin/plugin-host.js.map +1 -1
- package/dist/plugin/plugin-http.d.ts +1 -1
- package/dist/plugin/plugin-http.js +5 -1
- package/dist/plugin/plugin-http.js.map +1 -1
- package/dist/plugin/plugin-lazy-remote.js.map +1 -1
- package/dist/plugin/plugin-remote-websocket.js.map +1 -1
- package/dist/plugin/plugin-remote-worker.js +5 -2
- package/dist/plugin/plugin-remote-worker.js.map +1 -1
- package/dist/plugin/plugin-remote.js +1 -1
- package/dist/plugin/plugin-remote.js.map +1 -1
- package/dist/plugin/plugin-repl.js +6 -2
- package/dist/plugin/plugin-repl.js.map +1 -1
- package/dist/plugin/runtime/child-process-worker.d.ts +4 -4
- package/dist/plugin/runtime/child-process-worker.js +1 -2
- package/dist/plugin/runtime/child-process-worker.js.map +1 -1
- package/dist/plugin/runtime/cluster-fork-worker.d.ts +1 -1
- package/dist/plugin/runtime/cluster-fork-worker.js +2 -0
- package/dist/plugin/runtime/cluster-fork-worker.js.map +1 -1
- package/dist/plugin/runtime/custom-worker.js.map +1 -1
- package/dist/plugin/runtime/node-fork-worker.d.ts +1 -1
- package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
- package/dist/plugin/runtime/node-thread-worker.js.map +1 -1
- package/dist/plugin/runtime/python-worker.js +1 -1
- package/dist/plugin/runtime/python-worker.js.map +1 -1
- package/dist/plugin/runtime/runtime-worker.d.ts +1 -1
- package/dist/plugin/system.d.ts +1 -1
- package/dist/plugin/system.js +1 -0
- package/dist/plugin/system.js.map +1 -1
- package/dist/promise-utils.d.ts +1 -1
- package/dist/promise-utils.js.map +1 -1
- package/dist/rpc-buffer-serializer.d.ts +1 -1
- package/dist/rpc-serializer.js.map +1 -1
- package/dist/rpc.d.ts +10 -9
- package/dist/rpc.js +15 -8
- package/dist/rpc.js.map +1 -1
- package/dist/runtime.d.ts +11 -11
- package/dist/runtime.js +17 -18
- package/dist/runtime.js.map +1 -1
- package/dist/scrypted-cluster-main.js +3 -2
- package/dist/scrypted-cluster-main.js.map +1 -1
- package/dist/scrypted-plugin-main.js +1 -1
- package/dist/scrypted-plugin-main.js.map +1 -1
- package/dist/scrypted-server-main.js +8 -5
- package/dist/scrypted-server-main.js.map +1 -1
- package/dist/server-settings.d.ts +1 -1
- package/dist/server-settings.js +4 -4
- package/dist/server-settings.js.map +1 -1
- package/dist/services/addresses.d.ts +1 -1
- package/dist/services/addresses.js +2 -2
- package/dist/services/addresses.js.map +1 -1
- package/dist/services/alerts.js +2 -2
- package/dist/services/alerts.js.map +1 -1
- package/dist/services/cluster-fork.js.map +1 -1
- package/dist/services/plugin.d.ts +5 -5
- package/dist/services/plugin.js.map +1 -1
- package/dist/services/service-control.js.map +1 -1
- package/dist/services/users.d.ts +2 -2
- package/dist/services/users.js.map +1 -1
- package/dist/state.d.ts +7 -7
- package/dist/state.js +4 -4
- package/dist/state.js.map +1 -1
- package/dist/threading.js.map +1 -1
- package/dist/usertoken.d.ts +2 -2
- package/dist/usertoken.js.map +1 -1
- package/package.json +2 -2
- package/python/cluster_setup.py +13 -4
- package/python/plugin_remote.py +22 -18
- package/python/rpc_reader.py +3 -5
- package/src/cert.ts +2 -2
- package/src/cluster/cluster-labels.ts +4 -4
- package/src/cluster/cluster-setup.ts +20 -20
- package/src/db-types.ts +16 -16
- package/src/event-registry.ts +13 -11
- package/src/fetch/index.ts +4 -7
- package/src/http-interfaces.ts +2 -2
- package/src/infer-defaults.ts +12 -8
- package/src/ip.ts +2 -1
- package/src/level.ts +10 -9
- package/src/listen-zero.ts +1 -1
- package/src/mixin/mixin-cycle.ts +6 -6
- package/src/plugin/acl.ts +1 -1
- package/src/plugin/cluster.ts +2 -2
- package/src/plugin/descriptor.ts +2 -2
- package/src/plugin/device.ts +16 -16
- package/src/plugin/endpoint.ts +4 -4
- package/src/plugin/media.ts +34 -29
- package/src/plugin/mediaobject.ts +3 -3
- package/src/plugin/plugin-api.ts +7 -7
- package/src/plugin/plugin-console.ts +13 -12
- package/src/plugin/plugin-device.ts +20 -18
- package/src/plugin/plugin-host-api.ts +27 -13
- package/src/plugin/plugin-host.ts +26 -25
- package/src/plugin/plugin-http.ts +9 -5
- package/src/plugin/plugin-lazy-remote.ts +1 -1
- package/src/plugin/plugin-remote-websocket.ts +1 -1
- package/src/plugin/plugin-remote-worker.ts +22 -20
- package/src/plugin/plugin-remote.ts +14 -14
- package/src/plugin/plugin-repl.ts +6 -2
- package/src/plugin/runtime/child-process-worker.ts +11 -12
- package/src/plugin/runtime/cluster-fork-worker.ts +2 -0
- package/src/plugin/runtime/custom-worker.ts +6 -6
- package/src/plugin/runtime/node-fork-worker.ts +3 -3
- package/src/plugin/runtime/node-thread-worker.ts +3 -3
- package/src/plugin/runtime/python-worker.ts +14 -14
- package/src/plugin/runtime/runtime-worker.ts +1 -1
- package/src/plugin/system.ts +24 -23
- package/src/promise-utils.ts +4 -4
- package/src/rpc-serializer.ts +3 -3
- package/src/rpc.ts +25 -17
- package/src/runtime.ts +59 -60
- package/src/scrypted-cluster-main.ts +19 -18
- package/src/scrypted-plugin-main.ts +2 -2
- package/src/scrypted-server-main.ts +17 -14
- package/src/server-settings.ts +5 -5
- package/src/services/addresses.ts +3 -3
- package/src/services/alerts.ts +2 -2
- package/src/services/cluster-fork.ts +9 -9
- package/src/services/plugin.ts +15 -15
- package/src/services/service-control.ts +1 -1
- package/src/services/users.ts +3 -3
- package/src/state.ts +21 -21
- package/src/threading.ts +5 -5
- package/src/usertoken.ts +1 -1
package/src/db-types.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { LevelDocument } from "./level";
|
|
|
2
2
|
import { ScryptedNativeId, SystemDeviceState } from "@scrypted/types";
|
|
3
3
|
|
|
4
4
|
export class ScryptedDocument implements LevelDocument {
|
|
5
|
-
_id
|
|
6
|
-
_documentType
|
|
5
|
+
_id!: string;
|
|
6
|
+
_documentType!: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export class Settings extends ScryptedDocument {
|
|
@@ -16,28 +16,28 @@ export class Plugin extends ScryptedDocument {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export class ScryptedUser extends ScryptedDocument {
|
|
19
|
-
passwordDate
|
|
20
|
-
passwordHash
|
|
21
|
-
token
|
|
22
|
-
salt
|
|
23
|
-
aclId
|
|
19
|
+
passwordDate!: number;
|
|
20
|
+
passwordHash!: string;
|
|
21
|
+
token!: string;
|
|
22
|
+
salt!: string;
|
|
23
|
+
aclId?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export class ScryptedAlert extends ScryptedDocument {
|
|
27
|
-
timestamp
|
|
28
|
-
title
|
|
29
|
-
path
|
|
30
|
-
message
|
|
27
|
+
timestamp!: number;
|
|
28
|
+
title!: string;
|
|
29
|
+
path!: string;
|
|
30
|
+
message!: string;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export class PluginDevice extends ScryptedDocument {
|
|
34
|
-
constructor(id
|
|
34
|
+
constructor(id: string) {
|
|
35
35
|
super();
|
|
36
36
|
this._id = id;
|
|
37
37
|
}
|
|
38
38
|
nativeId: ScryptedNativeId;
|
|
39
|
-
pluginId
|
|
40
|
-
state
|
|
41
|
-
stateVersion
|
|
42
|
-
storage
|
|
39
|
+
pluginId!: string;
|
|
40
|
+
state!: { [property: string]: SystemDeviceState };
|
|
41
|
+
stateVersion!: number;
|
|
42
|
+
storage!: { [key: string]: string };
|
|
43
43
|
}
|
package/src/event-registry.ts
CHANGED
|
@@ -29,10 +29,11 @@ export class EventRegistry {
|
|
|
29
29
|
|
|
30
30
|
listen(callback: (id: string, eventDetails: EventDetails, eventData: any) => void): EventListenerRegister {
|
|
31
31
|
const events = this.systemListeners;
|
|
32
|
-
|
|
32
|
+
let cb: typeof callback | undefined = callback;
|
|
33
|
+
events.add(cb);
|
|
33
34
|
return new EventListenerRegisterImpl(() => {
|
|
34
|
-
events.delete(
|
|
35
|
-
|
|
35
|
+
events.delete(cb!);
|
|
36
|
+
cb = undefined;
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -45,14 +46,15 @@ export class EventRegistry {
|
|
|
45
46
|
this.listeners[token] = events;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
let cb: typeof callback | undefined = callback;
|
|
50
|
+
events.add(cb);
|
|
49
51
|
return new EventListenerRegisterImpl(() => {
|
|
50
|
-
events.delete(
|
|
51
|
-
|
|
52
|
+
events.delete(cb!);
|
|
53
|
+
cb = undefined;
|
|
52
54
|
});
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
notify(id: string | undefined, eventTime: number, eventInterface: string, property: string | undefined, value: any, options?: {
|
|
57
|
+
notify(id: string | undefined, eventTime: number | undefined, eventInterface: string, property: string | undefined, value: any, options?: {
|
|
56
58
|
changed?: boolean;
|
|
57
59
|
mixinId?: string;
|
|
58
60
|
}): boolean {
|
|
@@ -62,9 +64,9 @@ export class EventRegistry {
|
|
|
62
64
|
return false;
|
|
63
65
|
|
|
64
66
|
const eventDetails: EventDetails = {
|
|
65
|
-
eventId: undefined
|
|
67
|
+
eventId: undefined!,
|
|
66
68
|
eventInterface,
|
|
67
|
-
eventTime
|
|
69
|
+
eventTime: eventTime!,
|
|
68
70
|
property,
|
|
69
71
|
mixinId,
|
|
70
72
|
};
|
|
@@ -79,9 +81,9 @@ export class EventRegistry {
|
|
|
79
81
|
// system listeners only get state changes.
|
|
80
82
|
// there are many potentially noisy stateless events, like
|
|
81
83
|
// object detection and settings changes.
|
|
82
|
-
if ((eventDetails.property && !eventDetails.mixinId) || allowedEventInterfaces.has(eventInterface)) {
|
|
84
|
+
if ((eventDetails.property && !eventDetails.mixinId) || allowedEventInterfaces.has(eventInterface!)) {
|
|
83
85
|
for (const event of this.systemListeners) {
|
|
84
|
-
event(id
|
|
86
|
+
event(id!, eventDetails, value);
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
|
package/src/fetch/index.ts
CHANGED
|
@@ -66,14 +66,14 @@ export type fetcher<B, M> = <T extends HttpFetchOptions<B>>(options: T) => Promi
|
|
|
66
66
|
>>;
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
export function getHttpFetchAccept(responseType: HttpFetchResponseType | undefined) {
|
|
69
|
+
export function getHttpFetchAccept(responseType: HttpFetchResponseType | undefined): string | undefined {
|
|
70
70
|
switch (responseType) {
|
|
71
71
|
case 'json':
|
|
72
72
|
return 'application/json';
|
|
73
73
|
case 'text':
|
|
74
74
|
return 'text/plain';
|
|
75
75
|
}
|
|
76
|
-
return;
|
|
76
|
+
return undefined;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
export function hasHeader(headers: [string, string][], key: string) {
|
|
@@ -119,10 +119,7 @@ export function createHeadersArray(headers: HeadersInit | undefined): [string, s
|
|
|
119
119
|
return headersArray;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
const v = headers[k];
|
|
124
|
-
headersArray.push([k, v]);
|
|
125
|
-
}
|
|
122
|
+
headersArray.push(...Object.entries(headers));
|
|
126
123
|
|
|
127
124
|
return headersArray;
|
|
128
125
|
}
|
|
@@ -135,7 +132,7 @@ export function createHeadersArray(headers: HeadersInit | undefined): [string, s
|
|
|
135
132
|
*/
|
|
136
133
|
export function createStringOrBufferBody(headers: [string, string][], body: any) {
|
|
137
134
|
let contentType: string | undefined;
|
|
138
|
-
if (typeof body === 'object') {
|
|
135
|
+
if (typeof body === 'object' && !ArrayBuffer.isView(body)) {
|
|
139
136
|
body = JSON.stringify(body);
|
|
140
137
|
contentType = 'application/json';
|
|
141
138
|
}
|
package/src/http-interfaces.ts
CHANGED
|
@@ -63,7 +63,7 @@ export class HttpResponseImpl implements HttpResponse {
|
|
|
63
63
|
|
|
64
64
|
// prefer etag
|
|
65
65
|
this.res.sendFile(filePath, {
|
|
66
|
-
root:
|
|
66
|
+
root: undefined,
|
|
67
67
|
dotfiles: 'allow',
|
|
68
68
|
cacheControl: false,
|
|
69
69
|
});
|
|
@@ -110,7 +110,7 @@ export class HttpResponseImpl implements HttpResponse {
|
|
|
110
110
|
this.res.end();
|
|
111
111
|
}
|
|
112
112
|
catch (e) {
|
|
113
|
-
this.res.destroy(e);
|
|
113
|
+
this.res.destroy(e as Error);
|
|
114
114
|
}
|
|
115
115
|
finally {
|
|
116
116
|
peer.kill();
|
package/src/infer-defaults.ts
CHANGED
|
@@ -36,12 +36,16 @@ addType(ScryptedInterface.HttpRequestHandler, ScryptedDeviceType.DataSource);
|
|
|
36
36
|
addType(ScryptedInterface.BufferConverter, ScryptedDeviceType.API);
|
|
37
37
|
addType(ScryptedInterface.DeviceProvider, ScryptedDeviceType.DeviceProvider);
|
|
38
38
|
|
|
39
|
-
export function inferTypeFromInterfaces(interfaces: ScryptedInterface[]): ScryptedDeviceType {
|
|
39
|
+
export function inferTypeFromInterfaces(interfaces: ScryptedInterface[]): ScryptedDeviceType | undefined {
|
|
40
40
|
return inferTypesFromInterfaces(interfaces)[0];
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export function inferTypesFromInterfaces(interfaces: ScryptedInterface[]): ScryptedDeviceType[] {
|
|
44
|
-
const types = Object.keys(inferenceTable)
|
|
44
|
+
const types = Object.keys(inferenceTable)
|
|
45
|
+
.filter(iface => interfaces.includes(iface as ScryptedInterface))
|
|
46
|
+
.map(iface => inferenceTable[iface])
|
|
47
|
+
.filter((types): types is ScryptedDeviceType[] => types !== undefined)
|
|
48
|
+
.flat();
|
|
45
49
|
return types;
|
|
46
50
|
}
|
|
47
51
|
|
|
@@ -96,24 +100,24 @@ const roomHints: { [hint: string]: string } = {
|
|
|
96
100
|
'Laundry': 'Laundry Room',
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
export function inferRoomFromName(name: string): string {
|
|
103
|
+
export function inferRoomFromName(name: string): string | undefined {
|
|
100
104
|
if (!name)
|
|
101
|
-
return;
|
|
105
|
+
return undefined;
|
|
102
106
|
for (const hint of Object.keys(roomHints)) {
|
|
103
107
|
if (name.includes(hint))
|
|
104
108
|
return roomHints[hint];
|
|
105
109
|
}
|
|
110
|
+
return undefined;
|
|
106
111
|
}
|
|
107
112
|
|
|
108
|
-
export function getProvidedRoomOrDefault(pluginDevice: PluginDevice): string {
|
|
113
|
+
export function getProvidedRoomOrDefault(pluginDevice: PluginDevice): string | undefined {
|
|
109
114
|
const providedRoom = getState(pluginDevice, ScryptedInterfaceProperty.providedRoom);
|
|
110
115
|
if (providedRoom)
|
|
111
116
|
return providedRoom;
|
|
112
|
-
|
|
113
|
-
return room;
|
|
117
|
+
return inferRoomFromName(getDisplayName(pluginDevice));
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
export function getDisplayRoom(pluginDevice: PluginDevice): string {
|
|
120
|
+
export function getDisplayRoom(pluginDevice: PluginDevice): string | undefined {
|
|
117
121
|
const room = getState(pluginDevice, ScryptedInterfaceProperty.room);
|
|
118
122
|
if (room)
|
|
119
123
|
return room;
|
package/src/ip.ts
CHANGED
|
@@ -70,6 +70,7 @@ export function getUsableNetworkAddresses() {
|
|
|
70
70
|
const getUsable = (family: string | number) => {
|
|
71
71
|
const usable = Object.values(nis)
|
|
72
72
|
.flat()
|
|
73
|
+
.filter((details): details is os.NetworkInterfaceInfo => !!details)
|
|
73
74
|
.filter((details) => details.family === family)
|
|
74
75
|
.filter(details => isUsableNetworkAddress(details.address));
|
|
75
76
|
return usable;
|
|
@@ -84,7 +85,7 @@ export function getUsableNetworkAddresses() {
|
|
|
84
85
|
const fixedAddresses = ipv6.filter(details => details.address.includes('::'));
|
|
85
86
|
const fixedRanges = fixedAddresses.map(details => {
|
|
86
87
|
const block = new net.BlockList();
|
|
87
|
-
const cidr = parseInt(details.address.split('/')[1]) || 1;
|
|
88
|
+
const cidr = parseInt(details.address.split('/')[1] ?? '') || 1;
|
|
88
89
|
block.addSubnet(details.address, cidr, 'ipv6');
|
|
89
90
|
return block;
|
|
90
91
|
});
|
package/src/level.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { GetOptions, Level, OpenOptions, PutOptions } from 'level';
|
|
2
2
|
|
|
3
3
|
export interface LevelDocument {
|
|
4
|
-
_id
|
|
5
|
-
_documentType
|
|
4
|
+
_id: any;
|
|
5
|
+
_documentType: string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export interface LevelDocumentConstructor<T extends LevelDocument> {
|
|
@@ -16,11 +16,11 @@ function createLevelDocument(documentConstructor: any, json: any) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export class WrappedLevel extends Level<string, string | number> {
|
|
19
|
-
curId
|
|
19
|
+
curId!: number;
|
|
20
20
|
|
|
21
|
-
async open(): Promise<void>;
|
|
22
|
-
async open(options?: OpenOptions): Promise<void> {
|
|
23
|
-
await super.open(options);
|
|
21
|
+
override async open(): Promise<void>;
|
|
22
|
+
override async open(options?: OpenOptions): Promise<void> {
|
|
23
|
+
await super.open(options!);
|
|
24
24
|
try {
|
|
25
25
|
this.curId = parseInt(await this.get('_id') as string);
|
|
26
26
|
}
|
|
@@ -31,14 +31,15 @@ export class WrappedLevel extends Level<string, string | number> {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
async tryGet<T>(documentConstructor: new () => T, _id: any, options?: GetOptions<string, string | number>): Promise<T> {
|
|
34
|
+
async tryGet<T>(documentConstructor: new () => T, _id: any, options?: GetOptions<string, string | number>): Promise<T | undefined> {
|
|
35
35
|
try {
|
|
36
36
|
const _documentType = documentConstructor.name;
|
|
37
37
|
const key = `${_documentType}/${_id}`;
|
|
38
|
-
const json = await this.get(key, options)
|
|
38
|
+
const json = await this.get(key, options!)
|
|
39
39
|
return createLevelDocument(documentConstructor, json);
|
|
40
40
|
}
|
|
41
41
|
catch (e) {
|
|
42
|
+
return undefined;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -82,7 +83,7 @@ export class WrappedLevel extends Level<string, string | number> {
|
|
|
82
83
|
|
|
83
84
|
value._documentType = _documentType;
|
|
84
85
|
const key = `${_documentType}/${value._id}`;
|
|
85
|
-
await this.put(key, JSON.stringify(value), options);
|
|
86
|
+
await this.put(key, JSON.stringify(value), options!);
|
|
86
87
|
return value;
|
|
87
88
|
};
|
|
88
89
|
|
package/src/listen-zero.ts
CHANGED
|
@@ -18,7 +18,7 @@ export async function listenZeroSingleClient(hostname: string, options?: net.Ser
|
|
|
18
18
|
const server = options?.tls ? new tls.Server(options) : new net.Server(options);
|
|
19
19
|
const port = await listenZero(server, hostname);
|
|
20
20
|
|
|
21
|
-
let cancel
|
|
21
|
+
let cancel!: () => void;
|
|
22
22
|
const clientPromise = new Promise<net.Socket>((resolve, reject) => {
|
|
23
23
|
const timeout = setTimeout(() => {
|
|
24
24
|
server.close();
|
package/src/mixin/mixin-cycle.ts
CHANGED
|
@@ -10,22 +10,22 @@ export function getMixins(scrypted: ScryptedRuntime, id: string) {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function hasMixinCycle(scrypted: ScryptedRuntime, id: string, mixins?: string[]) {
|
|
13
|
-
|
|
13
|
+
let mixinsList = mixins || getMixins(scrypted, id);
|
|
14
14
|
|
|
15
15
|
// given the mixins for a device, find all the mixins for those mixins,
|
|
16
16
|
// and create a visited graph.
|
|
17
17
|
// if the visited graphs includes the original device, that indicates
|
|
18
18
|
// a cyclical dependency for that device.
|
|
19
|
-
const visitedMixins = new Set(
|
|
19
|
+
const visitedMixins = new Set(mixinsList);
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
while (
|
|
23
|
-
const mixin =
|
|
21
|
+
mixinsList = mixinsList.slice();
|
|
22
|
+
while (mixinsList.length) {
|
|
23
|
+
const mixin = mixinsList.pop()!;
|
|
24
24
|
if (visitedMixins.has(mixin))
|
|
25
25
|
continue;
|
|
26
26
|
visitedMixins.add(mixin);
|
|
27
27
|
const providerMixins = getMixins(scrypted, mixin);
|
|
28
|
-
|
|
28
|
+
mixinsList.push(...providerMixins);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
return visitedMixins.has(id);
|
package/src/plugin/acl.ts
CHANGED
|
@@ -61,7 +61,7 @@ export class AccessControls {
|
|
|
61
61
|
const { eventInterface } = eventDetails;
|
|
62
62
|
|
|
63
63
|
for (const dacl of dacls) {
|
|
64
|
-
if (!dacl.interfaces || dacl.interfaces.includes(eventInterface))
|
|
64
|
+
if (!dacl.interfaces || dacl.interfaces.includes(eventInterface!))
|
|
65
65
|
return false;
|
|
66
66
|
}
|
|
67
67
|
|
package/src/plugin/cluster.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface ClusterForkServiceInterface {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export class ClusterManagerImpl implements ClusterManager {
|
|
9
|
-
private clusterServicePromise
|
|
9
|
+
private clusterServicePromise!: Promise<ClusterForkServiceInterface>;
|
|
10
10
|
|
|
11
11
|
constructor(public clusterMode: undefined | 'client' | 'server', private api: PluginAPI, private clusterWorkerId: string) {
|
|
12
12
|
}
|
|
@@ -16,7 +16,7 @@ export class ClusterManagerImpl implements ClusterManager {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
getClusterAddress(): string {
|
|
19
|
-
return process.env.SCRYPTED_CLUSTER_ADDRESS
|
|
19
|
+
return process.env.SCRYPTED_CLUSTER_ADDRESS!;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
getClusterMode(): 'server' | 'client' | undefined {
|
package/src/plugin/descriptor.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ScryptedInterface, ScryptedInterfaceDescriptor, ScryptedInterfaceDescriptors } from "@scrypted/types";
|
|
2
2
|
|
|
3
|
-
export const allInterfaceProperties: string[] =
|
|
3
|
+
export const allInterfaceProperties: string[] = Object.values(ScryptedInterfaceDescriptors).map(type => type.properties).flat();
|
|
4
4
|
|
|
5
5
|
export function getPropertyInterfaces(descriptors: { [scryptedInterface: string]: ScryptedInterfaceDescriptor }) {
|
|
6
6
|
const propertyInterfaces: { [property: string]: ScryptedInterface } = {};
|
|
@@ -26,7 +26,7 @@ export function getInterfaceProperties(descriptors: { [scryptedInterface: string
|
|
|
26
26
|
|
|
27
27
|
export function isValidInterfaceMethod(descriptors: { [scryptedInterface: string]: ScryptedInterfaceDescriptor }, interfaces: Set<string>, method: string) {
|
|
28
28
|
const availableMethods = getInterfaceMethods(descriptors, interfaces);
|
|
29
|
-
return availableMethods.includes(method) || descriptors[ScryptedInterface.ScryptedDevice]
|
|
29
|
+
return availableMethods.includes(method) || descriptors[ScryptedInterface.ScryptedDevice]!.methods.includes(method);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export function isValidInterfaceProperty(descriptors: { [scryptedInterface: string]: ScryptedInterfaceDescriptor }, interfaces: string[], property: string): boolean {
|
package/src/plugin/device.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { SystemManagerImpl } from './system';
|
|
|
7
7
|
class DeviceLogger implements Logger {
|
|
8
8
|
nativeId: ScryptedNativeId;
|
|
9
9
|
api: PluginAPI;
|
|
10
|
-
logger
|
|
10
|
+
logger!: Promise<PluginLogger>;
|
|
11
11
|
|
|
12
12
|
constructor(api: PluginAPI, nativeId: ScryptedNativeId, public console: any) {
|
|
13
13
|
this.api = api;
|
|
@@ -65,12 +65,12 @@ export class DeviceStateProxyHandler implements ProxyHandler<any> {
|
|
|
65
65
|
return { id: this.id }
|
|
66
66
|
if (p === 'setState')
|
|
67
67
|
return this.setState;
|
|
68
|
-
return this.deviceManager.systemManager.state[this.id][p as string]?.value;
|
|
68
|
+
return this.deviceManager.systemManager.state[this.id]![p as string]?.value;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
set?(target: any, p: PropertyKey, value: any, receiver: any) {
|
|
72
72
|
checkProperty(p.toString(), value);
|
|
73
|
-
this.deviceManager.systemManager.state[this.id][p as string] = {
|
|
73
|
+
this.deviceManager.systemManager.state[this.id]![p as string] = {
|
|
74
74
|
value,
|
|
75
75
|
};
|
|
76
76
|
this.setState(p.toString(), value);
|
|
@@ -84,10 +84,10 @@ interface DeviceManagerDevice {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
export class DeviceManagerImpl implements DeviceManager {
|
|
87
|
-
api
|
|
88
|
-
nativeIds = new Map<
|
|
89
|
-
deviceStorage = new Map<
|
|
90
|
-
mixinStorage = new Map<
|
|
87
|
+
api!: PluginAPI;
|
|
88
|
+
nativeIds = new Map<ScryptedNativeId, DeviceManagerDevice>();
|
|
89
|
+
deviceStorage = new Map<ScryptedNativeId, StorageImpl>();
|
|
90
|
+
mixinStorage = new Map<ScryptedNativeId, Map<string, StorageImpl>>();
|
|
91
91
|
|
|
92
92
|
constructor(public systemManager: SystemManagerImpl,
|
|
93
93
|
public getDeviceConsole: (nativeId?: ScryptedNativeId) => Console,
|
|
@@ -103,7 +103,7 @@ export class DeviceManagerImpl implements DeviceManager {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
getDeviceState(nativeId?: any): DeviceState {
|
|
106
|
-
const handler = new DeviceStateProxyHandler(this, this.nativeIds.get(nativeId)
|
|
106
|
+
const handler = new DeviceStateProxyHandler(this, this.nativeIds.get(nativeId)!.id,
|
|
107
107
|
(property, value) => this.api.setState(nativeId, property, value));
|
|
108
108
|
return new Proxy(handler, handler);
|
|
109
109
|
}
|
|
@@ -136,7 +136,7 @@ export class DeviceManagerImpl implements DeviceManager {
|
|
|
136
136
|
}
|
|
137
137
|
pruneMixinStorage() {
|
|
138
138
|
for (const nativeId of this.nativeIds.keys()) {
|
|
139
|
-
const storage = this.nativeIds.get(nativeId)
|
|
139
|
+
const storage = this.nativeIds.get(nativeId)!.storage;
|
|
140
140
|
for (const key of Object.keys(storage)) {
|
|
141
141
|
if (!key.startsWith('mixin:'))
|
|
142
142
|
continue;
|
|
@@ -152,7 +152,7 @@ export class DeviceManagerImpl implements DeviceManager {
|
|
|
152
152
|
async onMixinEvent(id: string, nativeId: ScryptedNativeId, eventInterface: string, eventData: any) {
|
|
153
153
|
return this.api.onMixinEvent(id, nativeId, eventInterface, eventData);
|
|
154
154
|
}
|
|
155
|
-
getNativeIds():
|
|
155
|
+
getNativeIds(): ScryptedNativeId[] {
|
|
156
156
|
return Array.from(this.nativeIds.keys());
|
|
157
157
|
}
|
|
158
158
|
async onDeviceDiscovered(device: Device) {
|
|
@@ -219,20 +219,20 @@ export class StorageImpl implements Storage {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
get storage(): { [key: string]: any } {
|
|
222
|
-
return this.deviceManager.nativeIds.get(this.nativeId)
|
|
222
|
+
return this.deviceManager.nativeIds.get(this.nativeId)!.storage;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
get length(): number {
|
|
226
|
-
return Object.keys(this.storage).filter(key => key.startsWith(this.prefix)).length;
|
|
226
|
+
return Object.keys(this.storage).filter(key => key.startsWith(this.prefix!)).length;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
clear(): void {
|
|
230
230
|
if (!this.prefix) {
|
|
231
|
-
this.deviceManager.nativeIds.get(this.nativeId)
|
|
231
|
+
this.deviceManager.nativeIds.get(this.nativeId)!.storage = {};
|
|
232
232
|
}
|
|
233
233
|
else {
|
|
234
234
|
const storage = this.storage;
|
|
235
|
-
Object.keys(this.storage).filter(key => key.startsWith(this.prefix)).forEach(key => delete storage[key]);
|
|
235
|
+
Object.keys(this.storage).filter(key => key.startsWith(this.prefix!)).forEach(key => delete storage[key]);
|
|
236
236
|
}
|
|
237
237
|
this.api.setStorage(this.nativeId, this.storage);
|
|
238
238
|
}
|
|
@@ -242,9 +242,9 @@ export class StorageImpl implements Storage {
|
|
|
242
242
|
}
|
|
243
243
|
key(index: number): string {
|
|
244
244
|
if (!this.prefix) {
|
|
245
|
-
return Object.keys(this.storage)[index]
|
|
245
|
+
return Object.keys(this.storage)[index]!;
|
|
246
246
|
}
|
|
247
|
-
return Object.keys(this.storage).filter(key => key.startsWith(this.prefix))[index]
|
|
247
|
+
return Object.keys(this.storage).filter(key => key.startsWith(this.prefix!))[index]!.substring(this.prefix!.length);
|
|
248
248
|
}
|
|
249
249
|
removeItem(key: string): void {
|
|
250
250
|
delete this.storage[this.prefix + key];
|
package/src/plugin/endpoint.ts
CHANGED
|
@@ -3,10 +3,10 @@ import type { DeviceManagerImpl } from "./device";
|
|
|
3
3
|
import type { PluginAPI } from "./plugin-api";
|
|
4
4
|
|
|
5
5
|
export class EndpointManagerImpl implements EndpointManager {
|
|
6
|
-
deviceManager
|
|
7
|
-
api
|
|
8
|
-
pluginId
|
|
9
|
-
mediaManager
|
|
6
|
+
deviceManager!: DeviceManagerImpl;
|
|
7
|
+
api!: PluginAPI;
|
|
8
|
+
pluginId!: string;
|
|
9
|
+
mediaManager!: MediaManager;
|
|
10
10
|
|
|
11
11
|
getEndpoint(nativeId?: ScryptedNativeId) {
|
|
12
12
|
if (!nativeId)
|
package/src/plugin/media.ts
CHANGED
|
@@ -208,20 +208,25 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
208
208
|
.map(([id]) => {
|
|
209
209
|
const device = this.getDeviceById<MediaConverter & BufferConverter>(id);
|
|
210
210
|
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
211
|
+
try {
|
|
212
|
+
return (device.converters || []).map(([fromMimeType, toMimeType], index) => {
|
|
213
|
+
return {
|
|
214
|
+
id: `${id}-${index}`,
|
|
215
|
+
name: device.name,
|
|
216
|
+
fromMimeType,
|
|
217
|
+
toMimeType,
|
|
218
|
+
convert(data, fromMimeType, toMimeType, options?) {
|
|
219
|
+
// MediaConverter is injected the plugin's node runtime which may be compiled against an
|
|
220
|
+
// older sdk that does not have MediaConverter. use the older convert method instead.
|
|
221
|
+
// once BufferConverter is removed, this can be simplified to device.convertMedia.
|
|
222
|
+
return (device.convertMedia || device.convert)(data, fromMimeType, toMimeType, options);
|
|
223
|
+
},
|
|
224
|
+
} as IdBufferConverter;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (e) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
225
230
|
});
|
|
226
231
|
|
|
227
232
|
const converters = [...mediaConverters.flat(), ...bufferConverters];
|
|
@@ -343,7 +348,7 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
343
348
|
fromMimeType: mediaObject.mimeType,
|
|
344
349
|
toMimeType,
|
|
345
350
|
convert: async (data, fromMimeType, toMimeType) => {
|
|
346
|
-
return mediaObject.convert(toMimeType);
|
|
351
|
+
return mediaObject.convert!(toMimeType);
|
|
347
352
|
}
|
|
348
353
|
});
|
|
349
354
|
|
|
@@ -361,10 +366,10 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
361
366
|
// connect the intrinsic converter to other converters
|
|
362
367
|
for (const candidate of converters) {
|
|
363
368
|
try {
|
|
364
|
-
const candidateMime = new MimeType(candidate.fromMimeType);
|
|
369
|
+
const candidateMime = new MimeType(candidate.fromMimeType!);
|
|
365
370
|
if (!mimeMatches(convertedMime, candidateMime))
|
|
366
371
|
continue;
|
|
367
|
-
const outputWeight = parseFloat(candidateMime.parameters.get('converter-weight')) || (candidateMime.essence === '*/*' ? 1000 : 1);
|
|
372
|
+
const outputWeight = parseFloat(candidateMime.parameters.get('converter-weight')!) || (candidateMime.essence === '*/*' ? 1000 : 1);
|
|
368
373
|
const candidateId = candidate.id;
|
|
369
374
|
node[candidateId] = outputWeight;
|
|
370
375
|
}
|
|
@@ -376,10 +381,10 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
376
381
|
|
|
377
382
|
for (const converter of converters) {
|
|
378
383
|
try {
|
|
379
|
-
const inputMime = new MimeType(converter.fromMimeType);
|
|
380
|
-
const convertedMime = new MimeType(converter.toMimeType);
|
|
384
|
+
const inputMime = new MimeType(converter.fromMimeType!);
|
|
385
|
+
const convertedMime = new MimeType(converter.toMimeType!);
|
|
381
386
|
// catch all converters should be heavily weighted so as not to use them.
|
|
382
|
-
const inputWeight = parseFloat(inputMime.parameters.get('converter-weight')) || (inputMime.essence === '*/*' ? 1000 : 1);
|
|
387
|
+
const inputWeight = parseFloat(inputMime.parameters.get('converter-weight')!) || (inputMime.essence === '*/*' ? 1000 : 1);
|
|
383
388
|
// const convertedWeight = parseFloat(convertedMime.parameters.get('converter-weight')) || (convertedMime.essence === ScryptedMimeTypes.MediaObject ? 1000 : 1);
|
|
384
389
|
// const conversionWeight = inputWeight + convertedWeight;
|
|
385
390
|
const targetId = converter.id;
|
|
@@ -388,10 +393,10 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
388
393
|
// edge matches
|
|
389
394
|
for (const candidate of converters) {
|
|
390
395
|
try {
|
|
391
|
-
const candidateMime = new MimeType(candidate.fromMimeType);
|
|
396
|
+
const candidateMime = new MimeType(candidate.fromMimeType!);
|
|
392
397
|
if (!mimeMatches(convertedMime, candidateMime))
|
|
393
398
|
continue;
|
|
394
|
-
const outputWeight = parseFloat(candidateMime.parameters.get('converter-weight')) || (candidateMime.essence === '*/*' ? 1000 : 1);
|
|
399
|
+
const outputWeight = parseFloat(candidateMime.parameters.get('converter-weight')!) || (candidateMime.essence === '*/*' ? 1000 : 1);
|
|
395
400
|
const candidateId = candidate.id;
|
|
396
401
|
node[candidateId] = inputWeight + outputWeight;
|
|
397
402
|
}
|
|
@@ -431,23 +436,23 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
431
436
|
let valueMime = new MimeType(mediaObject.mimeType);
|
|
432
437
|
|
|
433
438
|
while (route.length) {
|
|
434
|
-
const node = route.shift()
|
|
435
|
-
const converter = converterMap.get(node)
|
|
436
|
-
const converterToMimeType = new MimeType(converter.toMimeType);
|
|
437
|
-
const converterFromMimeType = new MimeType(converter.fromMimeType);
|
|
439
|
+
const node = route.shift()!;
|
|
440
|
+
const converter = converterMap.get(node)!;
|
|
441
|
+
const converterToMimeType = new MimeType(converter.toMimeType!);
|
|
442
|
+
const converterFromMimeType = new MimeType(converter.fromMimeType!);
|
|
438
443
|
const type = converterToMimeType.type === '*' ? valueMime.type : converterToMimeType.type;
|
|
439
444
|
const subtype = converterToMimeType.subtype === '*' ? valueMime.subtype : converterToMimeType.subtype;
|
|
440
445
|
let targetMimeType = `${type}/${subtype}`;
|
|
441
446
|
if (!route.length && outputMime.parameters.size) {
|
|
442
447
|
const withParameters = new MimeType(targetMimeType);
|
|
443
448
|
for (const k of outputMime.parameters.keys()) {
|
|
444
|
-
withParameters.parameters.set(k, outputMime.parameters.get(k));
|
|
449
|
+
withParameters.parameters.set(k, outputMime.parameters.get(k)!);
|
|
445
450
|
}
|
|
446
451
|
targetMimeType = outputMime.toString();
|
|
447
452
|
}
|
|
448
453
|
|
|
449
454
|
if (converter.toMimeType === ScryptedMimeTypes.MediaObject) {
|
|
450
|
-
const mo = await converter.convert(value, valueMime.essence, toMimeType, { sourceId }) as MediaObjectInterface;
|
|
455
|
+
const mo = await converter.convert!(value, valueMime.essence, toMimeType, { sourceId }) as MediaObjectInterface;
|
|
451
456
|
const found = await this.convertMediaObject(mo, toMimeType);
|
|
452
457
|
return {
|
|
453
458
|
data: found,
|
|
@@ -455,7 +460,7 @@ export abstract class MediaManagerBase implements MediaManager {
|
|
|
455
460
|
};
|
|
456
461
|
}
|
|
457
462
|
|
|
458
|
-
value = await converter.convert(value, valueMime.essence, targetMimeType, { sourceId }) as string | Buffer;
|
|
463
|
+
value = await converter.convert!(value, valueMime.essence, targetMimeType, { sourceId }) as string | Buffer;
|
|
459
464
|
valueMime = new MimeType(targetMimeType);
|
|
460
465
|
}
|
|
461
466
|
|
|
@@ -5,12 +5,12 @@ import { MediaObjectRemote } from "./plugin-api";
|
|
|
5
5
|
export class MediaObject implements MediaObjectRemote {
|
|
6
6
|
__proxy_props: any;
|
|
7
7
|
|
|
8
|
-
constructor(public mimeType: string, public data: any, options
|
|
8
|
+
constructor(public mimeType: string, public data: any, options?: MediaObjectCreateOptions) {
|
|
9
9
|
this.__proxy_props = {}
|
|
10
10
|
options ||= {};
|
|
11
11
|
options.mimeType = mimeType;
|
|
12
|
-
options
|
|
13
|
-
options
|
|
12
|
+
options!.convert ||= null!;
|
|
13
|
+
options!.toMimeTypes ||= null!;
|
|
14
14
|
|
|
15
15
|
for (const [key, value] of Object.entries(options)) {
|
|
16
16
|
if (RpcPeer.isTransportSafe(value))
|