@scrypted/server 0.144.1 → 0.144.3

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.
Files changed (174) hide show
  1. package/dist/cert.js +1 -1
  2. package/dist/cert.js.map +1 -1
  3. package/dist/cluster/cluster-labels.d.ts +3 -3
  4. package/dist/cluster/cluster-labels.js +2 -2
  5. package/dist/cluster/cluster-labels.js.map +1 -1
  6. package/dist/cluster/cluster-setup.d.ts +3 -3
  7. package/dist/cluster/cluster-setup.js +3 -3
  8. package/dist/cluster/cluster-setup.js.map +1 -1
  9. package/dist/db-types.d.ts +4 -4
  10. package/dist/db-types.js.map +1 -1
  11. package/dist/event-registry.d.ts +2 -2
  12. package/dist/event-registry.js +9 -7
  13. package/dist/event-registry.js.map +1 -1
  14. package/dist/fetch/index.d.ts +2 -2
  15. package/dist/fetch/index.js +3 -6
  16. package/dist/fetch/index.js.map +1 -1
  17. package/dist/http-interfaces.js +1 -1
  18. package/dist/http-interfaces.js.map +1 -1
  19. package/dist/infer-defaults.d.ts +4 -4
  20. package/dist/infer-defaults.js +8 -4
  21. package/dist/infer-defaults.js.map +1 -1
  22. package/dist/ip.js +2 -1
  23. package/dist/ip.js.map +1 -1
  24. package/dist/level.d.ts +3 -3
  25. package/dist/level.js +1 -0
  26. package/dist/level.js.map +1 -1
  27. package/dist/listen-zero.js.map +1 -1
  28. package/dist/mixin/mixin-cycle.js +6 -6
  29. package/dist/mixin/mixin-cycle.js.map +1 -1
  30. package/dist/plugin/acl.js.map +1 -1
  31. package/dist/plugin/cluster.js.map +1 -1
  32. package/dist/plugin/descriptor.js +1 -1
  33. package/dist/plugin/descriptor.js.map +1 -1
  34. package/dist/plugin/device.d.ts +6 -6
  35. package/dist/plugin/device.js.map +1 -1
  36. package/dist/plugin/endpoint.js.map +1 -1
  37. package/dist/plugin/media.js.map +1 -1
  38. package/dist/plugin/mediaobject.d.ts +1 -1
  39. package/dist/plugin/mediaobject.js.map +1 -1
  40. package/dist/plugin/plugin-api.d.ts +6 -6
  41. package/dist/plugin/plugin-api.js +2 -2
  42. package/dist/plugin/plugin-api.js.map +1 -1
  43. package/dist/plugin/plugin-console.js +11 -10
  44. package/dist/plugin/plugin-console.js.map +1 -1
  45. package/dist/plugin/plugin-device.d.ts +3 -3
  46. package/dist/plugin/plugin-device.js +2 -0
  47. package/dist/plugin/plugin-device.js.map +1 -1
  48. package/dist/plugin/plugin-host-api.d.ts +1 -1
  49. package/dist/plugin/plugin-host-api.js +19 -5
  50. package/dist/plugin/plugin-host-api.js.map +1 -1
  51. package/dist/plugin/plugin-host.js +3 -2
  52. package/dist/plugin/plugin-host.js.map +1 -1
  53. package/dist/plugin/plugin-http.d.ts +1 -1
  54. package/dist/plugin/plugin-http.js +5 -1
  55. package/dist/plugin/plugin-http.js.map +1 -1
  56. package/dist/plugin/plugin-lazy-remote.js.map +1 -1
  57. package/dist/plugin/plugin-remote-websocket.js.map +1 -1
  58. package/dist/plugin/plugin-remote-worker.js +5 -2
  59. package/dist/plugin/plugin-remote-worker.js.map +1 -1
  60. package/dist/plugin/plugin-remote.js +1 -1
  61. package/dist/plugin/plugin-remote.js.map +1 -1
  62. package/dist/plugin/plugin-repl.js +6 -2
  63. package/dist/plugin/plugin-repl.js.map +1 -1
  64. package/dist/plugin/runtime/child-process-worker.d.ts +4 -4
  65. package/dist/plugin/runtime/child-process-worker.js +1 -2
  66. package/dist/plugin/runtime/child-process-worker.js.map +1 -1
  67. package/dist/plugin/runtime/cluster-fork-worker.d.ts +1 -1
  68. package/dist/plugin/runtime/cluster-fork-worker.js +2 -0
  69. package/dist/plugin/runtime/cluster-fork-worker.js.map +1 -1
  70. package/dist/plugin/runtime/custom-worker.js.map +1 -1
  71. package/dist/plugin/runtime/node-fork-worker.d.ts +1 -1
  72. package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
  73. package/dist/plugin/runtime/node-thread-worker.js.map +1 -1
  74. package/dist/plugin/runtime/python-worker.js +1 -1
  75. package/dist/plugin/runtime/python-worker.js.map +1 -1
  76. package/dist/plugin/runtime/runtime-worker.d.ts +1 -1
  77. package/dist/plugin/system.d.ts +1 -1
  78. package/dist/plugin/system.js +1 -0
  79. package/dist/plugin/system.js.map +1 -1
  80. package/dist/promise-utils.d.ts +1 -1
  81. package/dist/promise-utils.js.map +1 -1
  82. package/dist/rpc-buffer-serializer.d.ts +1 -1
  83. package/dist/rpc-serializer.js.map +1 -1
  84. package/dist/rpc.d.ts +10 -9
  85. package/dist/rpc.js +15 -8
  86. package/dist/rpc.js.map +1 -1
  87. package/dist/runtime.d.ts +11 -11
  88. package/dist/runtime.js +17 -18
  89. package/dist/runtime.js.map +1 -1
  90. package/dist/scrypted-cluster-main.js +3 -2
  91. package/dist/scrypted-cluster-main.js.map +1 -1
  92. package/dist/scrypted-plugin-main.js +1 -1
  93. package/dist/scrypted-plugin-main.js.map +1 -1
  94. package/dist/scrypted-server-main.js +8 -5
  95. package/dist/scrypted-server-main.js.map +1 -1
  96. package/dist/server-settings.d.ts +1 -1
  97. package/dist/server-settings.js +4 -4
  98. package/dist/server-settings.js.map +1 -1
  99. package/dist/services/addresses.d.ts +1 -1
  100. package/dist/services/addresses.js +2 -2
  101. package/dist/services/addresses.js.map +1 -1
  102. package/dist/services/alerts.js +2 -2
  103. package/dist/services/alerts.js.map +1 -1
  104. package/dist/services/cluster-fork.js.map +1 -1
  105. package/dist/services/plugin.d.ts +5 -5
  106. package/dist/services/plugin.js.map +1 -1
  107. package/dist/services/service-control.js.map +1 -1
  108. package/dist/services/users.d.ts +2 -2
  109. package/dist/services/users.js.map +1 -1
  110. package/dist/state.d.ts +7 -7
  111. package/dist/state.js +4 -4
  112. package/dist/state.js.map +1 -1
  113. package/dist/threading.js.map +1 -1
  114. package/dist/usertoken.d.ts +2 -2
  115. package/dist/usertoken.js.map +1 -1
  116. package/package.json +2 -2
  117. package/python/cluster_setup.py +13 -4
  118. package/python/plugin_remote.py +22 -18
  119. package/python/rpc_reader.py +3 -5
  120. package/src/cert.ts +2 -2
  121. package/src/cluster/cluster-labels.ts +4 -4
  122. package/src/cluster/cluster-setup.ts +20 -20
  123. package/src/db-types.ts +16 -16
  124. package/src/event-registry.ts +13 -11
  125. package/src/fetch/index.ts +4 -7
  126. package/src/http-interfaces.ts +2 -2
  127. package/src/infer-defaults.ts +12 -8
  128. package/src/ip.ts +2 -1
  129. package/src/level.ts +10 -9
  130. package/src/listen-zero.ts +1 -1
  131. package/src/mixin/mixin-cycle.ts +6 -6
  132. package/src/plugin/acl.ts +1 -1
  133. package/src/plugin/cluster.ts +2 -2
  134. package/src/plugin/descriptor.ts +2 -2
  135. package/src/plugin/device.ts +16 -16
  136. package/src/plugin/endpoint.ts +4 -4
  137. package/src/plugin/media.ts +15 -15
  138. package/src/plugin/mediaobject.ts +3 -3
  139. package/src/plugin/plugin-api.ts +7 -7
  140. package/src/plugin/plugin-console.ts +13 -12
  141. package/src/plugin/plugin-device.ts +20 -18
  142. package/src/plugin/plugin-host-api.ts +27 -13
  143. package/src/plugin/plugin-host.ts +26 -25
  144. package/src/plugin/plugin-http.ts +9 -5
  145. package/src/plugin/plugin-lazy-remote.ts +1 -1
  146. package/src/plugin/plugin-remote-websocket.ts +1 -1
  147. package/src/plugin/plugin-remote-worker.ts +22 -20
  148. package/src/plugin/plugin-remote.ts +14 -14
  149. package/src/plugin/plugin-repl.ts +6 -2
  150. package/src/plugin/runtime/child-process-worker.ts +11 -12
  151. package/src/plugin/runtime/cluster-fork-worker.ts +2 -0
  152. package/src/plugin/runtime/custom-worker.ts +6 -6
  153. package/src/plugin/runtime/node-fork-worker.ts +3 -3
  154. package/src/plugin/runtime/node-thread-worker.ts +3 -3
  155. package/src/plugin/runtime/python-worker.ts +14 -14
  156. package/src/plugin/runtime/runtime-worker.ts +1 -1
  157. package/src/plugin/system.ts +24 -23
  158. package/src/promise-utils.ts +4 -4
  159. package/src/rpc-serializer.ts +3 -3
  160. package/src/rpc.ts +25 -17
  161. package/src/runtime.ts +59 -60
  162. package/src/scrypted-cluster-main.ts +19 -18
  163. package/src/scrypted-plugin-main.ts +2 -2
  164. package/src/scrypted-server-main.ts +17 -14
  165. package/src/server-settings.ts +5 -5
  166. package/src/services/addresses.ts +3 -3
  167. package/src/services/alerts.ts +2 -2
  168. package/src/services/cluster-fork.ts +9 -9
  169. package/src/services/plugin.ts +15 -15
  170. package/src/services/service-control.ts +1 -1
  171. package/src/services/users.ts +3 -3
  172. package/src/state.ts +21 -21
  173. package/src/threading.ts +5 -5
  174. 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?: string;
