@iobroker/js-controller-adapter 7.0.2 → 7.0.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.
- package/build/cjs/index.js +2 -1
- package/build/cjs/index.js.map +2 -2
- package/build/cjs/lib/_Types.d.ts +0 -2
- package/build/cjs/lib/adapter/adapter.d.ts +3 -6
- package/build/cjs/lib/adapter/adapter.js +1537 -14
- package/build/cjs/lib/adapter/adapter.js.map +3 -3
- package/build/cjs/lib/adapter/constants.js +17 -0
- package/build/cjs/lib/adapter/constants.js.map +1 -1
- package/build/cjs/lib/adapter/log.d.ts +0 -1
- package/build/cjs/lib/adapter/log.js +6 -0
- package/build/cjs/lib/adapter/log.js.map +1 -1
- package/build/cjs/lib/adapter/userInterfaceMessagingController.d.ts +0 -2
- package/build/cjs/lib/adapter/userInterfaceMessagingController.js +41 -0
- package/build/cjs/lib/adapter/userInterfaceMessagingController.js.map +1 -1
- package/build/cjs/lib/adapter/utils.js +4 -0
- package/build/cjs/lib/adapter/utils.js.map +1 -1
- package/build/cjs/lib/adapter/validator.d.ts +0 -2
- package/build/cjs/lib/adapter/validator.js +95 -0
- package/build/cjs/lib/adapter/validator.js.map +1 -1
- package/build/esm/index.d.ts.map +1 -1
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/lib/_Types.d.ts +0 -2
- package/build/esm/lib/_Types.d.ts.map +1 -1
- package/build/esm/lib/adapter/adapter.d.ts +3 -6
- package/build/esm/lib/adapter/adapter.d.ts.map +1 -1
- package/build/esm/lib/adapter/adapter.js +4 -4
- package/build/esm/lib/adapter/adapter.js.map +1 -1
- package/build/esm/lib/adapter/log.d.ts +0 -1
- package/build/esm/lib/adapter/log.d.ts.map +1 -1
- package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts +0 -2
- package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts.map +1 -1
- package/build/esm/lib/adapter/validator.d.ts +0 -2
- package/build/esm/lib/adapter/validator.d.ts.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +10 -10
|
@@ -67,22 +67,39 @@ var STATE_QUALITY;
|
|
|
67
67
|
})(STATE_QUALITY || (STATE_QUALITY = {}));
|
|
68
68
|
const SUPPORTED_FEATURES_INTERNAL = [
|
|
69
69
|
"ALIAS",
|
|
70
|
+
// Alias Feature supported, Since `js-controller` 2.0
|
|
70
71
|
"ALIAS_SEPARATE_READ_WRITE_ID",
|
|
72
|
+
// Alias support separated ids for read and write, Since `js-controller` 3.0
|
|
71
73
|
"ADAPTER_GETPORT_BIND",
|
|
74
|
+
// getPort method of adapter supports second parameter to bind to a special network interface, Since js-controller 2.0
|
|
72
75
|
"ADAPTER_DEL_OBJECT_RECURSIVE",
|
|
76
|
+
// delObject supports options.recursive flag to delete objects structures recursive, Since js-controller 2.2
|
|
73
77
|
"ADAPTER_SET_OBJECT_SETS_DEFAULT_VALUE",
|
|
78
|
+
// setObject(*) methods set the default (def) value via setState after the object is created. Since js-controller 2.0
|
|
74
79
|
"ADAPTER_AUTO_DECRYPT_NATIVE",
|
|
80
|
+
// all native attributes that are listed in an array `encryptedNative` in io-pack will be automatically decrypted and encrypted. Since js-controller 3.0
|
|
75
81
|
"PLUGINS",
|
|
82
|
+
// configurable plugins supported. Since `js-controller` 3.0
|
|
76
83
|
"CONTROLLER_NPM_AUTO_REBUILD",
|
|
84
|
+
// Automatic rebuild when node version mismatch is detected. Since `js-controller` 3.0
|
|
77
85
|
"CONTROLLER_READWRITE_BASE_SETTINGS",
|
|
86
|
+
// If base settings could be read and written. Since js-controller 3.0
|
|
78
87
|
"CONTROLLER_MULTI_REPO",
|
|
88
|
+
// Controller supports multiple repositories
|
|
79
89
|
"CONTROLLER_LICENSE_MANAGER",
|
|
90
|
+
// Controller can read licenses from iobroker.net. Since js-controller 4.0
|
|
80
91
|
"CONTROLLER_OS_PACKAGE_UPGRADE",
|
|
92
|
+
// Controller can upgrade OS packages
|
|
81
93
|
"DEL_INSTANCE_CUSTOM",
|
|
94
|
+
// instances/adapter can be deleted with --custom flag to remove corresponding custom of all objects. Since js-controller 4.0
|
|
82
95
|
"CUSTOM_FULL_VIEW",
|
|
96
|
+
// `getObjectView('system', 'custom-full', ...)` will return full objects and not only `common.custom` part. Since `js-controller` 5.0
|
|
83
97
|
"ADAPTER_GET_OBJECTS_BY_ARRAY",
|
|
98
|
+
// getForeignObjects supports an array of ids too. Since js-controller 5.0
|
|
84
99
|
"CONTROLLER_UI_UPGRADE",
|
|
100
|
+
// Controller can be updated via sendToHost('upgradeController', ...)
|
|
85
101
|
"ADAPTER_WEBSERVER_UPGRADE"
|
|
102
|
+
// Controller supports upgrading adapter and provides a webserver (triggered via sendToHost). Since `js-controller` 5.0
|
|
86
103
|
];
|
|
87
104
|
const SUPPORTED_FEATURES = [...SUPPORTED_FEATURES_INTERNAL];
|
|
88
105
|
const MAX_TIMEOUT = 2 ** 32 / 2 - 1;
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/adapter/constants.ts"],
|
|
4
4
|
"sourcesContent": ["/**\n * Constants needed for adapter.js\n */\nexport const DEFAULT_SECRET = 'Zgfr56gFe87jJOM';\nexport const ALIAS_STARTS_WITH = 'alias.';\nexport const SYSTEM_ADMIN_USER = 'system.user.admin';\nexport const SYSTEM_ADMIN_GROUP = 'system.group.administrator';\nexport const ERROR_PERMISSION = 'permissionError';\nexport const ACCESS_GROUP_READ = 0x40;\nexport const ACCESS_GROUP_WRITE = 0x20;\nexport const ACCESS_EVERY_WRITE = 0x2;\nexport const ACCESS_EVERY_READ = 0x4;\nexport const ACCESS_USER_READ = 0x400;\nexport const ACCESS_USER_WRITE = 0x200;\nexport const NO_PROTECT_ADAPTERS = ['admin', 'iot', 'cloud', 'discovery'];\n\n/** Two-way mapping for state quality (\"q\" attribute of a state) */\nexport enum STATE_QUALITY {\n /** The default value for a state */\n GOOD = 0x00,\n /** General problem */\n BAD = 0x01,\n /** The instance cannot establish a connection */\n CONNECTION_PROBLEM = 0x02,\n /** Substitute value from controller. Do not set this in adapters */\n SUBSTITUTE_FROM_CONTROLLER = 0x10,\n /** Quality for default values */\n SUBSTITUTE_INITIAL_VALUE = 0x20,\n /** Substitute value from instance or device */\n SUBSTITUTE_DEVICE_INSTANCE_VALUE = 0x40,\n /** Substitute value from a sensor */\n SUBSTITUTE_SENSOR_VALUE = 0x80,\n /** General problem by instance */\n GENERAL_INSTANCE_PROBLEM = 0x11,\n /** General problem by device */\n GENERAL_DEVICE_PROBLEM = 0x41,\n /** General problem by sensor */\n GENERAL_SENSOR_PROBLEM = 0x81,\n /** The instance is not connected */\n INSTANCE_NOT_CONNECTED = 0x12,\n /** The device is not connected */\n DEVICE_NOT_CONNECTED = 0x42,\n /** The sensor is not connected */\n SENSOR_NOT_CONNECTED = 0x82,\n /** The device has reported an error */\n DEVICE_ERROR_REPORT = 0x44,\n /** The sensor has reported an error */\n SENSOR_ERROR_REPORT = 0x84,\n}\n\n/** Using the const array just for type inference */\nconst SUPPORTED_FEATURES_INTERNAL = [\n 'ALIAS', // Alias Feature supported, Since `js-controller` 2.0\n 'ALIAS_SEPARATE_READ_WRITE_ID', // Alias support separated ids for read and write, Since `js-controller` 3.0\n 'ADAPTER_GETPORT_BIND', // getPort method of adapter supports second parameter to bind to a special network interface, Since js-controller 2.0\n 'ADAPTER_DEL_OBJECT_RECURSIVE', // delObject supports options.recursive flag to delete objects structures recursive, Since js-controller 2.2\n 'ADAPTER_SET_OBJECT_SETS_DEFAULT_VALUE', // setObject(*) methods set the default (def) value via setState after the object is created. Since js-controller 2.0\n 'ADAPTER_AUTO_DECRYPT_NATIVE', // all native attributes that are listed in an array `encryptedNative` in io-pack will be automatically decrypted and encrypted. Since js-controller 3.0\n 'PLUGINS', // configurable plugins supported. Since `js-controller` 3.0\n 'CONTROLLER_NPM_AUTO_REBUILD', // Automatic rebuild when node version mismatch is detected. Since `js-controller` 3.0\n 'CONTROLLER_READWRITE_BASE_SETTINGS', // If base settings could be read and written. Since js-controller 3.0\n 'CONTROLLER_MULTI_REPO', // Controller supports multiple repositories\n 'CONTROLLER_LICENSE_MANAGER', // Controller can read licenses from iobroker.net. Since js-controller 4.0\n 'CONTROLLER_OS_PACKAGE_UPGRADE', // Controller can upgrade OS packages\n 'DEL_INSTANCE_CUSTOM', // instances/adapter can be deleted with --custom flag to remove corresponding custom of all objects. Since js-controller 4.0\n 'CUSTOM_FULL_VIEW', // `getObjectView('system', 'custom-full', ...)` will return full objects and not only `common.custom` part. Since `js-controller` 5.0\n 'ADAPTER_GET_OBJECTS_BY_ARRAY', // getForeignObjects supports an array of ids too. Since js-controller 5.0\n 'CONTROLLER_UI_UPGRADE', // Controller can be updated via sendToHost('upgradeController', ...)\n 'ADAPTER_WEBSERVER_UPGRADE', // Controller supports upgrading adapter and provides a webserver (triggered via sendToHost). Since `js-controller` 5.0\n] as const;\n\nexport const SUPPORTED_FEATURES = [...SUPPORTED_FEATURES_INTERNAL];\n\nexport type SupportedFeature = (typeof SUPPORTED_FEATURES)[number];\n\n/** Maximum possible value for 32-bit signed integer */\nexport const MAX_TIMEOUT = 2 ** 32 / 2 - 1;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;AAGO,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB,CAAC,SAAS,OAAO,SAAS,WAAW;AAGxE,IAAY;CAAZ,SAAYA,gBAAa;AAErB,EAAAA,eAAAA,eAAA,
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;AAGO,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB,CAAC,SAAS,OAAO,SAAS,WAAW;AAGxE,IAAY;CAAZ,SAAYA,gBAAa;AAErB,EAAAA,eAAAA,eAAA,MAAA,IAAA,CAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,KAAA,IAAA,CAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,oBAAA,IAAA,CAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,4BAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,0BAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,kCAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,yBAAA,IAAA,GAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,0BAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,wBAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,wBAAA,IAAA,GAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,wBAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,sBAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,sBAAA,IAAA,GAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,qBAAA,IAAA,EAAA,IAAA;AAEA,EAAAA,eAAAA,eAAA,qBAAA,IAAA,GAAA,IAAA;AACJ,GA/BY,kBAAA,gBAAa,CAAA,EAAA;AAkCzB,MAAM,8BAA8B;EAChC;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;;AAGG,MAAM,qBAAqB,CAAC,GAAG,2BAA2B;AAK1D,MAAM,cAAc,KAAK,KAAK,IAAI;",
|
|
6
6
|
"names": ["STATE_QUALITY"]
|
|
7
7
|
}
|
|
@@ -24,7 +24,13 @@ module.exports = __toCommonJS(log_exports);
|
|
|
24
24
|
class Log {
|
|
25
25
|
namespaceLog;
|
|
26
26
|
level;
|
|
27
|
+
// TODO: this should be a winston.Logger, but the exported types will mess up because of https://github.com/microsoft/rushstack/issues/2220
|
|
27
28
|
logger;
|
|
29
|
+
/**
|
|
30
|
+
* @param namespaceLog Logging namespace to prefix
|
|
31
|
+
* @param level The log level
|
|
32
|
+
* @param logger logger instance
|
|
33
|
+
*/
|
|
28
34
|
constructor(namespaceLog, level, logger) {
|
|
29
35
|
this.namespaceLog = namespaceLog;
|
|
30
36
|
this.level = level;
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/adapter/log.ts"],
|
|
4
4
|
"sourcesContent": ["/**\n * Log class for adapter.js\n *\n * It prefixes every message with the given namespace\n */\nexport class Log implements ioBroker.Logger {\n private readonly namespaceLog: string;\n readonly level: ioBroker.LogLevel;\n // TODO: this should be a winston.Logger, but the exported types will mess up because of https://github.com/microsoft/rushstack/issues/2220\n private readonly logger: any;\n\n /**\n * @param namespaceLog Logging namespace to prefix\n * @param level The log level\n * @param logger logger instance\n */\n constructor(namespaceLog: string, level: ioBroker.LogLevel, logger: any) {\n this.namespaceLog = namespaceLog;\n this.level = level;\n // We have to bind the `this` context here, or it is possible that `this` is\n // undefined when passing around the logger methods. This happens e.g. when doing this:\n // const log = new Log(...);\n // const test = log.info;\n // test();\n this.logger = logger;\n this.silly = this.silly.bind(this);\n this.debug = this.debug.bind(this);\n this.info = this.info.bind(this);\n this.error = this.error.bind(this);\n this.warn = this.warn.bind(this);\n }\n\n silly(msg: string): void {\n this.logger.silly(`${this.namespaceLog} ${msg}`);\n }\n\n debug(msg: string): void {\n this.logger.debug(`${this.namespaceLog} ${msg}`);\n }\n\n info(msg: string): void {\n this.logger.info(`${this.namespaceLog} ${msg}`);\n }\n\n error(msg: string): void {\n this.logger.error(`${this.namespaceLog} ${msg}`);\n }\n\n warn(msg: string): void {\n this.logger.warn(`${this.namespaceLog} ${msg}`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;AAKM,MAAO,IAAG;EACK;EACR
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;AAKM,MAAO,IAAG;EACK;EACR;;EAEQ;;;;;;EAOjB,YAAY,cAAsB,OAA0B,QAAW;AACnE,SAAK,eAAe;AACpB,SAAK,QAAQ;AAMb,SAAK,SAAS;AACd,SAAK,QAAQ,KAAK,MAAM,KAAK,IAAI;AACjC,SAAK,QAAQ,KAAK,MAAM,KAAK,IAAI;AACjC,SAAK,OAAO,KAAK,KAAK,KAAK,IAAI;AAC/B,SAAK,QAAQ,KAAK,MAAM,KAAK,IAAI;AACjC,SAAK,OAAO,KAAK,KAAK,KAAK,IAAI;EACnC;EAEA,MAAM,KAAW;AACb,SAAK,OAAO,MAAM,GAAG,KAAK,YAAY,IAAI,GAAG,EAAE;EACnD;EAEA,MAAM,KAAW;AACb,SAAK,OAAO,MAAM,GAAG,KAAK,YAAY,IAAI,GAAG,EAAE;EACnD;EAEA,KAAK,KAAW;AACZ,SAAK,OAAO,KAAK,GAAG,KAAK,YAAY,IAAI,GAAG,EAAE;EAClD;EAEA,MAAM,KAAW;AACb,SAAK,OAAO,MAAM,GAAG,KAAK,YAAY,IAAI,GAAG,EAAE;EACnD;EAEA,KAAK,KAAW;AACZ,SAAK,OAAO,KAAK,GAAG,KAAK,YAAY,IAAI,GAAG,EAAE;EAClD;;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
/// <reference types="@iobroker/types-dev" />
|
|
3
1
|
import type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';
|
|
4
2
|
import type { AdapterClass } from '../../lib/adapter/adapter.js';
|
|
5
3
|
import type { UserInterfaceClientRemoveMessage, UserInterfaceClientSubscribeHandler, UserInterfaceClientSubscribeReturnType, UserInterfaceClientUnsubscribeHandler } from '../../lib/_Types.js';
|
|
@@ -22,10 +22,15 @@ __export(userInterfaceMessagingController_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(userInterfaceMessagingController_exports);
|
|
24
24
|
class UserInterfaceMessagingController {
|
|
25
|
+
/** The adapter using this messaging controller */
|
|
25
26
|
adapter;
|
|
27
|
+
/** Callback to call if successfully subscribed */
|
|
26
28
|
unsubscribeCallback;
|
|
29
|
+
/** Callback to call if successfully unsubscribed */
|
|
27
30
|
subscribeCallback;
|
|
31
|
+
/** All currently registered client handlers */
|
|
28
32
|
handlers = /* @__PURE__ */ new Map();
|
|
33
|
+
/** Collection of current heartbeat timers */
|
|
29
34
|
heartbeatTimers = /* @__PURE__ */ new Map();
|
|
30
35
|
constructor(options) {
|
|
31
36
|
const { adapter, unsubscribeCallback, subscribeCallback } = options;
|
|
@@ -33,6 +38,11 @@ class UserInterfaceMessagingController {
|
|
|
33
38
|
this.unsubscribeCallback = unsubscribeCallback;
|
|
34
39
|
this.subscribeCallback = subscribeCallback;
|
|
35
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Send a message to the given clientId
|
|
43
|
+
*
|
|
44
|
+
* @param options Data, states and client information
|
|
45
|
+
*/
|
|
36
46
|
sendToClient(options) {
|
|
37
47
|
const { states, clientId, data } = options;
|
|
38
48
|
if (!this.handlers.has(clientId)) {
|
|
@@ -45,12 +55,22 @@ class UserInterfaceMessagingController {
|
|
|
45
55
|
from: `system.adapter.${this.adapter.namespace}`
|
|
46
56
|
});
|
|
47
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Send a message to all active clients
|
|
60
|
+
*
|
|
61
|
+
* @param options Data and states options
|
|
62
|
+
*/
|
|
48
63
|
async sendToAllClients(options) {
|
|
49
64
|
const { states, data } = options;
|
|
50
65
|
for (const clientId of Object.keys(this.handlers)) {
|
|
51
66
|
await this.sendToClient({ clientId, data, states });
|
|
52
67
|
}
|
|
53
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Register subscription from new client
|
|
71
|
+
*
|
|
72
|
+
* @param msg The subscribe message
|
|
73
|
+
*/
|
|
54
74
|
async registerClientSubscribeByMessage(msg) {
|
|
55
75
|
if (!this.subscribeCallback) {
|
|
56
76
|
return;
|
|
@@ -78,6 +98,12 @@ class UserInterfaceMessagingController {
|
|
|
78
98
|
}
|
|
79
99
|
return res;
|
|
80
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Remove a client subscription, issued by message
|
|
103
|
+
* It contains an array of types which should be unsubscribed
|
|
104
|
+
*
|
|
105
|
+
* @param msg The unsubscribe message
|
|
106
|
+
*/
|
|
81
107
|
removeClientSubscribeByMessage(msg) {
|
|
82
108
|
const handler = this.extractHandlerFromMessage(msg);
|
|
83
109
|
const reason = msg.command === "clientSubscribeError" ? msg.command : msg.message.reason;
|
|
@@ -98,13 +124,28 @@ class UserInterfaceMessagingController {
|
|
|
98
124
|
}
|
|
99
125
|
}
|
|
100
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Convert handler to id
|
|
129
|
+
*
|
|
130
|
+
* @param handler the client handler to creat the id for
|
|
131
|
+
*/
|
|
101
132
|
handlerToId(handler) {
|
|
102
133
|
const { sid, type, from } = handler;
|
|
103
134
|
return `${sid}-${from}-${type}`;
|
|
104
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Extract the client handler from a given message
|
|
138
|
+
*
|
|
139
|
+
* @param msg the subscribe or unsubscribe message
|
|
140
|
+
*/
|
|
105
141
|
extractHandlerFromMessage(msg) {
|
|
106
142
|
return { sid: msg.message.sid, from: msg.from, type: msg.message.type };
|
|
107
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Handle expired heartbeat
|
|
146
|
+
*
|
|
147
|
+
* @param clientId the id of the expired client
|
|
148
|
+
*/
|
|
108
149
|
heartbeatExpired(clientId) {
|
|
109
150
|
this.handlers.delete(clientId);
|
|
110
151
|
this.heartbeatTimers.delete(clientId);
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/adapter/userInterfaceMessagingController.ts"],
|
|
4
4
|
"sourcesContent": ["import type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { AdapterClass } from '@/lib/adapter/adapter.js';\nimport type {\n UserInterfaceClientRemoveMessage,\n UserInterfaceClientSubscribeHandler,\n UserInterfaceClientSubscribeReturnType,\n UserInterfaceClientUnsubscribeHandler,\n} from '@/lib/_Types.js';\n\nexport interface HeartbeatTimer {\n /** The actual timer */\n timer: NodeJS.Timeout;\n /** The heartbeat interval */\n heartbeat: number;\n}\n\nexport interface MessagingControllerOptions {\n /** The adapter using this messaging controller */\n adapter: AdapterClass;\n /** Callback to call if successfully subscribed */\n subscribeCallback?: UserInterfaceClientSubscribeHandler;\n /** Callback to call if successfully unsubscribed */\n unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;\n}\n\nexport interface SendToClientOptions {\n /** ID of the client to send the message to, will send to all if omitted */\n clientId: string;\n /** Data to send to the client */\n data: unknown;\n /** The states db */\n states: StatesInRedisClient;\n}\n\nexport type SendToAllClientOptions = Omit<SendToClientOptions, 'clientId'>;\n\nexport interface ClientHandler {\n /** The session id of the client connection */\n sid: string;\n /** Name of the subscriber */\n from: string;\n /** Individual type which can be specified */\n type: string;\n}\n\n/**\n * The message has short keys, to save bytes for high-throughput messaging\n */\ninterface UserInterfaceMessage {\n /** The individual type of the client handler */\n m: string;\n /** The session id of the client connection */\n s: string;\n /** The actual data */\n d: unknown;\n}\n\nexport class UserInterfaceMessagingController {\n /** The adapter using this messaging controller */\n private readonly adapter: AdapterClass;\n /** Callback to call if successfully subscribed */\n private readonly unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;\n /** Callback to call if successfully unsubscribed */\n private readonly subscribeCallback?: UserInterfaceClientSubscribeHandler;\n /** All currently registered client handlers */\n private readonly handlers = new Map<string, ClientHandler>();\n /** Collection of current heartbeat timers */\n private heartbeatTimers = new Map<string, HeartbeatTimer>();\n constructor(options: MessagingControllerOptions) {\n const { adapter, unsubscribeCallback, subscribeCallback } = options;\n\n this.adapter = adapter;\n this.unsubscribeCallback = unsubscribeCallback;\n this.subscribeCallback = subscribeCallback;\n }\n\n /**\n * Send a message to the given clientId\n *\n * @param options Data, states and client information\n */\n sendToClient(options: SendToClientOptions): Promise<void> {\n const { states, clientId, data } = options;\n\n if (!this.handlers.has(clientId)) {\n throw new Error(`Client \"${clientId}\" is not registered`);\n }\n\n const handler = this.handlers.get(clientId)!;\n\n return states.pushMessage(handler.from, {\n command: 'im',\n message: { m: handler.type, s: handler.sid, d: data } satisfies UserInterfaceMessage,\n from: `system.adapter.${this.adapter.namespace}`,\n });\n }\n\n /**\n * Send a message to all active clients\n *\n * @param options Data and states options\n */\n async sendToAllClients(options: SendToAllClientOptions): Promise<void> {\n const { states, data } = options;\n\n for (const clientId of Object.keys(this.handlers)) {\n await this.sendToClient({ clientId, data, states });\n }\n }\n\n /**\n * Register subscription from new client\n *\n * @param msg The subscribe message\n */\n async registerClientSubscribeByMessage(\n msg: ioBroker.Message,\n ): Promise<UserInterfaceClientSubscribeReturnType | undefined> {\n if (!this.subscribeCallback) {\n return;\n }\n\n const handler = this.extractHandlerFromMessage(msg);\n const clientId = this.handlerToId(handler);\n\n if (this.heartbeatTimers.has(clientId)) {\n this.heartbeatTimers.get(clientId)!.timer.refresh();\n return;\n }\n\n const resOrAwaitable = this.subscribeCallback({ clientId, message: msg });\n let res: UserInterfaceClientSubscribeReturnType;\n\n if (resOrAwaitable instanceof Promise) {\n res = await resOrAwaitable;\n } else {\n res = resOrAwaitable;\n }\n\n if (!res.accepted) {\n return res;\n }\n\n this.handlers.set(clientId, handler);\n if (res.heartbeat) {\n const timer = setTimeout(() => this.heartbeatExpired(clientId), res.heartbeat);\n this.heartbeatTimers.set(clientId, { heartbeat: res.heartbeat, timer });\n }\n\n return res;\n }\n\n /**\n * Remove a client subscription, issued by message\n * It contains an array of types which should be unsubscribed\n *\n * @param msg The unsubscribe message\n */\n removeClientSubscribeByMessage(msg: UserInterfaceClientRemoveMessage): void {\n const handler = this.extractHandlerFromMessage(msg);\n const reason = msg.command === 'clientSubscribeError' ? msg.command : msg.message.reason;\n\n const types = msg.message.type;\n\n for (const type of types) {\n const clientId = this.handlerToId({ ...handler, type });\n\n if (this.heartbeatTimers.has(clientId)) {\n const timer = this.heartbeatTimers.get(clientId)!;\n\n clearTimeout(timer.timer);\n this.heartbeatTimers.delete(clientId);\n }\n\n if (!this.handlers.has(clientId)) {\n return;\n }\n\n this.handlers.delete(clientId);\n if (this.unsubscribeCallback) {\n this.unsubscribeCallback({ clientId, message: msg, reason });\n }\n }\n }\n\n /**\n * Convert handler to id\n *\n * @param handler the client handler to creat the id for\n */\n private handlerToId(handler: ClientHandler): string {\n const { sid, type, from } = handler;\n\n return `${sid}-${from}-${type}`;\n }\n\n /**\n * Extract the client handler from a given message\n *\n * @param msg the subscribe or unsubscribe message\n */\n private extractHandlerFromMessage(msg: ioBroker.Message): ClientHandler {\n return { sid: msg.message.sid, from: msg.from, type: msg.message.type };\n }\n\n /**\n * Handle expired heartbeat\n *\n * @param clientId the id of the expired client\n */\n private heartbeatExpired(clientId: string): void {\n this.handlers.delete(clientId);\n this.heartbeatTimers.delete(clientId);\n\n if (this.unsubscribeCallback) {\n this.unsubscribeCallback({ clientId, reason: 'timeout' });\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAyDA;;;;;AAAM,MAAO,iCAAgC
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
20
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/adapter/utils.ts"],
|
|
4
4
|
"sourcesContent": ["import {\n isObject,\n isControllerUiUpgradeSupported,\n encrypt,\n decrypt,\n appNameLowerCase,\n getRootDir,\n execAsync,\n} from '@iobroker/js-controller-common-db/tools';\nimport { SUPPORTED_FEATURES, type SupportedFeature } from '@/lib/adapter/constants.js';\nimport path from 'node:path';\nimport fs from 'fs-extra';\n\ninterface EncryptArrayOptions {\n /** The objects whose values should be en/decrypted */\n obj: Record<string, unknown>;\n /** Keys which need to be en/decrypted */\n keys: string[];\n /** Secret to use for en/decryption */\n secret: string;\n}\n\ninterface GetScopedPackageIdentifierOptions {\n /** Name of the node module */\n moduleName: string;\n /** Adapter namespace */\n namespace: string;\n}\n\n/**\n * Check if messagebox is configured for given instance\n * This means, at least one of the properties has a value different from false\n *\n * @param instanceCommon Instance common\n */\nexport function isMessageboxSupported(instanceCommon: ioBroker.InstanceCommon): boolean {\n if (!isObject(instanceCommon.supportedMessages)) {\n return !!instanceCommon.messagebox;\n }\n\n return Object.values(instanceCommon.supportedMessages).find(val => val !== false) !== undefined;\n}\n\n/**\n * Get the supported features for the current running controller\n */\nexport function getSupportedFeatures(): SupportedFeature[] {\n if (!isControllerUiUpgradeSupported()) {\n const idx = SUPPORTED_FEATURES.indexOf('CONTROLLER_UI_UPGRADE');\n if (idx !== -1) {\n SUPPORTED_FEATURES.splice(idx, 1);\n }\n }\n\n return SUPPORTED_FEATURES;\n}\n\n/**\n * Encrypt given keys of given object\n *\n * @param options keys, object and secret information\n */\nexport function encryptArray(options: EncryptArrayOptions): void {\n const { secret, obj, keys } = options;\n\n for (const attr of keys) {\n const val = obj[attr];\n if (typeof val === 'string') {\n obj[attr] = encrypt(secret, val);\n }\n }\n}\n\n/**\n * Decrypt given keys of given object\n *\n * @param options keys, object and secret information\n */\nexport function decryptArray(options: EncryptArrayOptions): void {\n const { secret, obj, keys } = options;\n\n for (const attr of keys) {\n const val = obj[attr];\n if (typeof val === 'string') {\n obj[attr] = decrypt(secret, val);\n }\n }\n}\n\n/**\n * Transform a npm moduleName to the adapter scoped name, like `axios` to `@iobroker-javascript.0/axios`\n *\n * @param options name of the node module and namespace information\n */\nexport function getAdapterScopedPackageIdentifier(options: GetScopedPackageIdentifierOptions): string {\n const { moduleName, namespace } = options;\n\n let internalModuleName = moduleName;\n if (internalModuleName.startsWith('@')) {\n internalModuleName = internalModuleName.substring(1).replace(/\\//g, '-');\n }\n\n return `@${appNameLowerCase}-${namespace}/${internalModuleName}`;\n}\n\n/**\n * List all packages installed in the given adapter namespace\n *\n * @param namespace namespace to check installed modules for\n */\nexport async function listInstalledNodeModules(namespace: string): Promise<string[]> {\n const packJson = (await fs.readJson(path.join(getRootDir(), 'package.json'))) as {\n dependencies: Record<string, string>;\n };\n const dependencies: string[] = [];\n\n for (const [dependency, versionInfo] of Object.entries(packJson.dependencies)) {\n if (!dependency.startsWith(`@${appNameLowerCase}-${namespace}/`)) {\n continue;\n }\n\n let realDependencyName: string;\n // remove npm: and version after last @\n if (versionInfo.startsWith('npm:')) {\n realDependencyName = versionInfo.substring(4, versionInfo.lastIndexOf('@'));\n } else {\n realDependencyName = await requestModuleNameByUrl(versionInfo);\n }\n\n dependencies.push(realDependencyName);\n }\n\n return dependencies;\n}\n\n/**\n * Request a module name by given url using `npm view`\n *\n * @param url the url to the package which should be installed via npm\n */\nexport async function requestModuleNameByUrl(url: string): Promise<string> {\n const res = await execAsync(`npm view ${url} name`);\n\n if (typeof res.stdout !== 'string') {\n throw new Error(\n `Could not determine module name for url \"${url}\". Unexpected stdout: \"${res.stdout ? res.stdout.toString() : ''}\"`,\n );\n }\n\n return res.stdout.trim();\n}\n"],
|
|
5
|
-
"mappings": "
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;AAAA,mBAQO;AACP,uBAA0D;AAC1D,uBAAiB;AACjB,sBAAe;AAwBT,SAAU,sBAAsB,gBAAuC;AACzE,MAAI,KAAC,uBAAS,eAAe,iBAAiB,GAAG;AAC7C,WAAO,CAAC,CAAC,eAAe;EAC5B;AAEA,SAAO,OAAO,OAAO,eAAe,iBAAiB,EAAE,KAAK,SAAO,QAAQ,KAAK,MAAM;AAC1F;AAKM,SAAU,uBAAoB;AAChC,MAAI,KAAC,6CAA8B,GAAI;AACnC,UAAM,MAAM,oCAAmB,QAAQ,uBAAuB;AAC9D,QAAI,QAAQ,IAAI;AACZ,0CAAmB,OAAO,KAAK,CAAC;IACpC;EACJ;AAEA,SAAO;AACX;AAOM,SAAU,aAAa,SAA4B;AACrD,QAAM,EAAE,QAAQ,KAAK,KAAI,IAAK;AAE9B,aAAW,QAAQ,MAAM;AACrB,UAAM,MAAM,IAAI,IAAI;AACpB,QAAI,OAAO,QAAQ,UAAU;AACzB,UAAI,IAAI,QAAI,sBAAQ,QAAQ,GAAG;IACnC;EACJ;AACJ;AAOM,SAAU,aAAa,SAA4B;AACrD,QAAM,EAAE,QAAQ,KAAK,KAAI,IAAK;AAE9B,aAAW,QAAQ,MAAM;AACrB,UAAM,MAAM,IAAI,IAAI;AACpB,QAAI,OAAO,QAAQ,UAAU;AACzB,UAAI,IAAI,QAAI,sBAAQ,QAAQ,GAAG;IACnC;EACJ;AACJ;AAOM,SAAU,kCAAkC,SAA0C;AACxF,QAAM,EAAE,YAAY,UAAS,IAAK;AAElC,MAAI,qBAAqB;AACzB,MAAI,mBAAmB,WAAW,GAAG,GAAG;AACpC,yBAAqB,mBAAmB,UAAU,CAAC,EAAE,QAAQ,OAAO,GAAG;EAC3E;AAEA,SAAO,IAAI,6BAAgB,IAAI,SAAS,IAAI,kBAAkB;AAClE;AAOA,eAAsB,yBAAyB,WAAiB;AAC5D,QAAM,WAAY,MAAM,gBAAAA,QAAG,SAAS,iBAAAC,QAAK,SAAK,yBAAU,GAAI,cAAc,CAAC;AAG3E,QAAM,eAAyB,CAAA;AAE/B,aAAW,CAAC,YAAY,WAAW,KAAK,OAAO,QAAQ,SAAS,YAAY,GAAG;AAC3E,QAAI,CAAC,WAAW,WAAW,IAAI,6BAAgB,IAAI,SAAS,GAAG,GAAG;AAC9D;IACJ;AAEA,QAAI;AAEJ,QAAI,YAAY,WAAW,MAAM,GAAG;AAChC,2BAAqB,YAAY,UAAU,GAAG,YAAY,YAAY,GAAG,CAAC;IAC9E,OAAO;AACH,2BAAqB,MAAM,uBAAuB,WAAW;IACjE;AAEA,iBAAa,KAAK,kBAAkB;EACxC;AAEA,SAAO;AACX;AAOA,eAAsB,uBAAuB,KAAW;AACpD,QAAM,MAAM,UAAM,wBAAU,YAAY,GAAG,OAAO;AAElD,MAAI,OAAO,IAAI,WAAW,UAAU;AAChC,UAAM,IAAI,MACN,4CAA4C,GAAG,0BAA0B,IAAI,SAAS,IAAI,OAAO,SAAQ,IAAK,EAAE,GAAG;EAE3H;AAEA,SAAO,IAAI,OAAO,KAAI;AAC1B;",
|
|
6
6
|
"names": ["fs", "path"]
|
|
7
7
|
}
|
|
@@ -30,6 +30,16 @@ class Validator {
|
|
|
30
30
|
log;
|
|
31
31
|
namespace;
|
|
32
32
|
namespaceRegExp;
|
|
33
|
+
/**
|
|
34
|
+
* Validator for internal adapter.js usage
|
|
35
|
+
*
|
|
36
|
+
* @param objects - Objects DB
|
|
37
|
+
* @param states - States DB
|
|
38
|
+
* @param namespaceLog - Log prefix
|
|
39
|
+
* @param logger - Logger instance
|
|
40
|
+
* @param namespace - the namespace of the adapter
|
|
41
|
+
* @param namespaceRegExp - the namespace RegExp of the adapter `adapter.0`
|
|
42
|
+
*/
|
|
33
43
|
constructor(objects, states, namespaceLog, logger, namespace, namespaceRegExp) {
|
|
34
44
|
this.objects = objects;
|
|
35
45
|
this.states = states;
|
|
@@ -38,6 +48,13 @@ class Validator {
|
|
|
38
48
|
this.namespaceRegExp = namespaceRegExp;
|
|
39
49
|
this.log = logger;
|
|
40
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Performs the strict object check, which includes checking object existence, read-only logic, type and min/max
|
|
53
|
+
* additionally it rounds state values whose objects have a `common.step` attribute defined
|
|
54
|
+
*
|
|
55
|
+
* @param id - id of the state
|
|
56
|
+
* @param state - ioBroker setState object
|
|
57
|
+
*/
|
|
41
58
|
async performStrictObjectCheck(id, state) {
|
|
42
59
|
try {
|
|
43
60
|
if (state.val === void 0) {
|
|
@@ -80,6 +97,14 @@ class Validator {
|
|
|
80
97
|
this.log.warn(`${this.namespaceLog} Could not perform strict object check of state ${id}: ${e.message}`);
|
|
81
98
|
}
|
|
82
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Checks if a passed ID is valid. Throws an error if id is invalid
|
|
102
|
+
*
|
|
103
|
+
* @param id id to check or object with properties device, channel and state
|
|
104
|
+
* @param isForeignId true&false if the ID is a foreign/full ID or only an "adapter local" id
|
|
105
|
+
* @param options optional
|
|
106
|
+
* @throws Error when id is invalid
|
|
107
|
+
*/
|
|
83
108
|
validateId(id, isForeignId, options) {
|
|
84
109
|
if (options && options.maintenance && options.user === import_constants.SYSTEM_ADMIN_USER) {
|
|
85
110
|
return;
|
|
@@ -120,15 +145,33 @@ class Validator {
|
|
|
120
145
|
}
|
|
121
146
|
}
|
|
122
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Look up the error description for an error code
|
|
150
|
+
*
|
|
151
|
+
* @param code error code
|
|
152
|
+
* @returns error description
|
|
153
|
+
*/
|
|
123
154
|
static getErrorText(code) {
|
|
124
155
|
code = code || 0;
|
|
125
156
|
return (import_js_controller_common.EXIT_CODES[code] || code).toString();
|
|
126
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Throws if a type is not matching the expected type
|
|
160
|
+
*
|
|
161
|
+
* @param value value to check a type of
|
|
162
|
+
* @param name name of the parameter for logging
|
|
163
|
+
*/
|
|
127
164
|
static assertString(value, name) {
|
|
128
165
|
if (typeof value !== "string") {
|
|
129
166
|
throw new Error(`Parameter "${name}" needs to be of type "string" but type "${typeof value}" has been passed`);
|
|
130
167
|
}
|
|
131
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Throws if a type is not a pattern
|
|
171
|
+
*
|
|
172
|
+
* @param value value to check a type of
|
|
173
|
+
* @param name name of the parameter for logging
|
|
174
|
+
*/
|
|
132
175
|
static assertPattern(value, name) {
|
|
133
176
|
if (typeof value !== "string" && !Array.isArray(value)) {
|
|
134
177
|
throw new Error(`Parameter "${name}" needs to be of type "string" or an array of type "string", "${typeof value}" has been passed`);
|
|
@@ -140,36 +183,78 @@ class Validator {
|
|
|
140
183
|
}
|
|
141
184
|
}
|
|
142
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Throws if a type is not matching the expected type
|
|
188
|
+
*
|
|
189
|
+
* @param value value to check a type of
|
|
190
|
+
* @param name name of the parameter for logging
|
|
191
|
+
*/
|
|
143
192
|
static assertBoolean(value, name) {
|
|
144
193
|
if (typeof value !== "boolean") {
|
|
145
194
|
throw new Error(`Parameter "${name}" needs to be of type "boolean" but type "${typeof value}" has been passed`);
|
|
146
195
|
}
|
|
147
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Throws if a type is not matching the expected type
|
|
199
|
+
*
|
|
200
|
+
* @param value value to check a type of
|
|
201
|
+
* @param name name of the parameter for logging
|
|
202
|
+
*/
|
|
148
203
|
static assertNumber(value, name) {
|
|
149
204
|
if (typeof value !== "number") {
|
|
150
205
|
throw new Error(`Parameter "${name}" needs to be of type "number" but type "${typeof value}" has been passed`);
|
|
151
206
|
}
|
|
152
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Throws if a type is not matching the expected type
|
|
210
|
+
*
|
|
211
|
+
* @param value value to check a type of
|
|
212
|
+
* @param name name of the parameter for logging
|
|
213
|
+
*/
|
|
153
214
|
static assertObject(value, name) {
|
|
154
215
|
if (!import_js_controller_common.tools.isObject(value)) {
|
|
155
216
|
throw new Error(`Parameter "${name}" needs to be a real object but type "${typeof value}" has been passed`);
|
|
156
217
|
}
|
|
157
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Throws if a type is not an optional callback
|
|
221
|
+
*
|
|
222
|
+
* @param value value to check a type of
|
|
223
|
+
* @param name name of the parameter for logging
|
|
224
|
+
*/
|
|
158
225
|
static assertBuffer(value, name) {
|
|
159
226
|
if (!Buffer.isBuffer(value)) {
|
|
160
227
|
throw new Error(`Parameter "${name}" needs to be a Buffer but type "${typeof value}" has been passed`);
|
|
161
228
|
}
|
|
162
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Throws if a type is not an optional callback
|
|
232
|
+
*
|
|
233
|
+
* @param value value to check a type of
|
|
234
|
+
* @param name name of the parameter for logging
|
|
235
|
+
*/
|
|
163
236
|
static assertOptionalCallback(value, name) {
|
|
164
237
|
if (value && typeof value !== "function") {
|
|
165
238
|
throw new Error(`Parameter "${name}" needs to be of type "null", "undefined" or "function" but type "${typeof value}" has been passed`);
|
|
166
239
|
}
|
|
167
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Throws if a type is not an optional callback
|
|
243
|
+
*
|
|
244
|
+
* @param value value to check a type of
|
|
245
|
+
* @param name name of the parameter for logging
|
|
246
|
+
*/
|
|
168
247
|
static assertCallback(value, name) {
|
|
169
248
|
if (typeof value !== "function") {
|
|
170
249
|
throw new Error(`Parameter "${name}" needs to be of type "function" but type "${typeof value}" has been passed`);
|
|
171
250
|
}
|
|
172
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Adds the namespace to the ID if it is missing, if an object is passed it will be converted to an id string
|
|
254
|
+
*
|
|
255
|
+
* @param id id which will be fixed
|
|
256
|
+
* @param isPattern if the id is a pattern
|
|
257
|
+
*/
|
|
173
258
|
fixId(id, isPattern = false) {
|
|
174
259
|
if (!id) {
|
|
175
260
|
id = "";
|
|
@@ -189,6 +274,11 @@ class Validator {
|
|
|
189
274
|
}
|
|
190
275
|
return result;
|
|
191
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Validates the object-type argument that is passed to setState
|
|
279
|
+
*
|
|
280
|
+
* @param obj object to validate
|
|
281
|
+
*/
|
|
192
282
|
validateSetStateObjectArgument(obj) {
|
|
193
283
|
if (!Object.values(obj).some((prop) => prop !== void 0)) {
|
|
194
284
|
throw new Error(`The state contains no properties! At least one property is expected!`);
|
|
@@ -220,6 +310,11 @@ class Validator {
|
|
|
220
310
|
}
|
|
221
311
|
}
|
|
222
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* Validates that the timeout is not exceeding a 32-bit signed integer
|
|
315
|
+
*
|
|
316
|
+
* @param ms milliseconds to validate
|
|
317
|
+
*/
|
|
223
318
|
static assertTimeout(ms) {
|
|
224
319
|
if (ms > import_constants.MAX_TIMEOUT) {
|
|
225
320
|
throw new Error(`Timeout (${ms}) is larger than a 32-bit signed integer (${import_constants.MAX_TIMEOUT})`);
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/adapter/validator.ts"],
|
|
4
4
|
"sourcesContent": ["import { MAX_TIMEOUT, SYSTEM_ADMIN_USER } from '@/lib/adapter/constants.js';\nimport { tools, EXIT_CODES } from '@iobroker/js-controller-common';\n\ntype Callback = (...args: any[]) => void | Promise<void>;\ntype OptionalCallback = undefined | Callback;\ntype Pattern = string | string[];\n\nexport interface ValidateIdOptions {\n /** in maintenance mode, we can access invalid ids to delete them, only works with the admin user */\n maintenance?: boolean;\n /** User used to check for access rights */\n user?: string;\n}\n\nexport class Validator {\n private readonly objects: any;\n private readonly states: any;\n private readonly namespaceLog: string;\n private readonly log: any;\n private readonly namespace: string;\n private readonly namespaceRegExp: RegExp;\n\n /**\n * Validator for internal adapter.js usage\n *\n * @param objects - Objects DB\n * @param states - States DB\n * @param namespaceLog - Log prefix\n * @param logger - Logger instance\n * @param namespace - the namespace of the adapter\n * @param namespaceRegExp - the namespace RegExp of the adapter `adapter.0`\n */\n constructor(\n objects: any,\n states: any,\n namespaceLog: string,\n logger: any,\n namespace: string,\n namespaceRegExp: RegExp,\n ) {\n this.objects = objects;\n this.states = states;\n this.namespaceLog = namespaceLog;\n this.namespace = namespace;\n this.namespaceRegExp = namespaceRegExp;\n this.log = logger;\n }\n\n /**\n * Performs the strict object check, which includes checking object existence, read-only logic, type and min/max\n * additionally it rounds state values whose objects have a `common.step` attribute defined\n *\n * @param id - id of the state\n * @param state - ioBroker setState object\n */\n async performStrictObjectCheck(id: string, state: ioBroker.SettableState): Promise<void> {\n // TODO: in js-c 3.5 (or 2 releases after 3.3) we should let it throw and add tests, maybe we\n // can already let the non existing object case throw with 3.4 because this is already producing a warning\n try {\n if (state.val === undefined) {\n // only ack etc. is also possible to acknowledge the current value,\n // if only undefined provided, it should have thrown before\n return;\n }\n\n const obj = await this.objects.getObjectAsync(id);\n // at first check object existence\n if (!obj) {\n this.log.warn(\n `${this.namespaceLog} State \"${id}\" has no existing object, this might lead to an error in future versions`,\n );\n return;\n }\n\n // for a state object, we require common.type to exist\n if (obj.common?.type) {\n // check if we are allowed to write (read-only can only be written with ack: true)\n if (!state.ack && obj.common.write === false) {\n this.log.warn(\n `${this.namespaceLog} Read-only state \"${id}\" has been written without ack-flag with value \"${state.val}\"`,\n );\n }\n\n if (state.val !== null) {\n // now check if a type is correct, null is always allowed\n if (\n !(\n (obj.common.type === 'mixed' && typeof state.val !== 'object') ||\n (obj.common.type !== 'object' && obj.common.type === typeof state.val) ||\n (obj.common.type === 'array' && typeof state.val === 'string') ||\n (obj.common.type === 'json' && typeof state.val === 'string') ||\n (obj.common.type === 'object' && typeof state.val === 'string')\n )\n ) {\n // types can be 'number', 'string', 'boolean', 'array', 'object', 'mixed', 'json';\n // 'array', 'object', 'json' need to be string\n if (['object', 'json', 'array'].includes(obj.common.type)) {\n this.log.info(\n `${\n this.namespaceLog\n } State value to set for \"${id}\" has to be stringified but received type \"${typeof state.val}\"`,\n );\n } else {\n this.log.info(\n `${this.namespaceLog} State value to set for \"${id}\" has to be ${\n obj.common.type === 'mixed'\n ? `one of type \"string\", \"number\", \"boolean\"`\n : `type \"${obj.common.type}\"`\n } but received type \"${typeof state.val}\" `,\n );\n }\n }\n\n // now round step and check min/max if it's a number\n if (typeof state.val === 'number') {\n if (typeof obj.common.step === 'number' && obj.common.step > 0) {\n // round to next step\n const inv = 1 / obj.common.step;\n state.val = Math.round(state.val * inv) / inv;\n }\n\n if (obj.common.max !== undefined && state.val > obj.common.max) {\n this.log.warn(\n `${this.namespaceLog} State value to set for \"${id}\" has value \"${state.val}\" greater than max \"${obj.common.max}\"`,\n );\n }\n\n if (obj.common.min !== undefined && state.val < obj.common.min) {\n this.log.warn(\n `${this.namespaceLog} State value to set for \"${id}\" has value \"${state.val}\" less than min \"${obj.common.min}\"`,\n );\n }\n }\n }\n } else {\n this.log.warn(\n `${this.namespaceLog} Object of state \"${id}\" is missing the required property \"common.type\"`,\n );\n }\n } catch (e) {\n this.log.warn(`${this.namespaceLog} Could not perform strict object check of state ${id}: ${e.message}`);\n }\n }\n\n /**\n * Checks if a passed ID is valid. Throws an error if id is invalid\n *\n * @param id id to check or object with properties device, channel and state\n * @param isForeignId true&false if the ID is a foreign/full ID or only an \"adapter local\" id\n * @param options optional\n * @throws Error when id is invalid\n */\n validateId(id: any, isForeignId: boolean, options?: ValidateIdOptions | null): asserts id is string {\n // there is a special maintenance mode to clear the DB from invalid IDs\n if (options && options.maintenance && options.user === SYSTEM_ADMIN_USER) {\n return;\n }\n\n if (!id && id !== 0) {\n throw new Error('The id is empty! Please provide a valid id.');\n }\n\n const type = typeof id;\n\n if (!isForeignId && type === 'number') {\n this.log.warn(\n `${this.namespaceLog} The id \"${id}\" has an invalid type! Expected \"string\" or \"object\", received \"number\".`,\n );\n this.log.warn(\n `${this.namespaceLog} This will be refused in future versions. Please report this to the developer.`,\n );\n } else if (type !== 'string' && !tools.isObject(id)) {\n throw new Error(`The id \"${id}\" has an invalid type! Expected \"string\" or \"object\", received \"${type}\".`);\n }\n\n if (tools.isObject(id)) {\n // id can be an object, at least one of the following properties has to exist\n const reqProperties = ['device', 'channel', 'state'];\n let found = false;\n for (const reqProperty of reqProperties) {\n if (id[reqProperty] !== undefined) {\n if (typeof id[reqProperty] !== 'string') {\n throw new Error(\n `The id's property \"${reqProperty}\" of \"${JSON.stringify(\n id,\n )}\" has an invalid type! Expected \"string\", received \"${typeof id[reqProperty]}\".`,\n );\n }\n\n if (id[reqProperty].includes('.')) {\n throw new Error(\n `The id's property \"${reqProperty}\" of \"${JSON.stringify(\n id,\n )}\" contains the invalid character \".\"!`,\n );\n }\n found = true;\n }\n }\n if (!found) {\n throw new Error(\n `The id \"${JSON.stringify(\n id,\n )}\" is an invalid object! Expected at least one of the properties \"device\", \"channel\" or \"state\" to exist.`,\n );\n }\n } else {\n if (type !== 'string') {\n throw new Error(\n `The id \"${JSON.stringify(id)}\" has an invalid type! Expected \"string\", received \"${type}\".`,\n );\n }\n if (id.endsWith('.')) {\n throw new Error(`The id \"${id}\" is invalid. Ids are not allowed to end in \".\"`);\n }\n }\n }\n\n /**\n * Look up the error description for an error code\n *\n * @param code error code\n * @returns error description\n */\n static getErrorText(code: number): string {\n code = code || 0;\n return (EXIT_CODES[code] || code).toString();\n }\n\n /**\n * Throws if a type is not matching the expected type\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertString(value: unknown, name: string): asserts value is string {\n if (typeof value !== 'string') {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"string\" but type \"${typeof value}\" has been passed`,\n );\n }\n }\n\n /**\n * Throws if a type is not a pattern\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertPattern(value: unknown, name: string): asserts value is Pattern {\n if (typeof value !== 'string' && !Array.isArray(value)) {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"string\" or an array of type \"string\", \"${typeof value}\" has been passed`,\n );\n } else if (Array.isArray(value)) {\n for (const entry of value) {\n if (typeof entry !== 'string') {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"string\" or an array of type \"string\", but the array contains a value of type \"${typeof value}\"`,\n );\n }\n }\n }\n }\n\n /**\n * Throws if a type is not matching the expected type\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertBoolean(value: unknown, name: string): asserts value is boolean {\n if (typeof value !== 'boolean') {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"boolean\" but type \"${typeof value}\" has been passed`,\n );\n }\n }\n\n /**\n * Throws if a type is not matching the expected type\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertNumber(value: unknown, name: string): asserts value is number {\n if (typeof value !== 'number') {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"number\" but type \"${typeof value}\" has been passed`,\n );\n }\n }\n\n /**\n * Throws if a type is not matching the expected type\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertObject<T extends Record<string, any> = Record<string, any>>(\n value: unknown,\n name: string,\n ): asserts value is T {\n if (!tools.isObject(value)) {\n throw new Error(`Parameter \"${name}\" needs to be a real object but type \"${typeof value}\" has been passed`);\n }\n }\n\n /**\n * Throws if a type is not an optional callback\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertBuffer(value: unknown, name: string): asserts value is Buffer {\n if (!Buffer.isBuffer(value)) {\n throw new Error(`Parameter \"${name}\" needs to be a Buffer but type \"${typeof value}\" has been passed`);\n }\n }\n\n /**\n * Throws if a type is not an optional callback\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertOptionalCallback(value: unknown, name: string): asserts value is OptionalCallback {\n if (value && typeof value !== 'function') {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"null\", \"undefined\" or \"function\" but type \"${typeof value}\" has been passed`,\n );\n }\n }\n\n /**\n * Throws if a type is not an optional callback\n *\n * @param value value to check a type of\n * @param name name of the parameter for logging\n */\n static assertCallback(value: unknown, name: string): asserts value is Callback {\n if (typeof value !== 'function') {\n throw new Error(\n `Parameter \"${name}\" needs to be of type \"function\" but type \"${typeof value}\" has been passed`,\n );\n }\n }\n\n /**\n * Adds the namespace to the ID if it is missing, if an object is passed it will be converted to an id string\n *\n * @param id id which will be fixed\n * @param isPattern if the id is a pattern\n */\n fixId(id: string | ioBroker.IdObject, isPattern = false): string {\n if (!id) {\n id = '';\n }\n\n let result = '';\n if (typeof id === 'string') {\n result = id;\n\n // if not the instance name itself and also not starts with namespace and \".\"\n if (id !== this.namespace && !this.namespaceRegExp.test(id)) {\n if (!isPattern) {\n result = this.namespace + (id ? `.${id}` : '');\n } else {\n result = `${this.namespace}.${id ? id : ''}`;\n }\n }\n } else if (tools.isObject(id)) {\n // If ID is an object\n // Add namespace + device + channel\n result = `${this.namespace}.${id.device ? `${id.device}.` : ''}${id.channel ? `${id.channel}.` : ''}${\n id.state ? id.state : ''\n }`;\n }\n return result;\n }\n\n /**\n * Validates the object-type argument that is passed to setState\n *\n * @param obj object to validate\n */\n validateSetStateObjectArgument(obj: Record<string, any>): void {\n // Check that we have at least one existing non-undefined property at all, else invalid\n if (!Object.values(obj).some(prop => prop !== undefined)) {\n throw new Error(`The state contains no properties! At least one property is expected!`);\n }\n\n /*\n The following object parameters and types are allowed:\n val: any, (optional)\n ack: boolean, (optional)\n ts: number, (optional)\n q: number, (optional)\n from: string, (optional)\n c: string, (optional)\n expire: number (optional)\n lc: number (optional)\n user: string (optional)\n\n Everything else is forbidden\n */\n const optionalProperties: Record<string, string> = {\n val: 'any',\n ack: 'boolean',\n ts: 'number',\n q: 'number',\n from: 'string',\n c: 'string',\n expire: 'number',\n lc: 'number',\n user: 'string',\n };\n\n // Are there any forbidden properties?\n const forbiddenProperties = Object.keys(obj).filter(k => !optionalProperties[k]);\n if (forbiddenProperties.length) {\n throw new Error(`The state contains the forbidden properties ${forbiddenProperties.join(', ')}!`);\n }\n // Do all properties have the correct type?\n for (const [key, type] of Object.entries(optionalProperties)) {\n // any permits all types\n if (type === 'any') {\n continue;\n }\n // don't flag optional properties when they don't exist or are undefined\n if (!(key in obj) || obj[key] === undefined) {\n continue;\n }\n if (type !== typeof obj[key]) {\n throw new Error(\n `The state property \"${key}\" has the wrong type \"${typeof obj[key]}\" (should be \"${type}\")!`,\n );\n }\n }\n }\n\n /**\n * Validates that the timeout is not exceeding a 32-bit signed integer\n *\n * @param ms milliseconds to validate\n */\n static assertTimeout(ms: number): void {\n if (ms > MAX_TIMEOUT) {\n throw new Error(`Timeout (${ms}) is larger than a 32-bit signed integer (${MAX_TIMEOUT})`);\n }\n\n if (ms < 0) {\n throw new Error(`Timeout (${ms}) is smaller than 0`);\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;uBAA+C;AAC/C,kCAAkC;AAa5B,MAAO,UAAS;EACD;EACA;EACA;EACA;EACA;EACA
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,cAAc,iBAAiB,CAAC"}
|
package/build/esm/index.js
CHANGED
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,cAAc,iBAAiB,CAAC"}
|