6
- _documentType?: string;
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: number;
20
- passwordHash: string;
21
- token: string;
22
- salt: string;
23
- aclId: string;
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: number;
28
- title: string;
29
- path: string;
30
- message: string;
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?: string) {
34
+ constructor(id: string) {
35
35
  super();
36
36
  this._id = id;
37
37
  }
38
38
  nativeId: ScryptedNativeId;
39
- pluginId: string;
40
- state: { [property: string]: SystemDeviceState };
41
- stateVersion: number;
42
- storage: { [key: string]: string };
39
+ pluginId!: string;
40
+ state!: { [property: string]: SystemDeviceState };
41
+ stateVersion!: number;
42
+ storage!: { [key: string]: string };
43
43
  }
@@ -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
- events.add(callback);
32
+ let cb: typeof callback | undefined = callback;
33
+ events.add(cb);
33
34
  return new EventListenerRegisterImpl(() => {
34
- events.delete(callback);
35
- callback = undefined;
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
- events.add(callback);
49
+ let cb: typeof callback | undefined = callback;
50
+ events.add(cb);
49
51
  return new EventListenerRegisterImpl(() => {
50
- events.delete(callback);
51
- callback = undefined;
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, eventDetails, value);
86
+ event(id!, eventDetails, value);
85
87
  }
86
88
  }
87
89
 
@@ -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
- for (const k of Object.keys(headers)) {
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
  }
@@ -63,7 +63,7 @@ export class HttpResponseImpl implements HttpResponse {
63
63
 
64
64
  // prefer etag
65
65
  this.res.sendFile(filePath, {
66
- root: null,
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();
@@ -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).filter(iface => interfaces.includes(iface as ScryptedInterface)).map(iface => inferenceTable[iface]).flat();
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
- const room = inferRoomFromName(getDisplayName(pluginDevice));
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?: any;
5
- _documentType?: string;
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: number;
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
 
@@ -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: () => void;
21
+ let cancel!: () => void;
22
22
  const clientPromise = new Promise<net.Socket>((resolve, reject) => {
23
23
  const timeout = setTimeout(() => {
24
24
  server.close();
@@ -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
- mixins = mixins || getMixins(scrypted, id);
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(mixins);
19
+ const visitedMixins = new Set(mixinsList);
20
20
 
21
- mixins = mixins.slice();
22
- while (mixins.length) {
23
- const mixin = mixins.pop();
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
- mixins.push(...providerMixins);
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
 
@@ -6,7 +6,7 @@ export interface ClusterForkServiceInterface {
6
6
  }
7
7
 
8
8
  export class ClusterManagerImpl implements ClusterManager {
9
- private clusterServicePromise: Promise<ClusterForkServiceInterface>;
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 {
@@ -1,6 +1,6 @@
1
1
  import { ScryptedInterface, ScryptedInterfaceDescriptor, ScryptedInterfaceDescriptors } from "@scrypted/types";
2
2
 
3
- export const allInterfaceProperties: string[] = [].concat(...Object.values(ScryptedInterfaceDescriptors).map(type => type.properties));
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].methods.includes(method);
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 {
@@ -7,7 +7,7 @@ import { SystemManagerImpl } from './system';
7
7
  class DeviceLogger implements Logger {
8
8
  nativeId: ScryptedNativeId;
9
9
  api: PluginAPI;
10
- logger: Promise<PluginLogger>;
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: PluginAPI;
88
- nativeIds = new Map<string, DeviceManagerDevice>();
89
- deviceStorage = new Map<string, StorageImpl>();
90
- mixinStorage = new Map<string, Map<string, StorageImpl>>();
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).id,
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).storage;
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(): string[] {
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).storage;
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).storage = {};
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].substring(this.prefix.length);
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];
@@ -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: DeviceManagerImpl;
7
- api: PluginAPI;
8
- pluginId: string;
9
- mediaManager: MediaManager;
6
+ deviceManager!: DeviceManagerImpl;
7
+ api!: PluginAPI;
8
+ pluginId!: string;
9
+ mediaManager!: MediaManager;
10
10
 
11
11
  getEndpoint(nativeId?: ScryptedNativeId) {
12
12
  if (!nativeId)
@@ -348,7 +348,7 @@ export abstract class MediaManagerBase implements MediaManager {
348
348
  fromMimeType: mediaObject.mimeType,
349
349
  toMimeType,
350
350
  convert: async (data, fromMimeType, toMimeType) => {
351
- return mediaObject.convert(toMimeType);
351
+ return mediaObject.convert!(toMimeType);
352
352
  }
353
353
  });
354
354
 
@@ -366,10 +366,10 @@ export abstract class MediaManagerBase implements MediaManager {
366
366
  // connect the intrinsic converter to other converters
367
367
  for (const candidate of converters) {
368
368
  try {
369
- const candidateMime = new MimeType(candidate.fromMimeType);
369
+ const candidateMime = new MimeType(candidate.fromMimeType!);
370
370
  if (!mimeMatches(convertedMime, candidateMime))
371
371
  continue;
372
- 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);
373
373
  const candidateId = candidate.id;
374
374
  node[candidateId] = outputWeight;
375
375
  }
@@ -381,10 +381,10 @@ export abstract class MediaManagerBase implements MediaManager {
381
381
 
382
382
  for (const converter of converters) {
383
383
  try {
384
- const inputMime = new MimeType(converter.fromMimeType);
385
- const convertedMime = new MimeType(converter.toMimeType);
384
+ const inputMime = new MimeType(converter.fromMimeType!);
385
+ const convertedMime = new MimeType(converter.toMimeType!);
386
386
  // catch all converters should be heavily weighted so as not to use them.
387
- 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);
388
388
  // const convertedWeight = parseFloat(convertedMime.parameters.get('converter-weight')) || (convertedMime.essence === ScryptedMimeTypes.MediaObject ? 1000 : 1);
389
389
  // const conversionWeight = inputWeight + convertedWeight;
390
390
  const targetId = converter.id;
@@ -393,10 +393,10 @@ export abstract class MediaManagerBase implements MediaManager {
393
393
  // edge matches
394
394
  for (const candidate of converters) {
395
395
  try {
396
- const candidateMime = new MimeType(candidate.fromMimeType);
396
+ const candidateMime = new MimeType(candidate.fromMimeType!);
397
397
  if (!mimeMatches(convertedMime, candidateMime))
398
398
  continue;
399
- 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);
400
400
  const candidateId = candidate.id;
401
401
  node[candidateId] = inputWeight + outputWeight;
402
402
  }
@@ -436,23 +436,23 @@ export abstract class MediaManagerBase implements MediaManager {
436
436
  let valueMime = new MimeType(mediaObject.mimeType);
437
437
 
438
438
  while (route.length) {
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);
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!);
443
443
  const type = converterToMimeType.type === '*' ? valueMime.type : converterToMimeType.type;
444
444
  const subtype = converterToMimeType.subtype === '*' ? valueMime.subtype : converterToMimeType.subtype;
445
445
  let targetMimeType = `${type}/${subtype}`;
446
446
  if (!route.length && outputMime.parameters.size) {
447
447
  const withParameters = new MimeType(targetMimeType);
448
448
  for (const k of outputMime.parameters.keys()) {
449
- withParameters.parameters.set(k, outputMime.parameters.get(k));
449
+ withParameters.parameters.set(k, outputMime.parameters.get(k)!);
450
450
  }
451
451
  targetMimeType = outputMime.toString();
452
452
  }
453
453
 
454
454
  if (converter.toMimeType === ScryptedMimeTypes.MediaObject) {
455
- 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;
456
456
  const found = await this.convertMediaObject(mo, toMimeType);
457
457
  return {
458
458
  data: found,
@@ -460,7 +460,7 @@ export abstract class MediaManagerBase implements MediaManager {
460
460
  };
461
461
  }
462
462
 
463
- 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;
464
464
  valueMime = new MimeType(targetMimeType);
465
465
  }
466
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: MediaObjectCreateOptions) {
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.convert ||= null;
13
- options.toMimeTypes ||= null;
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))
@@ -19,9 +19,9 @@ export interface PluginAPI {
19
19
  onDeviceEvent(nativeId: ScryptedNativeId, eventInterface: string, eventData?: any): Promise<void>;
20
20
  onMixinEvent(id: string, nativeId: ScryptedNativeId, eventInterface: string, eventData?: any): Promise<void>;
21
21
  onDeviceRemoved(nativeId: string): Promise<void>;
22
- setStorage(nativeId: string, storage: { [key: string]: any }): Promise<void>;
22
+ setStorage(nativeId: ScryptedNativeId, storage: { [key: string]: any }): Promise<void>;
23
23
 
24
- getDeviceById(id: string): Promise<ScryptedDevice>;
24
+ getDeviceById(id: string): Promise<ScryptedDevice | undefined>;
25
25
  setDeviceProperty(id: string, property: ScryptedInterfaceProperty, value: any): Promise<void>;
26
26
  removeDevice(id: string): Promise<void>;
27
27
  listen(EventListener: (id: string, eventDetails: EventDetails, eventData: any) => void): Promise<EventListenerRegister>;
@@ -69,7 +69,7 @@ export class PluginAPIManagedListeners {
69
69
  }
70
70
 
71
71
  export class PluginAPIProxy extends PluginAPIManagedListeners implements PluginAPI {
72
- acl: AccessControls;
72
+ acl!: AccessControls;
73
73
 
74
74
  constructor(public api: PluginAPI, public mediaManager?: MediaManager) {
75
75
  super();
@@ -108,9 +108,9 @@ export class PluginAPIProxy extends PluginAPIManagedListeners implements PluginA
108
108
  this.acl?.deny();
109
109
  return this.api.setStorage(nativeId, storage);
110
110
  }
111
- getDeviceById(id: string): Promise<ScryptedDevice> {
111
+ async getDeviceById(id: string): Promise<ScryptedDevice | undefined> {
112
112
  if (this.acl?.shouldRejectDevice(id))
113
- return;
113
+ return undefined;
114
114
  return this.api.getDeviceById(id);
115
115
  }
116
116
  setDeviceProperty(id: string, property: ScryptedInterfaceProperty, value: any): Promise<void> {
@@ -148,7 +148,7 @@ export class PluginAPIProxy extends PluginAPIManagedListeners implements PluginA
148
148
  return this.api.getComponent(id);
149
149
  }
150
150
  async getMediaManager(): Promise<MediaManager> {
151
- return this.mediaManager;
151
+ return this.mediaManager!;
152
152
  }
153
153
 
154
154
  async requestRestart() {
@@ -176,7 +176,7 @@ export class PluginZipAPI {
176
176
  }
177
177
 
178
178
  export interface PluginRemote {
179
- loadZip(packageJson: any, zipAPI: PluginZipAPI, options: PluginRemoteLoadZipOptions): Promise<any>;
179
+ loadZip(packageJson: any, zipAPI: PluginZipAPI, options?: PluginRemoteLoadZipOptions): Promise<any>;
180
180
  setSystemState(state: { [id: string]: { [property: string]: SystemDeviceState } }): Promise<void>;
181
181
  setNativeId(nativeId: ScryptedNativeId, id: string, storage: { [key: string]: any }): Promise<void>;
182
182
  updateDeviceState(id: string, state: { [property: string]: SystemDeviceState }): Promise<void>;