@iobroker/js-controller-common 7.2.3 → 8.0.0-alpha.2-20260923-99da17fcc

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 (42) hide show
  1. package/build/cjs/index.js +5 -5
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/lib/common/constants.d.ts +1 -1
  4. package/build/cjs/lib/common/constants.js +3 -1
  5. package/build/cjs/lib/common/constants.js.map +2 -2
  6. package/build/cjs/lib/common/notificationHandler.js +6 -2
  7. package/build/cjs/lib/common/notificationHandler.js.map +2 -2
  8. package/build/cjs/lib/common/objects.d.ts +3 -0
  9. package/build/cjs/lib/common/objects.js +5 -0
  10. package/build/cjs/lib/common/objects.js.map +2 -2
  11. package/build/cjs/lib/common/states.d.ts +3 -0
  12. package/build/cjs/lib/common/states.js +5 -0
  13. package/build/cjs/lib/common/states.js.map +2 -2
  14. package/build/cjs/lib/common/tools.d.ts +5 -0
  15. package/build/cjs/lib/common/tools.js +4 -0
  16. package/build/cjs/lib/common/tools.js.map +2 -2
  17. package/build/cjs/lib/common/zipFiles.d.ts +36 -0
  18. package/build/cjs/lib/common/zipFiles.js +10 -0
  19. package/build/cjs/lib/common/zipFiles.js.map +2 -2
  20. package/build/esm/lib/common/constants.d.ts +1 -1
  21. package/build/esm/lib/common/constants.d.ts.map +1 -1
  22. package/build/esm/lib/common/constants.js +1 -0
  23. package/build/esm/lib/common/constants.js.map +1 -1
  24. package/build/esm/lib/common/notificationHandler.js +3 -3
  25. package/build/esm/lib/common/notificationHandler.js.map +1 -1
  26. package/build/esm/lib/common/objects.d.ts +3 -0
  27. package/build/esm/lib/common/objects.d.ts.map +1 -1
  28. package/build/esm/lib/common/objects.js +3 -0
  29. package/build/esm/lib/common/objects.js.map +1 -1
  30. package/build/esm/lib/common/states.d.ts +3 -0
  31. package/build/esm/lib/common/states.d.ts.map +1 -1
  32. package/build/esm/lib/common/states.js +3 -0
  33. package/build/esm/lib/common/states.js.map +1 -1
  34. package/build/esm/lib/common/tools.d.ts +5 -0
  35. package/build/esm/lib/common/tools.d.ts.map +1 -1
  36. package/build/esm/lib/common/tools.js.map +1 -1
  37. package/build/esm/lib/common/zipFiles.d.ts +36 -0
  38. package/build/esm/lib/common/zipFiles.d.ts.map +1 -1
  39. package/build/esm/lib/common/zipFiles.js +36 -2
  40. package/build/esm/lib/common/zipFiles.js.map +1 -1
  41. package/build/tsconfig.build.tsbuildinfo +1 -1
  42. package/package.json +13 -13
@@ -27,8 +27,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  mod
28
28
  ));
29
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
- var esm_exports = {};
31
- __export(esm_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  NotificationHandler: () => import_notificationHandler.NotificationHandler,
33
33
  getObjectsConstructor: () => import_objects.getObjectsConstructor,
34
34
  getStatesConstructor: () => import_states.getStatesConstructor,
@@ -41,13 +41,13 @@ __export(esm_exports, {
41
41
  statesDbHasServer: () => import_states.statesDbHasServer,
42
42
  zipFiles: () => zipFiles
43
43
  });
44
- module.exports = __toCommonJS(esm_exports);
44
+ module.exports = __toCommonJS(index_exports);
45
45
  var import_states = require("./lib/common/states.js");
46
46
  var import_objects = require("./lib/common/objects.js");
47
47
  var import_notificationHandler = require("./lib/common/notificationHandler.js");
48
48
  var zipFiles = __toESM(require("./lib/common/zipFiles.js"), 1);
49
- __reExport(esm_exports, require("./lib/common/tools.js"), module.exports);
50
- __reExport(esm_exports, require("@iobroker/js-controller-common-db"), module.exports);
49
+ __reExport(index_exports, require("./lib/common/tools.js"), module.exports);
50
+ __reExport(index_exports, require("@iobroker/js-controller-common-db"), module.exports);
51
51
  const letsencrypt = true;
52
52
  // Annotate the CommonJS export names for ESM import in node:
53
53
  0 && (module.exports = {
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
4
  "sourcesContent": ["/// <reference types=\"@iobroker/types-dev\" />\nexport {\n getStatesConstructor,\n statesDbHasServer,\n isLocalStatesDbServer,\n performStatesInterview,\n} from '@/lib/common/states.js';\nexport {\n getObjectsConstructor,\n objectsDbHasServer,\n isLocalObjectsDbServer,\n performObjectsInterview,\n} from '@/lib/common/objects.js';\nexport { NotificationHandler } from '@/lib/common/notificationHandler.js';\nexport type { SupportedFeature } from '@/lib/common/constants.js';\nexport * as zipFiles from '@/lib/common/zipFiles.js';\nexport * from '@/lib/common/tools.js';\nexport * from '@iobroker/js-controller-common-db';\n\n/** Shim until all adapters are using adapter-core 3.1.4 or higher */\nexport const letsencrypt = true;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;AACA,oBAKO;AACP,qBAKO;AACP,iCAAoC;AAEpC,eAA0B;AAC1B,wBAAc,kCAhBd;AAiBA,wBAAc,8CAjBd;AAoBO,MAAM,cAAc;",
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;AACA,oBAKO;AACP,qBAKO;AACP,iCAAoC;AAEpC,eAA0B;AAC1B,0BAAc,kCAhBd;AAiBA,0BAAc,8CAjBd;AAoBO,MAAM,cAAc;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Constants needed for adapter.js and controller
3
3
  */
4
- export declare const SUPPORTED_FEATURES: ("ALIAS" | "ALIAS_SEPARATE_READ_WRITE_ID" | "ADAPTER_GETPORT_BIND" | "ADAPTER_DEL_OBJECT_RECURSIVE" | "ADAPTER_SET_OBJECT_SETS_DEFAULT_VALUE" | "ADAPTER_AUTO_DECRYPT_NATIVE" | "PLUGINS" | "CONTROLLER_NPM_AUTO_REBUILD" | "CONTROLLER_READWRITE_BASE_SETTINGS" | "CONTROLLER_MULTI_REPO" | "CONTROLLER_LICENSE_MANAGER" | "CONTROLLER_OS_PACKAGE_UPGRADE" | "DEL_INSTANCE_CUSTOM" | "CUSTOM_FULL_VIEW" | "ADAPTER_GET_OBJECTS_BY_ARRAY" | "CONTROLLER_UI_UPGRADE" | "ADAPTER_WEBSERVER_UPGRADE" | "CONTROLLER_CMD_EXEC_FILES" | "CONTROLLER_FEATURE_REQUEST")[];
4
+ export declare const SUPPORTED_FEATURES: ("ALIAS" | "ALIAS_SEPARATE_READ_WRITE_ID" | "ADAPTER_GETPORT_BIND" | "ADAPTER_DEL_OBJECT_RECURSIVE" | "ADAPTER_SET_OBJECT_SETS_DEFAULT_VALUE" | "ADAPTER_AUTO_DECRYPT_NATIVE" | "PLUGINS" | "CONTROLLER_NPM_AUTO_REBUILD" | "CONTROLLER_READWRITE_BASE_SETTINGS" | "CONTROLLER_MULTI_REPO" | "CONTROLLER_LICENSE_MANAGER" | "CONTROLLER_OS_PACKAGE_UPGRADE" | "DEL_INSTANCE_CUSTOM" | "CUSTOM_FULL_VIEW" | "ADAPTER_GET_OBJECTS_BY_ARRAY" | "CONTROLLER_UI_UPGRADE" | "ADAPTER_WEBSERVER_UPGRADE" | "CONTROLLER_CMD_EXEC_FILES" | "CONTROLLER_FEATURE_REQUEST" | "CONTROLLER_USED_RESOURCES")[];
5
5
  export type SupportedFeature = (typeof SUPPORTED_FEATURES)[number];
6
6
  //# sourceMappingURL=constants.d.ts.map
@@ -58,8 +58,10 @@ const SUPPORTED_FEATURES_INTERNAL = [
58
58
  // Controller supports upgrading adapter and provides a webserver (triggered via sendToHost). Since `js-controller` 5.0
59
59
  "CONTROLLER_CMD_EXEC_FILES",
60
60
  // cmdExec host message supports sending files together with the command. Since `js-controller` 7.2
61
- "CONTROLLER_FEATURE_REQUEST"
61
+ "CONTROLLER_FEATURE_REQUEST",
62
62
  // js-controller supports feature support requests via host messages. Since `js-controller` 7.2
63
+ "CONTROLLER_USED_RESOURCES"
64
+ // js-controller maintains a registry of exclusive resources (serial/TCP/UDP ports, ...) used by instances. Since `js-controller` 8.0
63
65
  ];
64
66
  const SUPPORTED_FEATURES = [...SUPPORTED_FEATURES_INTERNAL];
65
67
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/common/constants.ts"],
4
- "sourcesContent": ["/**\n * Constants needed for adapter.js and controller\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 'CONTROLLER_CMD_EXEC_FILES', // cmdExec host message supports sending files together with the command. Since `js-controller` 7.2\n 'CONTROLLER_FEATURE_REQUEST', // js-controller supports feature support requests via host messages. Since `js-controller` 7.2\n] as const;\n\nexport const SUPPORTED_FEATURES = [...SUPPORTED_FEATURES_INTERNAL];\n\nexport type SupportedFeature = (typeof SUPPORTED_FEATURES)[number];\n\n// Compile-time guarantee that the runtime list stays in sync with the public `ioBroker.SupportedFeature` type (defined in @iobroker/types-dev)\ntype AssertExtends<T extends U, U> = T;\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype _AssertFeaturesInSync = AssertExtends<SupportedFeature, ioBroker.SupportedFeature> &\n AssertExtends<ioBroker.SupportedFeature, SupportedFeature>;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;AAKA,MAAM,8BAA8B;EAChC;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;;AAGG,MAAM,qBAAqB,CAAC,GAAG,2BAA2B;",
4
+ "sourcesContent": ["/**\n * Constants needed for adapter.js and controller\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 'CONTROLLER_CMD_EXEC_FILES', // cmdExec host message supports sending files together with the command. Since `js-controller` 7.2\n 'CONTROLLER_FEATURE_REQUEST', // js-controller supports feature support requests via host messages. Since `js-controller` 7.2\n 'CONTROLLER_USED_RESOURCES', // js-controller maintains a registry of exclusive resources (serial/TCP/UDP ports, ...) used by instances. Since `js-controller` 8.0\n] as const;\n\nexport const SUPPORTED_FEATURES = [...SUPPORTED_FEATURES_INTERNAL];\n\nexport type SupportedFeature = (typeof SUPPORTED_FEATURES)[number];\n\n// Compile-time guarantee that the runtime list stays in sync with the public `ioBroker.SupportedFeature` type (defined in @iobroker/types-dev)\ntype AssertExtends<T extends U, U> = T;\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype _AssertFeaturesInSync = AssertExtends<SupportedFeature, ioBroker.SupportedFeature> &\n AssertExtends<ioBroker.SupportedFeature, SupportedFeature>;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;AAKA,MAAM,8BAA8B;EAChC;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;EACA;;;AAGG,MAAM,qBAAqB,CAAC,GAAG,2BAA2B;",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
9
  var __export = (target, all) => {
9
10
  for (var name in all)
10
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -35,6 +36,9 @@ var import_fs_extra = __toESM(require("fs-extra"), 1);
35
36
  var import_js_controller_common_db = require("@iobroker/js-controller-common-db");
36
37
  var import_node_path = __toESM(require("node:path"), 1);
37
38
  class NotificationHandler {
39
+ static {
40
+ __name(this, "NotificationHandler");
41
+ }
38
42
  states;
39
43
  objects;
40
44
  log;
@@ -98,10 +102,10 @@ class NotificationHandler {
98
102
  endkey: "system.adapter.\u9999"
99
103
  });
100
104
  for (const entry of res.rows) {
101
- if (entry.value.notifications) {
105
+ if (entry.value?.notifications) {
102
106
  await this.addConfig(entry.value.notifications);
103
107
  }
104
- if (entry.value.common && entry.value.common.host === this.host) {
108
+ if (entry.value?.common.host === this.host) {
105
109
  instancesOnHost.push(entry.id);
106
110
  }
107
111
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/common/notificationHandler.ts"],
4
- "sourcesContent": ["/**\n * Notification handler class\n *\n * 2021-2024 foxriver76 <moritz.heusinger@gmail.com>\n */\n\nimport fs from 'fs-extra';\nimport { tools } from '@iobroker/js-controller-common-db';\nimport path from 'node:path';\nimport type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { Client as ObjectsInRedisClient } from '@iobroker/db-objects-redis';\nimport type Winston from 'winston';\n\ntype MultilingualObject = Exclude<ioBroker.StringOrTranslated, string>;\n\n/** Settings to configure an instance of NotificationHandler */\nexport interface NotificationHandlerSettings {\n /** Name of the host (not id - hence, without `system.host.` prefix) */\n host: string;\n /** States DB instance */\n states: StatesInRedisClient;\n /** Objects DB instance */\n objects: ObjectsInRedisClient;\n /** Logger instance */\n log: Winston.Logger | Console;\n /** Prefix for the log messages */\n logPrefix: string;\n}\n\n/** A notification config entry represents the top level of the notification structure */\nexport interface NotificationsConfigEntry {\n /** e.g. system */\n scope: string;\n /** multilingual name */\n name: MultilingualObject;\n /** multilingual description */\n description: MultilingualObject;\n /** The notification categories inside this scope */\n categories: CategoryConfigEntry[];\n}\n\nexport type Severity = 'info' | 'notify' | 'alert';\n\n/** A notification category entry represents one of the categories of a scope */\nexport interface CategoryConfigEntry {\n /** Id of the category */\n category: string;\n /** Name of the category */\n name: MultilingualObject;\n /** Allows defining the severity of the notification with `info` being the lowest, `notify` representing middle priority, `alert` representing high priority and often containing critical information */\n severity: Severity;\n /** Description of the category */\n description: MultilingualObject;\n /** Regex where `console.error` output is parsed against to check if a notification of this category should be generated */\n regex: string[];\n /** Restrict the maximum number of messages for this category */\n limit: number;\n}\n\ninterface NotificationMessageObject {\n message: string;\n ts: number;\n contextData?: ioBroker.NotificationContextData;\n}\n\ninterface NotificationsCategory {\n [category: string]: {\n [instance: string]: NotificationMessageObject[];\n };\n}\n\ninterface NotificationsObject {\n [scope: string]: NotificationsCategory;\n}\n\ninterface FilteredNotificationCategory {\n description: MultilingualObject;\n name: MultilingualObject;\n severity: Severity;\n instances: {\n [instance: string]: {\n messages: NotificationMessageObject[];\n };\n };\n}\n\ninterface FilteredNotificationScope {\n description: MultilingualObject;\n name: MultilingualObject;\n categories: {\n [category: string]: FilteredNotificationCategory;\n };\n}\n\n/** The filtered information as a response for `getFilteredInformation` */\nexport interface FilteredNotificationInformation {\n [scope: string]: FilteredNotificationScope;\n}\n\ninterface NotificationSetupCategory {\n regex: RegExp[];\n limit: number;\n name: MultilingualObject;\n severity: Severity;\n description: MultilingualObject;\n}\n\ninterface NotificationSetupObject {\n [scope: string]: {\n name: MultilingualObject;\n description: MultilingualObject;\n categories: {\n [category: string]: NotificationSetupCategory;\n };\n };\n}\n\ninterface ScopeStateValue {\n [category: string]: {\n count: number;\n };\n}\n\ninterface AddMessageOptions {\n /** Scope of the message */\n scope: string;\n /** Category of the message, if non we check against regex of scope */\n category?: string | null;\n /** Message to add */\n message: string;\n /** Instance e.g., hm-rpc.1 or hostname, if hostname it needs to be prefixed like system.host.rpi */\n instance: string;\n /** Additional context for the notification which can be used by notification processing adapters */\n contextData?: ioBroker.NotificationContextData;\n}\n\n/**\n * The Notification handler class provides an interface to manage the ioBroker notification system\n */\nexport class NotificationHandler {\n private states: StatesInRedisClient;\n private objects: ObjectsInRedisClient;\n private log: Winston.Logger | Console;\n private currentNotifications: NotificationsObject = {};\n // default data dir is relative to controllerDir\n private readonly dataDir = path.join(tools.getControllerDir(), tools.getDefaultDataDir());\n private readonly setup: NotificationSetupObject = {};\n private readonly logPrefix: string;\n private readonly host: string;\n\n /**\n * Creates a new instance of the notification handler class\n *\n * @param settings settings to configure the handler instance\n */\n constructor(settings: NotificationHandlerSettings) {\n this.states = settings.states;\n this.objects = settings.objects;\n this.log = settings.log;\n this.logPrefix = settings.logPrefix;\n this.host = settings.host;\n\n // load notifications file\n this._loadNotifications();\n }\n\n /**\n * Get all adapter instances on this host and store their notifications config - and clears up removed instances notifications - should be called once after init\n */\n async getSetupOfAllAdaptersFromHost(): Promise<void> {\n // create the initial notifications object\n let obj;\n try {\n obj = await this.objects.getObject(`system.host.${this.host}.notifications`);\n } catch {\n // ignore\n }\n\n if (!obj) {\n try {\n await this.objects.setObject(`system.host.${this.host}.notifications`, {\n type: 'folder',\n common: {\n name: {\n en: 'Notifications',\n de: 'Benachrichtigungen',\n ru: '\u0423\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F',\n pt: 'Notifica\u00E7\u00F5es',\n nl: 'Meldingen',\n fr: 'Notifications',\n it: 'Notifiche',\n es: 'Notificaciones',\n pl: 'Powiadomienia',\n uk: '\u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F',\n 'zh-cn': '\u901A\u77E5\u4E8B\u9879',\n },\n },\n native: {},\n });\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not create notifications object: ${e.message}`);\n }\n }\n\n const instancesOnHost = [];\n // get all instances\n try {\n const res = await this.objects.getObjectViewAsync('system', 'instance', {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999',\n });\n\n for (const entry of res.rows) {\n // check that instance has notification settings\n if (entry.value.notifications) {\n await this.addConfig(entry.value.notifications);\n }\n\n if (entry.value.common && entry.value.common.host === this.host) {\n // if it's on our current host\n instancesOnHost.push(entry.id);\n }\n }\n } catch (e) {\n throw new Error(`Could not get notifications setup from instances: ${e.message}`);\n }\n\n // now clear up all notifications that do not belong to our host anymore\n for (const notificationsCategory of Object.values(this.currentNotifications)) {\n for (const instancesInfo of Object.values(notificationsCategory)) {\n for (const instance of Object.keys(instancesInfo)) {\n if (!instancesOnHost.includes(instance) && instance !== `system.host.${this.host}`) {\n // instance no longer on host\n this.log.info(`${this.logPrefix} Instance ${instance} removed from host, clear notifications`);\n await this.clearNotifications(null, null, instance);\n }\n }\n }\n }\n\n // now sync RAM with state\n await this._updateScopeStates();\n }\n\n /**\n * Add a new category to the given scope with a provided optional list of regex\n *\n * @param notifications - Array with notifications\n */\n async addConfig(notifications: NotificationsConfigEntry[]): Promise<void> {\n // if valid attributes, store it\n if (Array.isArray(notifications)) {\n for (const scopeObj of notifications) {\n // create the state object for each scope if non-existing\n let obj;\n try {\n obj = await this.objects.getObject(`system.host.${this.host}.notifications.${scopeObj.scope}`);\n } catch {\n // ignore\n }\n\n if (!obj) {\n try {\n await this.objects.setObject(`system.host.${this.host}.notifications.${scopeObj.scope}`, {\n type: 'state',\n common: {\n type: 'object',\n role: 'value',\n read: true,\n write: false,\n name: scopeObj.name,\n desc: scopeObj.description,\n },\n native: {},\n });\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Could not create notifications object for scope \"${scopeObj.scope}\": ${e.message}`,\n );\n }\n }\n\n if (Array.isArray(scopeObj.categories) && scopeObj.categories.length) {\n const setupScope = this.setup[scopeObj.scope] || {\n name: scopeObj.name,\n description: scopeObj.description,\n categories: {},\n };\n\n // only if scope has at least one category\n this.setup[scopeObj.scope] = setupScope;\n\n for (const categoryObj of scopeObj.categories) {\n const setupCategory = setupScope.categories[categoryObj.category] || {\n regex: [],\n limit: categoryObj.limit,\n name: categoryObj.name,\n severity: categoryObj.severity,\n description: categoryObj.description,\n };\n setupScope.categories[categoryObj.category] = setupCategory;\n\n try {\n let regex: RegExp[] = [];\n if (Array.isArray(categoryObj.regex)) {\n for (const regexString of categoryObj.regex) {\n regex.push(new RegExp(regexString));\n }\n } else if (typeof categoryObj.regex === 'string') {\n // if someone passes a string, convert to a single entry array\n regex = [new RegExp(categoryObj.regex)];\n }\n\n setupCategory.regex = regex;\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Cannot store regex \"${JSON.stringify(categoryObj.regex)}\" for scope \"${\n scopeObj.scope\n }\", category \"${categoryObj.category}\": ${e.message}`,\n );\n }\n }\n }\n }\n }\n }\n\n /**\n * Add a message to the scope and category\n *\n * @param options The scope, category, message, instance and contextData information\n */\n async addMessage(options: AddMessageOptions): Promise<void> {\n const { message, scope, category, contextData } = options;\n let { instance } = options;\n\n if (typeof instance !== 'string') {\n this.log.error(\n `${this.logPrefix} [addMessage] Instance has to be of type \"string\", got \"${typeof instance}\"`,\n );\n return;\n }\n\n if (!instance.startsWith('system.adapter.') && !instance.startsWith('system.host.')) {\n instance = `system.adapter.${instance}`;\n }\n\n // get state of the scope\n let stateVal: ScopeStateValue = {};\n try {\n const state = await this.states.getStateAsync(`system.host.${this.host}.notifications.${scope}`);\n stateVal = state?.val ? JSON.parse(state.val as string) : {};\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not get state for scope \"${scope}\": ${e.message}`);\n }\n\n let categories = [category];\n\n if (!category) {\n // check regex - in parse text we can have multiple matches\n categories = this._parseText(scope, message);\n }\n\n const currentScopeObj = this.currentNotifications[scope] || {};\n this.currentNotifications[scope] = currentScopeObj;\n\n for (const _category of categories) {\n if (!_category) {\n continue;\n }\n\n const currentCategoryObj = currentScopeObj[_category] || {};\n currentScopeObj[_category] = currentCategoryObj;\n\n // array of all messages for instance/category\n const currentInstances = currentCategoryObj[instance] || [];\n currentCategoryObj[instance] = currentInstances;\n\n const setupCategory = this.setup[scope]?.categories[_category];\n\n if (!setupCategory) {\n // no setup for this instance/category combination found - so we have nothing to add\n this.log.warn(\n `${this.logPrefix} No configuration found for scope \"${scope}\" and category \"${_category}\"`,\n );\n continue;\n }\n\n // if limit exceeded, remove last element - use while if it somehow grew too big\n while (setupCategory.limit < currentInstances.length + 1) {\n currentInstances.pop();\n }\n\n // add a new element at the beginning\n currentInstances.unshift({ message, ts: Date.now(), contextData });\n }\n\n // now count all messages of this scope - if nothing matched it can be undefined, and we can skip\n if (tools.isObject(this.currentNotifications[scope])) {\n for (const [categoryName, category] of Object.entries(currentScopeObj)) {\n const categoryCounter = Object.keys(category).length;\n\n stateVal[categoryName] = { count: categoryCounter };\n }\n }\n\n // set updated scope state\n try {\n await this.states.setState(`system.host.${this.host}.notifications.${scope}`, {\n val: JSON.stringify(stateVal),\n ack: true,\n });\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not set notifications state for scope \"${scope}\": ${e.message}`);\n }\n }\n\n /**\n * Updates all scope states by current notifications in RAM\n */\n private async _updateScopeStates(): Promise<void> {\n for (const [scope, scopeObj] of Object.entries(this.currentNotifications)) {\n const stateVal: ScopeStateValue = {};\n\n for (const [category, categoryObj] of Object.entries(scopeObj)) {\n // count the number of instances with this error\n const catCounter = Object.keys(categoryObj).length;\n stateVal[category] = { count: catCounter };\n }\n\n // set updated scope state\n try {\n await this.states.setState(`system.host.${this.host}.notifications.${scope}`, {\n val: JSON.stringify(stateVal),\n ack: true,\n });\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Could not set notifications state for scope \"${scope}\": ${e.message}`,\n );\n }\n }\n }\n\n /**\n * Check the given message against all regular expressions of the given scope\n *\n * @param scope - scope of the message\n * @param message - message to check\n */\n private _parseText(scope: string, message: string): string[] {\n const categories: string[] = [];\n\n const scopeObj = this.setup[scope];\n\n if (!scopeObj) {\n return categories;\n }\n\n for (const [categoryId, categoryObj] of Object.entries(scopeObj.categories)) {\n // check all regular expressions for this category\n for (const regex of categoryObj.regex) {\n if (regex.test(message)) {\n // matching category\n categories.push(categoryId);\n // no further testing needed for this category\n break;\n }\n }\n }\n\n return categories;\n }\n\n /**\n * Load notifications from a file\n */\n private _loadNotifications(): void {\n try {\n this.currentNotifications = fs.readJSONSync(path.join(this.dataDir, 'notifications.json'));\n } catch (e) {\n // at first start its normal, that we cannot read notifications, so just info\n this.log.debug(`${this.logPrefix} Could not read notifications.json: ${e.message}`);\n }\n }\n\n /**\n * Save current notifications to file\n */\n storeNotifications(): void {\n try {\n fs.writeJSONSync(path.join(this.dataDir, 'notifications.json'), this.currentNotifications);\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not write notifications.json: ${e.message}`);\n }\n }\n\n /**\n * Returns the stored notifications matching the filters with description and name\n *\n * @param scopeFilter - scope of notifications\n * @param categoryFilter - category of notifications\n * @param instanceFilter - instance of notifications\n */\n getFilteredInformation(\n scopeFilter: string | null | undefined,\n categoryFilter: string | null | undefined,\n instanceFilter: string | null | undefined,\n ): FilteredNotificationInformation {\n const res: FilteredNotificationInformation = {};\n for (const [scope, currentNotification] of Object.entries(this.currentNotifications)) {\n if (scopeFilter && scopeFilter !== scope) {\n // scope filtered out\n continue;\n }\n\n const scopeObj = this.setup[scope];\n\n if (!scopeObj) {\n // no scope set up\n continue;\n }\n\n const scopeResult: FilteredNotificationScope = {\n categories: {},\n description: scopeObj.description,\n name: scopeObj.name,\n };\n\n res[scope] = scopeResult;\n\n for (const [category, currentCategoryObj] of Object.entries(currentNotification)) {\n if (categoryFilter && categoryFilter !== category) {\n // category filtered out\n continue;\n }\n\n const categoryObj = scopeObj.categories[category];\n\n if (!categoryObj) {\n // no category set up\n continue;\n }\n\n const resultCategories: FilteredNotificationCategory = {\n instances: {},\n description: categoryObj.description,\n name: categoryObj.name,\n severity: categoryObj.severity,\n };\n\n scopeResult.categories[category] = resultCategories;\n\n for (const [instance, instanceObj] of Object.entries(currentCategoryObj)) {\n if (instanceFilter && instanceFilter !== instance) {\n // instance filtered out\n continue;\n }\n\n resultCategories.instances[instance] = {\n messages: instanceObj,\n };\n }\n }\n }\n return res;\n }\n\n /**\n * Clears the stored notifications matching the filters\n *\n * @param scopeFilter - scope of notifications\n * @param categoryFilter - category of notifications\n * @param instanceFilter - instance of notifications\n */\n async clearNotifications(\n scopeFilter: string | null | undefined,\n categoryFilter: string | null | undefined,\n instanceFilter: string | null | undefined,\n ): Promise<void> {\n for (const scope of Object.keys(this.currentNotifications)) {\n const currentNotificationScope = this.currentNotifications[scope];\n\n if (!currentNotificationScope) {\n delete this.currentNotifications[scope];\n continue;\n }\n if (scopeFilter && scopeFilter !== scope) {\n // skip this, because not desired to be deleted\n continue;\n }\n\n let stateVal: ScopeStateValue = {};\n try {\n const state = await this.states.getStateAsync(`system.host.${this.host}.notifications.${scope}`);\n stateVal = state && state.val ? JSON.parse(state.val as string) : {};\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not get state for scope \"${scope}\": ${e.message}`);\n }\n\n for (const [category, categoryObj] of Object.entries(currentNotificationScope)) {\n if (categoryFilter && categoryFilter !== category) {\n // category filtered out\n continue;\n }\n\n let categoryCounter = 0;\n for (const instance of Object.keys(categoryObj)) {\n if (instanceFilter && instanceFilter !== instance) {\n // instance filtered out - message counter remains\n categoryCounter += 1;\n continue;\n }\n\n // not filtered out -> remove\n delete categoryObj[instance];\n }\n\n stateVal[category] = { count: categoryCounter };\n\n // check if all instances of this category deleted\n if (!Object.keys(categoryObj).length) {\n delete currentNotificationScope[category];\n delete stateVal[category];\n }\n }\n\n // check if all categories of this scope deleted\n if (!Object.keys(currentNotificationScope).length) {\n delete this.currentNotifications[scope];\n }\n\n // set updated state\n try {\n await this.states.setState(`system.host.${this.host}.notifications.${scope}`, {\n val: JSON.stringify(stateVal),\n ack: true,\n });\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Could not set notifications state for scope \"${scope}\": ${e.message}`,\n );\n }\n }\n }\n\n /**\n * Check if given scope exists in config\n *\n * @param scope - scope to be checked for\n */\n scopeExists(scope: string): boolean {\n return !!this.setup[scope];\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Notification handler class\n *\n * 2021-2024 foxriver76 <moritz.heusinger@gmail.com>\n */\n\nimport fs from 'fs-extra';\nimport { tools } from '@iobroker/js-controller-common-db';\nimport path from 'node:path';\nimport type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { Client as ObjectsInRedisClient } from '@iobroker/db-objects-redis';\nimport type Winston from 'winston';\n\ntype MultilingualObject = Exclude<ioBroker.StringOrTranslated, string>;\n\n/** Settings to configure an instance of NotificationHandler */\nexport interface NotificationHandlerSettings {\n /** Name of the host (not id - hence, without `system.host.` prefix) */\n host: string;\n /** States DB instance */\n states: StatesInRedisClient;\n /** Objects DB instance */\n objects: ObjectsInRedisClient;\n /** Logger instance */\n log: Winston.Logger | Console;\n /** Prefix for the log messages */\n logPrefix: string;\n}\n\n/** A notification config entry represents the top level of the notification structure */\nexport interface NotificationsConfigEntry {\n /** e.g. system */\n scope: string;\n /** multilingual name */\n name: MultilingualObject;\n /** multilingual description */\n description: MultilingualObject;\n /** The notification categories inside this scope */\n categories: CategoryConfigEntry[];\n}\n\nexport type Severity = 'info' | 'notify' | 'alert';\n\n/** A notification category entry represents one of the categories of a scope */\nexport interface CategoryConfigEntry {\n /** Id of the category */\n category: string;\n /** Name of the category */\n name: MultilingualObject;\n /** Allows defining the severity of the notification with `info` being the lowest, `notify` representing middle priority, `alert` representing high priority and often containing critical information */\n severity: Severity;\n /** Description of the category */\n description: MultilingualObject;\n /** Regex where `console.error` output is parsed against to check if a notification of this category should be generated */\n regex: string[];\n /** Restrict the maximum number of messages for this category */\n limit: number;\n}\n\ninterface NotificationMessageObject {\n message: string;\n ts: number;\n contextData?: ioBroker.NotificationContextData;\n}\n\ninterface NotificationsCategory {\n [category: string]: {\n [instance: string]: NotificationMessageObject[];\n };\n}\n\ninterface NotificationsObject {\n [scope: string]: NotificationsCategory;\n}\n\ninterface FilteredNotificationCategory {\n description: MultilingualObject;\n name: MultilingualObject;\n severity: Severity;\n instances: {\n [instance: string]: {\n messages: NotificationMessageObject[];\n };\n };\n}\n\ninterface FilteredNotificationScope {\n description: MultilingualObject;\n name: MultilingualObject;\n categories: {\n [category: string]: FilteredNotificationCategory;\n };\n}\n\n/** The filtered information as a response for `getFilteredInformation` */\nexport interface FilteredNotificationInformation {\n [scope: string]: FilteredNotificationScope;\n}\n\ninterface NotificationSetupCategory {\n regex: RegExp[];\n limit: number;\n name: MultilingualObject;\n severity: Severity;\n description: MultilingualObject;\n}\n\ninterface NotificationSetupObject {\n [scope: string]: {\n name: MultilingualObject;\n description: MultilingualObject;\n categories: {\n [category: string]: NotificationSetupCategory;\n };\n };\n}\n\ninterface ScopeStateValue {\n [category: string]: {\n count: number;\n };\n}\n\ninterface AddMessageOptions {\n /** Scope of the message */\n scope: string;\n /** Category of the message, if non we check against regex of scope */\n category?: string | null;\n /** Message to add */\n message: string;\n /** Instance e.g., hm-rpc.1 or hostname, if hostname it needs to be prefixed like system.host.rpi */\n instance: string;\n /** Additional context for the notification which can be used by notification processing adapters */\n contextData?: ioBroker.NotificationContextData;\n}\n\n/**\n * The Notification handler class provides an interface to manage the ioBroker notification system\n */\nexport class NotificationHandler {\n private states: StatesInRedisClient;\n private objects: ObjectsInRedisClient;\n private log: Winston.Logger | Console;\n private currentNotifications: NotificationsObject = {};\n // default data dir is relative to controllerDir\n private readonly dataDir = path.join(tools.getControllerDir(), tools.getDefaultDataDir());\n private readonly setup: NotificationSetupObject = {};\n private readonly logPrefix: string;\n private readonly host: string;\n\n /**\n * Creates a new instance of the notification handler class\n *\n * @param settings settings to configure the handler instance\n */\n constructor(settings: NotificationHandlerSettings) {\n this.states = settings.states;\n this.objects = settings.objects;\n this.log = settings.log;\n this.logPrefix = settings.logPrefix;\n this.host = settings.host;\n\n // load notifications file\n this._loadNotifications();\n }\n\n /**\n * Get all adapter instances on this host and store their notifications config - and clears up removed instances notifications - should be called once after init\n */\n async getSetupOfAllAdaptersFromHost(): Promise<void> {\n // create the initial notifications object\n let obj;\n try {\n obj = await this.objects.getObject(`system.host.${this.host}.notifications`);\n } catch {\n // ignore\n }\n\n if (!obj) {\n try {\n await this.objects.setObject(`system.host.${this.host}.notifications`, {\n type: 'folder',\n common: {\n name: {\n en: 'Notifications',\n de: 'Benachrichtigungen',\n ru: '\u0423\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F',\n pt: 'Notifica\u00E7\u00F5es',\n nl: 'Meldingen',\n fr: 'Notifications',\n it: 'Notifiche',\n es: 'Notificaciones',\n pl: 'Powiadomienia',\n uk: '\u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F',\n 'zh-cn': '\u901A\u77E5\u4E8B\u9879',\n },\n },\n native: {},\n });\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not create notifications object: ${e.message}`);\n }\n }\n\n const instancesOnHost = [];\n // get all instances\n try {\n const res = await this.objects.getObjectViewAsync('system', 'instance', {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999',\n });\n\n for (const entry of res.rows) {\n if (entry.value?.notifications) {\n // check that instance has notification settings\n await this.addConfig(entry.value.notifications);\n }\n\n if (entry.value?.common.host === this.host) {\n // if it's on our current host\n instancesOnHost.push(entry.id);\n }\n }\n } catch (e) {\n throw new Error(`Could not get notifications setup from instances: ${e.message}`);\n }\n\n // now clear up all notifications that do not belong to our host anymore\n for (const notificationsCategory of Object.values(this.currentNotifications)) {\n for (const instancesInfo of Object.values(notificationsCategory)) {\n for (const instance of Object.keys(instancesInfo)) {\n if (!instancesOnHost.includes(instance) && instance !== `system.host.${this.host}`) {\n // instance no longer on host\n this.log.info(`${this.logPrefix} Instance ${instance} removed from host, clear notifications`);\n await this.clearNotifications(null, null, instance);\n }\n }\n }\n }\n\n // now sync RAM with state\n await this._updateScopeStates();\n }\n\n /**\n * Add a new category to the given scope with a provided optional list of regex\n *\n * @param notifications - Array with notifications\n */\n async addConfig(notifications: NotificationsConfigEntry[]): Promise<void> {\n // if valid attributes, store it\n if (Array.isArray(notifications)) {\n for (const scopeObj of notifications) {\n // create the state object for each scope if non-existing\n let obj;\n try {\n obj = await this.objects.getObject(`system.host.${this.host}.notifications.${scopeObj.scope}`);\n } catch {\n // ignore\n }\n\n if (!obj) {\n try {\n await this.objects.setObject(`system.host.${this.host}.notifications.${scopeObj.scope}`, {\n type: 'state',\n common: {\n type: 'object',\n role: 'value',\n read: true,\n write: false,\n name: scopeObj.name,\n desc: scopeObj.description,\n },\n native: {},\n });\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Could not create notifications object for scope \"${scopeObj.scope}\": ${e.message}`,\n );\n }\n }\n\n if (Array.isArray(scopeObj.categories) && scopeObj.categories.length) {\n const setupScope = this.setup[scopeObj.scope] || {\n name: scopeObj.name,\n description: scopeObj.description,\n categories: {},\n };\n\n // only if scope has at least one category\n this.setup[scopeObj.scope] = setupScope;\n\n for (const categoryObj of scopeObj.categories) {\n const setupCategory = setupScope.categories[categoryObj.category] || {\n regex: [],\n limit: categoryObj.limit,\n name: categoryObj.name,\n severity: categoryObj.severity,\n description: categoryObj.description,\n };\n setupScope.categories[categoryObj.category] = setupCategory;\n\n try {\n let regex: RegExp[] = [];\n if (Array.isArray(categoryObj.regex)) {\n for (const regexString of categoryObj.regex) {\n regex.push(new RegExp(regexString));\n }\n } else if (typeof categoryObj.regex === 'string') {\n // if someone passes a string, convert to a single entry array\n regex = [new RegExp(categoryObj.regex)];\n }\n\n setupCategory.regex = regex;\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Cannot store regex \"${JSON.stringify(categoryObj.regex)}\" for scope \"${\n scopeObj.scope\n }\", category \"${categoryObj.category}\": ${e.message}`,\n );\n }\n }\n }\n }\n }\n }\n\n /**\n * Add a message to the scope and category\n *\n * @param options The scope, category, message, instance and contextData information\n */\n async addMessage(options: AddMessageOptions): Promise<void> {\n const { message, scope, category, contextData } = options;\n let { instance } = options;\n\n if (typeof instance !== 'string') {\n this.log.error(\n `${this.logPrefix} [addMessage] Instance has to be of type \"string\", got \"${typeof instance}\"`,\n );\n return;\n }\n\n if (!instance.startsWith('system.adapter.') && !instance.startsWith('system.host.')) {\n instance = `system.adapter.${instance}`;\n }\n\n // get state of the scope\n let stateVal: ScopeStateValue = {};\n try {\n const state = await this.states.getStateAsync(`system.host.${this.host}.notifications.${scope}`);\n stateVal = state?.val ? JSON.parse(state.val as string) : {};\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not get state for scope \"${scope}\": ${e.message}`);\n }\n\n let categories = [category];\n\n if (!category) {\n // check regex - in parse text we can have multiple matches\n categories = this._parseText(scope, message);\n }\n\n const currentScopeObj = this.currentNotifications[scope] || {};\n this.currentNotifications[scope] = currentScopeObj;\n\n for (const _category of categories) {\n if (!_category) {\n continue;\n }\n\n const currentCategoryObj = currentScopeObj[_category] || {};\n currentScopeObj[_category] = currentCategoryObj;\n\n // array of all messages for instance/category\n const currentInstances = currentCategoryObj[instance] || [];\n currentCategoryObj[instance] = currentInstances;\n\n const setupCategory = this.setup[scope]?.categories[_category];\n\n if (!setupCategory) {\n // no setup for this instance/category combination found - so we have nothing to add\n this.log.warn(\n `${this.logPrefix} No configuration found for scope \"${scope}\" and category \"${_category}\"`,\n );\n continue;\n }\n\n // if limit exceeded, remove last element - use while if it somehow grew too big\n while (setupCategory.limit < currentInstances.length + 1) {\n currentInstances.pop();\n }\n\n // add a new element at the beginning\n currentInstances.unshift({ message, ts: Date.now(), contextData });\n }\n\n // now count all messages of this scope - if nothing matched it can be undefined, and we can skip\n if (tools.isObject(this.currentNotifications[scope])) {\n for (const [categoryName, category] of Object.entries(currentScopeObj)) {\n const categoryCounter = Object.keys(category).length;\n\n stateVal[categoryName] = { count: categoryCounter };\n }\n }\n\n // set updated scope state\n try {\n await this.states.setState(`system.host.${this.host}.notifications.${scope}`, {\n val: JSON.stringify(stateVal),\n ack: true,\n });\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not set notifications state for scope \"${scope}\": ${e.message}`);\n }\n }\n\n /**\n * Updates all scope states by current notifications in RAM\n */\n private async _updateScopeStates(): Promise<void> {\n for (const [scope, scopeObj] of Object.entries(this.currentNotifications)) {\n const stateVal: ScopeStateValue = {};\n\n for (const [category, categoryObj] of Object.entries(scopeObj)) {\n // count the number of instances with this error\n const catCounter = Object.keys(categoryObj).length;\n stateVal[category] = { count: catCounter };\n }\n\n // set updated scope state\n try {\n await this.states.setState(`system.host.${this.host}.notifications.${scope}`, {\n val: JSON.stringify(stateVal),\n ack: true,\n });\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Could not set notifications state for scope \"${scope}\": ${e.message}`,\n );\n }\n }\n }\n\n /**\n * Check the given message against all regular expressions of the given scope\n *\n * @param scope - scope of the message\n * @param message - message to check\n */\n private _parseText(scope: string, message: string): string[] {\n const categories: string[] = [];\n\n const scopeObj = this.setup[scope];\n\n if (!scopeObj) {\n return categories;\n }\n\n for (const [categoryId, categoryObj] of Object.entries(scopeObj.categories)) {\n // check all regular expressions for this category\n for (const regex of categoryObj.regex) {\n if (regex.test(message)) {\n // matching category\n categories.push(categoryId);\n // no further testing needed for this category\n break;\n }\n }\n }\n\n return categories;\n }\n\n /**\n * Load notifications from a file\n */\n private _loadNotifications(): void {\n try {\n this.currentNotifications = fs.readJSONSync(path.join(this.dataDir, 'notifications.json'));\n } catch (e) {\n // at first start its normal, that we cannot read notifications, so just info\n this.log.debug(`${this.logPrefix} Could not read notifications.json: ${e.message}`);\n }\n }\n\n /**\n * Save current notifications to file\n */\n storeNotifications(): void {\n try {\n fs.writeJSONSync(path.join(this.dataDir, 'notifications.json'), this.currentNotifications);\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not write notifications.json: ${e.message}`);\n }\n }\n\n /**\n * Returns the stored notifications matching the filters with description and name\n *\n * @param scopeFilter - scope of notifications\n * @param categoryFilter - category of notifications\n * @param instanceFilter - instance of notifications\n */\n getFilteredInformation(\n scopeFilter: string | null | undefined,\n categoryFilter: string | null | undefined,\n instanceFilter: string | null | undefined,\n ): FilteredNotificationInformation {\n const res: FilteredNotificationInformation = {};\n for (const [scope, currentNotification] of Object.entries(this.currentNotifications)) {\n if (scopeFilter && scopeFilter !== scope) {\n // scope filtered out\n continue;\n }\n\n const scopeObj = this.setup[scope];\n\n if (!scopeObj) {\n // no scope set up\n continue;\n }\n\n const scopeResult: FilteredNotificationScope = {\n categories: {},\n description: scopeObj.description,\n name: scopeObj.name,\n };\n\n res[scope] = scopeResult;\n\n for (const [category, currentCategoryObj] of Object.entries(currentNotification)) {\n if (categoryFilter && categoryFilter !== category) {\n // category filtered out\n continue;\n }\n\n const categoryObj = scopeObj.categories[category];\n\n if (!categoryObj) {\n // no category set up\n continue;\n }\n\n const resultCategories: FilteredNotificationCategory = {\n instances: {},\n description: categoryObj.description,\n name: categoryObj.name,\n severity: categoryObj.severity,\n };\n\n scopeResult.categories[category] = resultCategories;\n\n for (const [instance, instanceObj] of Object.entries(currentCategoryObj)) {\n if (instanceFilter && instanceFilter !== instance) {\n // instance filtered out\n continue;\n }\n\n resultCategories.instances[instance] = {\n messages: instanceObj,\n };\n }\n }\n }\n return res;\n }\n\n /**\n * Clears the stored notifications matching the filters\n *\n * @param scopeFilter - scope of notifications\n * @param categoryFilter - category of notifications\n * @param instanceFilter - instance of notifications\n */\n async clearNotifications(\n scopeFilter: string | null | undefined,\n categoryFilter: string | null | undefined,\n instanceFilter: string | null | undefined,\n ): Promise<void> {\n for (const scope of Object.keys(this.currentNotifications)) {\n const currentNotificationScope = this.currentNotifications[scope];\n\n if (!currentNotificationScope) {\n delete this.currentNotifications[scope];\n continue;\n }\n if (scopeFilter && scopeFilter !== scope) {\n // skip this, because not desired to be deleted\n continue;\n }\n\n let stateVal: ScopeStateValue = {};\n try {\n const state = await this.states.getStateAsync(`system.host.${this.host}.notifications.${scope}`);\n stateVal = state && state.val ? JSON.parse(state.val as string) : {};\n } catch (e) {\n this.log.error(`${this.logPrefix} Could not get state for scope \"${scope}\": ${e.message}`);\n }\n\n for (const [category, categoryObj] of Object.entries(currentNotificationScope)) {\n if (categoryFilter && categoryFilter !== category) {\n // category filtered out\n continue;\n }\n\n let categoryCounter = 0;\n for (const instance of Object.keys(categoryObj)) {\n if (instanceFilter && instanceFilter !== instance) {\n // instance filtered out - message counter remains\n categoryCounter += 1;\n continue;\n }\n\n // not filtered out -> remove\n delete categoryObj[instance];\n }\n\n stateVal[category] = { count: categoryCounter };\n\n // check if all instances of this category deleted\n if (!Object.keys(categoryObj).length) {\n delete currentNotificationScope[category];\n delete stateVal[category];\n }\n }\n\n // check if all categories of this scope deleted\n if (!Object.keys(currentNotificationScope).length) {\n delete this.currentNotifications[scope];\n }\n\n // set updated state\n try {\n await this.states.setState(`system.host.${this.host}.notifications.${scope}`, {\n val: JSON.stringify(stateVal),\n ack: true,\n });\n } catch (e) {\n this.log.error(\n `${this.logPrefix} Could not set notifications state for scope \"${scope}\": ${e.message}`,\n );\n }\n }\n }\n\n /**\n * Check if given scope exists in config\n *\n * @param scope - scope to be checked for\n */\n scopeExists(scope: string): boolean {\n return !!this.setup[scope];\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "category", "fs"]
7
7
  }
@@ -1,4 +1,7 @@
1
1
  import type { Client as ObjectsClient } from '@iobroker/db-objects-redis';
2
+ /**
3
+ * Get the objects database client constructor matching the configured objects DB type
4
+ */
2
5
  export declare function getObjectsConstructor(): Promise<typeof ObjectsClient>;
3
6
  /**
4
7
  * Allows to find out if a given objects dbType offers a server which runs on this host and listens (locally or globally/by IP)
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
9
  var __export = (target, all) => {
9
10
  for (var name in all)
10
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -50,6 +51,7 @@ async function getObjectsConstructor() {
50
51
  process.exit(101);
51
52
  }
52
53
  }
54
+ __name(getObjectsConstructor, "getObjectsConstructor");
53
55
  async function isLocalObjectsDbServer(dbType, host, checkIfLocalOnly = false) {
54
56
  const hasServer = await objectsDbHasServer(dbType);
55
57
  if (!hasServer) {
@@ -65,6 +67,7 @@ async function isLocalObjectsDbServer(dbType, host, checkIfLocalOnly = false) {
65
67
  }
66
68
  return result;
67
69
  }
70
+ __name(isLocalObjectsDbServer, "isLocalObjectsDbServer");
68
71
  async function objectsDbHasServer(dbType) {
69
72
  try {
70
73
  const objects = await import(`@iobroker/db-objects-${dbType}`);
@@ -74,6 +77,7 @@ async function objectsDbHasServer(dbType) {
74
77
  throw new Error(`Installation error or unknown objects database type: ${dbType}`);
75
78
  }
76
79
  }
80
+ __name(objectsDbHasServer, "objectsDbHasServer");
77
81
  async function performObjectsInterview(options) {
78
82
  const { dbType, config } = options;
79
83
  const objects = await import(`@iobroker/db-objects-${dbType}`);
@@ -82,6 +86,7 @@ async function performObjectsInterview(options) {
82
86
  }
83
87
  return objects.interview(config);
84
88
  }
89
+ __name(performObjectsInterview, "performObjectsInterview");
85
90
  // Annotate the CommonJS export names for ESM import in node:
86
91
  0 && (module.exports = {
87
92
  getObjectsConstructor,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/common/objects.ts"],
4
- "sourcesContent": ["import fs from 'fs-extra';\nimport { tools } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsClient, interview } from '@iobroker/db-objects-redis';\n\nexport async function getObjectsConstructor(): Promise<typeof ObjectsClient> {\n const config = fs.readJSONSync(tools.getConfigFileName());\n if (!config.objects) {\n config.objects = { type: 'jsonl' };\n }\n\n try {\n const Client = (await import(`@iobroker/db-objects-${config.objects.type}`)).Client;\n return Client;\n } catch (e) {\n console.error(e.stack);\n console.error(`Installation broken or unknown objects type: ${config.objects.type} configured`);\n process.exit(101);\n }\n}\n\n/**\n * Allows to find out if a given objects dbType offers a server which runs on this host and listens (locally or globally/by IP)\n *\n * @param dbType database type\n * @param host configured db host - multihost (array) will always return false\n * @param checkIfLocalOnly if true the method checks if the server listens to local connections only; else also external connection options are checked\n * @returns true if a server listens on this host (locally or globally/by IP)\n */\nexport async function isLocalObjectsDbServer(\n dbType: string,\n host: string | string[],\n checkIfLocalOnly: boolean = false,\n): Promise<boolean> {\n const hasServer = await objectsDbHasServer(dbType);\n if (!hasServer) {\n return false; // if no server it can not be a local server\n }\n\n if (Array.isArray(host)) {\n return false;\n }\n\n let result = host === 'localhost' || tools.isLocalAddress(host); // reachable locally only\n if (!checkIfLocalOnly) {\n const ownIps = tools.findIPs();\n result = result || tools.isListenAllAddress(host) || ownIps.includes(host);\n }\n\n return result;\n}\n\n/**\n * Allows to find out if a given objects dbType offers a server or not\n *\n * @param dbType database type\n * @returns true if a server class is available\n */\nexport async function objectsDbHasServer(dbType: string): Promise<boolean> {\n try {\n const objects = await import(`@iobroker/db-objects-${dbType}`);\n return !!objects.Server;\n } catch (e) {\n console.error(e);\n throw new Error(`Installation error or unknown objects database type: ${dbType}`);\n }\n}\n\ninterface PerformObjectsInterviewOptions {\n /** The partial states db options */\n config: ioBroker.ObjectsDatabaseOptions;\n /** Db type, like redis */\n dbType: string;\n}\n\n/**\n * Perform the objects interview if one has been provided\n *\n * @param options dbtype and the partial config\n * @returns the database options obtained by the answered questionnaire\n */\nexport async function performObjectsInterview(\n options: PerformObjectsInterviewOptions,\n): Promise<ioBroker.ObjectsDatabaseOptions> {\n const { dbType, config } = options;\n\n const objects = await import(`@iobroker/db-objects-${dbType}`);\n if (!objects.interview) {\n return config;\n }\n\n return objects.interview(config satisfies Parameters<typeof interview>[0]);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,sBAAe;AACf,kCAAsB;AAGtB,eAAsB,wBAAqB;AACvC,QAAM,SAAS,gBAAAA,QAAG,aAAa,kCAAM,kBAAiB,CAAE;AACxD,MAAI,CAAC,OAAO,SAAS;AACjB,WAAO,UAAU,EAAE,MAAM,QAAO;EACpC;AAEA,MAAI;AACA,UAAM,UAAU,MAAM,OAAO,wBAAwB,OAAO,QAAQ,IAAI,KAAK;AAC7E,WAAO;EACX,SAAS,GAAG;AACR,YAAQ,MAAM,EAAE,KAAK;AACrB,YAAQ,MAAM,gDAAgD,OAAO,QAAQ,IAAI,aAAa;AAC9F,YAAQ,KAAK,GAAG;EACpB;AACJ;AAUA,eAAsB,uBAClB,QACA,MACA,mBAA4B,OAAK;AAEjC,QAAM,YAAY,MAAM,mBAAmB,MAAM;AACjD,MAAI,CAAC,WAAW;AACZ,WAAO;EACX;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACrB,WAAO;EACX;AAEA,MAAI,SAAS,SAAS,eAAe,kCAAM,eAAe,IAAI;AAC9D,MAAI,CAAC,kBAAkB;AACnB,UAAM,SAAS,kCAAM,QAAO;AAC5B,aAAS,UAAU,kCAAM,mBAAmB,IAAI,KAAK,OAAO,SAAS,IAAI;EAC7E;AAEA,SAAO;AACX;AAQA,eAAsB,mBAAmB,QAAc;AACnD,MAAI;AACA,UAAM,UAAU,MAAM,OAAO,wBAAwB,MAAM;AAC3D,WAAO,CAAC,CAAC,QAAQ;EACrB,SAAS,GAAG;AACR,YAAQ,MAAM,CAAC;AACf,UAAM,IAAI,MAAM,wDAAwD,MAAM,EAAE;EACpF;AACJ;AAeA,eAAsB,wBAClB,SAAuC;AAEvC,QAAM,EAAE,QAAQ,OAAM,IAAK;AAE3B,QAAM,UAAU,MAAM,OAAO,wBAAwB,MAAM;AAC3D,MAAI,CAAC,QAAQ,WAAW;AACpB,WAAO;EACX;AAEA,SAAO,QAAQ,UAAU,MAAgD;AAC7E;",
4
+ "sourcesContent": ["import fs from 'fs-extra';\nimport { tools } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsClient, interview } from '@iobroker/db-objects-redis';\n\n/**\n * Get the objects database client constructor matching the configured objects DB type\n */\nexport async function getObjectsConstructor(): Promise<typeof ObjectsClient> {\n const config = fs.readJSONSync(tools.getConfigFileName());\n if (!config.objects) {\n config.objects = { type: 'jsonl' };\n }\n\n try {\n const Client = (await import(`@iobroker/db-objects-${config.objects.type}`)).Client;\n return Client;\n } catch (e) {\n console.error(e.stack);\n console.error(`Installation broken or unknown objects type: ${config.objects.type} configured`);\n process.exit(101);\n }\n}\n\n/**\n * Allows to find out if a given objects dbType offers a server which runs on this host and listens (locally or globally/by IP)\n *\n * @param dbType database type\n * @param host configured db host - multihost (array) will always return false\n * @param checkIfLocalOnly if true the method checks if the server listens to local connections only; else also external connection options are checked\n * @returns true if a server listens on this host (locally or globally/by IP)\n */\nexport async function isLocalObjectsDbServer(\n dbType: string,\n host: string | string[],\n checkIfLocalOnly: boolean = false,\n): Promise<boolean> {\n const hasServer = await objectsDbHasServer(dbType);\n if (!hasServer) {\n return false; // if no server it can not be a local server\n }\n\n if (Array.isArray(host)) {\n return false;\n }\n\n let result = host === 'localhost' || tools.isLocalAddress(host); // reachable locally only\n if (!checkIfLocalOnly) {\n const ownIps = tools.findIPs();\n result = result || tools.isListenAllAddress(host) || ownIps.includes(host);\n }\n\n return result;\n}\n\n/**\n * Allows to find out if a given objects dbType offers a server or not\n *\n * @param dbType database type\n * @returns true if a server class is available\n */\nexport async function objectsDbHasServer(dbType: string): Promise<boolean> {\n try {\n const objects = await import(`@iobroker/db-objects-${dbType}`);\n return !!objects.Server;\n } catch (e) {\n console.error(e);\n throw new Error(`Installation error or unknown objects database type: ${dbType}`);\n }\n}\n\ninterface PerformObjectsInterviewOptions {\n /** The partial states db options */\n config: ioBroker.ObjectsDatabaseOptions;\n /** Db type, like redis */\n dbType: string;\n}\n\n/**\n * Perform the objects interview if one has been provided\n *\n * @param options dbtype and the partial config\n * @returns the database options obtained by the answered questionnaire\n */\nexport async function performObjectsInterview(\n options: PerformObjectsInterviewOptions,\n): Promise<ioBroker.ObjectsDatabaseOptions> {\n const { dbType, config } = options;\n\n const objects = await import(`@iobroker/db-objects-${dbType}`);\n if (!objects.interview) {\n return config;\n }\n\n return objects.interview(config satisfies Parameters<typeof interview>[0]);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,sBAAe;AACf,kCAAsB;AAMtB,eAAsB,wBAAqB;AACvC,QAAM,SAAS,gBAAAA,QAAG,aAAa,kCAAM,kBAAiB,CAAE;AACxD,MAAI,CAAC,OAAO,SAAS;AACjB,WAAO,UAAU,EAAE,MAAM,QAAO;EACpC;AAEA,MAAI;AACA,UAAM,UAAU,MAAM,OAAO,wBAAwB,OAAO,QAAQ,IAAI,KAAK;AAC7E,WAAO;EACX,SAAS,GAAG;AACR,YAAQ,MAAM,EAAE,KAAK;AACrB,YAAQ,MAAM,gDAAgD,OAAO,QAAQ,IAAI,aAAa;AAC9F,YAAQ,KAAK,GAAG;EACpB;AACJ;AAdsB;AAwBtB,eAAsB,uBAClB,QACA,MACA,mBAA4B,OAAK;AAEjC,QAAM,YAAY,MAAM,mBAAmB,MAAM;AACjD,MAAI,CAAC,WAAW;AACZ,WAAO;EACX;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACrB,WAAO;EACX;AAEA,MAAI,SAAS,SAAS,eAAe,kCAAM,eAAe,IAAI;AAC9D,MAAI,CAAC,kBAAkB;AACnB,UAAM,SAAS,kCAAM,QAAO;AAC5B,aAAS,UAAU,kCAAM,mBAAmB,IAAI,KAAK,OAAO,SAAS,IAAI;EAC7E;AAEA,SAAO;AACX;AArBsB;AA6BtB,eAAsB,mBAAmB,QAAc;AACnD,MAAI;AACA,UAAM,UAAU,MAAM,OAAO,wBAAwB,MAAM;AAC3D,WAAO,CAAC,CAAC,QAAQ;EACrB,SAAS,GAAG;AACR,YAAQ,MAAM,CAAC;AACf,UAAM,IAAI,MAAM,wDAAwD,MAAM,EAAE;EACpF;AACJ;AARsB;AAuBtB,eAAsB,wBAClB,SAAuC;AAEvC,QAAM,EAAE,QAAQ,OAAM,IAAK;AAE3B,QAAM,UAAU,MAAM,OAAO,wBAAwB,MAAM;AAC3D,MAAI,CAAC,QAAQ,WAAW;AACpB,WAAO;EACX;AAEA,SAAO,QAAQ,UAAU,MAAgD;AAC7E;AAXsB;",
6
6
  "names": ["fs"]
7
7
  }
@@ -1,4 +1,7 @@
1
1
  import type { Client as StatesClient } from '@iobroker/db-states-redis';
2
+ /**
3
+ * Get the states database client constructor matching the configured states DB type
4
+ */
2
5
  export declare function getStatesConstructor(): Promise<typeof StatesClient>;
3
6
  /**
4
7
  * Allows to find out if a given states dbType offers a server or not
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
9
  var __export = (target, all) => {
9
10
  for (var name in all)
10
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -50,6 +51,7 @@ async function getStatesConstructor() {
50
51
  process.exit(101);
51
52
  }
52
53
  }
54
+ __name(getStatesConstructor, "getStatesConstructor");
53
55
  async function statesDbHasServer(dbType) {
54
56
  try {
55
57
  const states = await import(`@iobroker/db-states-${dbType}`);
@@ -58,6 +60,7 @@ async function statesDbHasServer(dbType) {
58
60
  throw new Error(`Installation error or unknown states database type: ${dbType}`);
59
61
  }
60
62
  }
63
+ __name(statesDbHasServer, "statesDbHasServer");
61
64
  async function isLocalStatesDbServer(dbType, host, checkIfLocalOnly = false) {
62
65
  const hasServer = await statesDbHasServer(dbType);
63
66
  if (!hasServer) {
@@ -73,6 +76,7 @@ async function isLocalStatesDbServer(dbType, host, checkIfLocalOnly = false) {
73
76
  }
74
77
  return result;
75
78
  }
79
+ __name(isLocalStatesDbServer, "isLocalStatesDbServer");
76
80
  async function performStatesInterview(options) {
77
81
  const { dbType, config } = options;
78
82
  const states = await import(`@iobroker/db-states-${dbType}`);
@@ -81,6 +85,7 @@ async function performStatesInterview(options) {
81
85
  }
82
86
  return states.interview(config);
83
87
  }
88
+ __name(performStatesInterview, "performStatesInterview");
84
89
  // Annotate the CommonJS export names for ESM import in node:
85
90
  0 && (module.exports = {
86
91
  getStatesConstructor,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/common/states.ts"],
4
- "sourcesContent": ["import fs from 'fs-extra';\nimport { tools } from '@iobroker/js-controller-common';\nimport type { Client as StatesClient, interview } from '@iobroker/db-states-redis';\n\nexport async function getStatesConstructor(): Promise<typeof StatesClient> {\n const config = fs.readJSONSync(tools.getConfigFileName());\n if (!config.states) {\n config.states = { type: 'jsonl' };\n }\n\n try {\n const Client = (await import(`@iobroker/db-states-${config.states.type}`)).Client;\n return Client;\n } catch (e) {\n console.error(e.stack);\n console.error(`Installation broken or unknown states type: ${config.states.type} configured.`);\n process.exit(101);\n }\n}\n\n/**\n * Allows to find out if a given states dbType offers a server or not\n *\n * @param dbType database type\n * @returns true if a server class is available\n */\nexport async function statesDbHasServer(dbType: string): Promise<boolean> {\n try {\n const states = await import(`@iobroker/db-states-${dbType}`);\n return !!states.Server;\n } catch {\n throw new Error(`Installation error or unknown states database type: ${dbType}`);\n }\n}\n\n/**\n * Allows to find out if a given states dbType offers a server which runs on this host and listens (locally or globally/by IP)\n *\n * @param dbType database type\n * @param host configured db host - multihost (array) will always return false\n * @param checkIfLocalOnly if true the method checks if the server listens to local connections only; else also external connection options are checked\n * @returns true if a server listens on this host (locally or globally/by IP)\n */\nexport async function isLocalStatesDbServer(\n dbType: string,\n host: string | string[],\n checkIfLocalOnly = false,\n): Promise<boolean> {\n const hasServer = await statesDbHasServer(dbType);\n if (!hasServer) {\n return false; // if no server it can not be a local server\n }\n\n if (Array.isArray(host)) {\n return false;\n }\n\n let result = host === 'localhost' || tools.isLocalAddress(host); // reachable locally only\n if (!checkIfLocalOnly && !Array.isArray(host)) {\n const ownIps = tools.findIPs();\n result = result || tools.isListenAllAddress(host) || ownIps.includes(host);\n }\n\n return result;\n}\n\ninterface PerformStatesInterviewOptions {\n /** The partial states db options */\n config: ioBroker.StatesDatabaseOptions;\n /** Db type, like redis */\n dbType: string;\n}\n\n/**\n * Perform the states interview if one has been provided\n *\n * @param options db type and partial config\n * @returns the database options obtained by the answered questionnaire\n */\nexport async function performStatesInterview(\n options: PerformStatesInterviewOptions,\n): Promise<ioBroker.StatesDatabaseOptions> {\n const { dbType, config } = options;\n\n const states = await import(`@iobroker/db-states-${dbType}`);\n if (!states.interview) {\n return config;\n }\n\n return states.interview(config satisfies Parameters<typeof interview>[0]);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,sBAAe;AACf,kCAAsB;AAGtB,eAAsB,uBAAoB;AACtC,QAAM,SAAS,gBAAAA,QAAG,aAAa,kCAAM,kBAAiB,CAAE;AACxD,MAAI,CAAC,OAAO,QAAQ;AAChB,WAAO,SAAS,EAAE,MAAM,QAAO;EACnC;AAEA,MAAI;AACA,UAAM,UAAU,MAAM,OAAO,uBAAuB,OAAO,OAAO,IAAI,KAAK;AAC3E,WAAO;EACX,SAAS,GAAG;AACR,YAAQ,MAAM,EAAE,KAAK;AACrB,YAAQ,MAAM,+CAA+C,OAAO,OAAO,IAAI,cAAc;AAC7F,YAAQ,KAAK,GAAG;EACpB;AACJ;AAQA,eAAsB,kBAAkB,QAAc;AAClD,MAAI;AACA,UAAM,SAAS,MAAM,OAAO,uBAAuB,MAAM;AACzD,WAAO,CAAC,CAAC,OAAO;EACpB,QAAQ;AACJ,UAAM,IAAI,MAAM,uDAAuD,MAAM,EAAE;EACnF;AACJ;AAUA,eAAsB,sBAClB,QACA,MACA,mBAAmB,OAAK;AAExB,QAAM,YAAY,MAAM,kBAAkB,MAAM;AAChD,MAAI,CAAC,WAAW;AACZ,WAAO;EACX;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACrB,WAAO;EACX;AAEA,MAAI,SAAS,SAAS,eAAe,kCAAM,eAAe,IAAI;AAC9D,MAAI,CAAC,oBAAoB,CAAC,MAAM,QAAQ,IAAI,GAAG;AAC3C,UAAM,SAAS,kCAAM,QAAO;AAC5B,aAAS,UAAU,kCAAM,mBAAmB,IAAI,KAAK,OAAO,SAAS,IAAI;EAC7E;AAEA,SAAO;AACX;AAeA,eAAsB,uBAClB,SAAsC;AAEtC,QAAM,EAAE,QAAQ,OAAM,IAAK;AAE3B,QAAM,SAAS,MAAM,OAAO,uBAAuB,MAAM;AACzD,MAAI,CAAC,OAAO,WAAW;AACnB,WAAO;EACX;AAEA,SAAO,OAAO,UAAU,MAAgD;AAC5E;",
4
+ "sourcesContent": ["import fs from 'fs-extra';\nimport { tools } from '@iobroker/js-controller-common';\nimport type { Client as StatesClient, interview } from '@iobroker/db-states-redis';\n\n/**\n * Get the states database client constructor matching the configured states DB type\n */\nexport async function getStatesConstructor(): Promise<typeof StatesClient> {\n const config = fs.readJSONSync(tools.getConfigFileName());\n if (!config.states) {\n config.states = { type: 'jsonl' };\n }\n\n try {\n const Client = (await import(`@iobroker/db-states-${config.states.type}`)).Client;\n return Client;\n } catch (e) {\n console.error(e.stack);\n console.error(`Installation broken or unknown states type: ${config.states.type} configured.`);\n process.exit(101);\n }\n}\n\n/**\n * Allows to find out if a given states dbType offers a server or not\n *\n * @param dbType database type\n * @returns true if a server class is available\n */\nexport async function statesDbHasServer(dbType: string): Promise<boolean> {\n try {\n const states = await import(`@iobroker/db-states-${dbType}`);\n return !!states.Server;\n } catch {\n throw new Error(`Installation error or unknown states database type: ${dbType}`);\n }\n}\n\n/**\n * Allows to find out if a given states dbType offers a server which runs on this host and listens (locally or globally/by IP)\n *\n * @param dbType database type\n * @param host configured db host - multihost (array) will always return false\n * @param checkIfLocalOnly if true the method checks if the server listens to local connections only; else also external connection options are checked\n * @returns true if a server listens on this host (locally or globally/by IP)\n */\nexport async function isLocalStatesDbServer(\n dbType: string,\n host: string | string[],\n checkIfLocalOnly = false,\n): Promise<boolean> {\n const hasServer = await statesDbHasServer(dbType);\n if (!hasServer) {\n return false; // if no server it can not be a local server\n }\n\n if (Array.isArray(host)) {\n return false;\n }\n\n let result = host === 'localhost' || tools.isLocalAddress(host); // reachable locally only\n if (!checkIfLocalOnly && !Array.isArray(host)) {\n const ownIps = tools.findIPs();\n result = result || tools.isListenAllAddress(host) || ownIps.includes(host);\n }\n\n return result;\n}\n\ninterface PerformStatesInterviewOptions {\n /** The partial states db options */\n config: ioBroker.StatesDatabaseOptions;\n /** Db type, like redis */\n dbType: string;\n}\n\n/**\n * Perform the states interview if one has been provided\n *\n * @param options db type and partial config\n * @returns the database options obtained by the answered questionnaire\n */\nexport async function performStatesInterview(\n options: PerformStatesInterviewOptions,\n): Promise<ioBroker.StatesDatabaseOptions> {\n const { dbType, config } = options;\n\n const states = await import(`@iobroker/db-states-${dbType}`);\n if (!states.interview) {\n return config;\n }\n\n return states.interview(config satisfies Parameters<typeof interview>[0]);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,sBAAe;AACf,kCAAsB;AAMtB,eAAsB,uBAAoB;AACtC,QAAM,SAAS,gBAAAA,QAAG,aAAa,kCAAM,kBAAiB,CAAE;AACxD,MAAI,CAAC,OAAO,QAAQ;AAChB,WAAO,SAAS,EAAE,MAAM,QAAO;EACnC;AAEA,MAAI;AACA,UAAM,UAAU,MAAM,OAAO,uBAAuB,OAAO,OAAO,IAAI,KAAK;AAC3E,WAAO;EACX,SAAS,GAAG;AACR,YAAQ,MAAM,EAAE,KAAK;AACrB,YAAQ,MAAM,+CAA+C,OAAO,OAAO,IAAI,cAAc;AAC7F,YAAQ,KAAK,GAAG;EACpB;AACJ;AAdsB;AAsBtB,eAAsB,kBAAkB,QAAc;AAClD,MAAI;AACA,UAAM,SAAS,MAAM,OAAO,uBAAuB,MAAM;AACzD,WAAO,CAAC,CAAC,OAAO;EACpB,QAAQ;AACJ,UAAM,IAAI,MAAM,uDAAuD,MAAM,EAAE;EACnF;AACJ;AAPsB;AAiBtB,eAAsB,sBAClB,QACA,MACA,mBAAmB,OAAK;AAExB,QAAM,YAAY,MAAM,kBAAkB,MAAM;AAChD,MAAI,CAAC,WAAW;AACZ,WAAO;EACX;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACrB,WAAO;EACX;AAEA,MAAI,SAAS,SAAS,eAAe,kCAAM,eAAe,IAAI;AAC9D,MAAI,CAAC,oBAAoB,CAAC,MAAM,QAAQ,IAAI,GAAG;AAC3C,UAAM,SAAS,kCAAM,QAAO;AAC5B,aAAS,UAAU,kCAAM,mBAAmB,IAAI,KAAK,OAAO,SAAS,IAAI;EAC7E;AAEA,SAAO;AACX;AArBsB;AAoCtB,eAAsB,uBAClB,SAAsC;AAEtC,QAAM,EAAE,QAAQ,OAAM,IAAK;AAE3B,QAAM,SAAS,MAAM,OAAO,uBAAuB,MAAM;AACzD,MAAI,CAAC,OAAO,WAAW;AACnB,WAAO;EACX;AAEA,SAAO,OAAO,UAAU,MAAgD;AAC5E;AAXsB;",
6
6
  "names": ["fs"]
7
7
  }
@@ -1,10 +1,15 @@
1
1
  import type { Client as ObjectsClient } from '@iobroker/db-objects-redis';
2
2
  import type { InternalLogger } from '@iobroker/js-controller-common-db/tools';
3
3
  import { type SupportedFeature } from './constants.js';
4
+ /** Instances grouped by their startup priority tier */
4
5
  export interface OrderedInstancesObject {
6
+ /** Instances in tier 1, started first */
5
7
  1: ioBroker.InstanceObject[];
8
+ /** Instances in tier 2, started after tier 1 */
6
9
  2: ioBroker.InstanceObject[];
10
+ /** Instances in tier 3, started last */
7
11
  3: ioBroker.InstanceObject[];
12
+ /** Admin instances, handled separately from the regular tiers */
8
13
  admin: ioBroker.InstanceObject[];
9
14
  }
10
15
  /**
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
7
  var __export = (target, all) => {
7
8
  for (var name in all)
8
9
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -61,6 +62,7 @@ async function getInstancesOrderedByStartPrio(objects, logger, logPrefix = "") {
61
62
  }
62
63
  return [...instances.admin, ...instances["1"], ...instances["2"], ...instances["3"]];
63
64
  }
65
+ __name(getInstancesOrderedByStartPrio, "getInstancesOrderedByStartPrio");
64
66
  function isInstalledFromNpm(options) {
65
67
  const { adapterName, installedFrom } = options;
66
68
  if (installedFrom === void 0) {
@@ -68,6 +70,7 @@ function isInstalledFromNpm(options) {
68
70
  }
69
71
  return installedFrom.startsWith(`${import_tools.appName.toLowerCase()}.${adapterName}`);
70
72
  }
73
+ __name(isInstalledFromNpm, "isInstalledFromNpm");
71
74
  function getSupportedFeatures() {
72
75
  const features = [...import_constants.SUPPORTED_FEATURES];
73
76
  if (!(0, import_tools.isControllerUiUpgradeSupported)()) {
@@ -78,6 +81,7 @@ function getSupportedFeatures() {
78
81
  }
79
82
  return features;
80
83
  }
84
+ __name(getSupportedFeatures, "getSupportedFeatures");
81
85
  // Annotate the CommonJS export names for ESM import in node:
82
86
  0 && (module.exports = {
83
87
  getInstancesOrderedByStartPrio,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/common/tools.ts"],
4
- "sourcesContent": ["import type { Client as ObjectsClient } from '@iobroker/db-objects-redis';\nimport { appName, isControllerUiUpgradeSupported } from '@iobroker/js-controller-common-db/tools';\nimport type { InternalLogger } from '@iobroker/js-controller-common-db/tools';\nimport { SUPPORTED_FEATURES, type SupportedFeature } from './constants.js';\n\nexport interface OrderedInstancesObject {\n 1: ioBroker.InstanceObject[];\n 2: ioBroker.InstanceObject[];\n 3: ioBroker.InstanceObject[];\n admin: ioBroker.InstanceObject[];\n}\n\n/**\n * Get ordered instances according to tier level\n *\n * @param objects - Objects DB\n * @param logger - logger object\n * @param logPrefix prefix for logging\n */\nexport async function getInstancesOrderedByStartPrio(\n objects: ObjectsClient,\n logger: InternalLogger | typeof console,\n logPrefix = '',\n): Promise<ioBroker.InstanceObject[]> {\n const instances: OrderedInstancesObject = { 1: [], 2: [], 3: [], admin: [] };\n const allowedTiers = [1, 2, 3];\n\n if (logPrefix) {\n // append space if we have a prefix\n logPrefix += ' ';\n }\n\n let doc: Awaited<ioBroker.GetObjectViewPromise<ioBroker.InstanceObject>> = { rows: [] };\n try {\n doc = await objects.getObjectViewAsync('system', 'instance', {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999',\n });\n } catch (e) {\n if (e.message?.startsWith('Cannot find ')) {\n logger.error(`${logPrefix} _design/system missing - call node ${appName}.js setup`);\n } else {\n logger.error(`${logPrefix} Can not get instances: ${e.message}`);\n }\n }\n\n if (!doc.rows || doc.rows.length === 0) {\n logger.info(`${logPrefix} no instances found`);\n } else {\n for (const row of doc.rows) {\n if (row?.value) {\n if (row.value._id.startsWith('system.adapter.admin')) {\n instances.admin.push(row.value);\n } else if (\n row.value.common?.tier !== undefined &&\n allowedTiers.includes(Math.round(row.value.common.tier))\n ) {\n instances[row.value.common.tier].push(row.value);\n } else {\n // no valid tier, so put it in the last one\n instances['3'].push(row.value);\n }\n }\n }\n }\n\n return [...instances.admin, ...instances['1'], ...instances['2'], ...instances['3']];\n}\n\ninterface IsInstalledFromNpmOptions {\n /** Installed from attribute of instance/adapter object */\n installedFrom?: ioBroker.InstalledFrom;\n /** Name of the adapter */\n adapterName: string;\n}\n\n/**\n * Check if the adapter has been installed from NPM\n *\n * @param options installedFrom and name information\n */\nexport function isInstalledFromNpm(options: IsInstalledFromNpmOptions): boolean {\n const { adapterName, installedFrom } = options;\n\n if (installedFrom === undefined) {\n return true;\n }\n\n return installedFrom.startsWith(`${appName.toLowerCase()}.${adapterName}`);\n}\n\n/**\n * Get the supported features for the current running controller\n */\nexport function getSupportedFeatures(): SupportedFeature[] {\n const features = [...SUPPORTED_FEATURES];\n\n if (!isControllerUiUpgradeSupported()) {\n const idx = features.indexOf('CONTROLLER_UI_UPGRADE');\n if (idx !== -1) {\n features.splice(idx, 1);\n }\n }\n\n return features;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AACA;;;;;;;AAAA,mBAAwD;AAExD,uBAA0D;AAgB1D,eAAsB,+BAClB,SACA,QACA,YAAY,IAAE;AAEd,QAAM,YAAoC,EAAE,GAAG,CAAA,GAAI,GAAG,CAAA,GAAI,GAAG,CAAA,GAAI,OAAO,CAAA,EAAE;AAC1E,QAAM,eAAe,CAAC,GAAG,GAAG,CAAC;AAE7B,MAAI,WAAW;AAEX,iBAAa;EACjB;AAEA,MAAI,MAAuE,EAAE,MAAM,CAAA,EAAE;AACrF,MAAI;AACA,UAAM,MAAM,QAAQ,mBAAmB,UAAU,YAAY;MACzD,UAAU;MACV,QAAQ;KACX;EACL,SAAS,GAAG;AACR,QAAI,EAAE,SAAS,WAAW,cAAc,GAAG;AACvC,aAAO,MAAM,GAAG,SAAS,uCAAuC,oBAAO,WAAW;IACtF,OAAO;AACH,aAAO,MAAM,GAAG,SAAS,2BAA2B,EAAE,OAAO,EAAE;IACnE;EACJ;AAEA,MAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,WAAW,GAAG;AACpC,WAAO,KAAK,GAAG,SAAS,qBAAqB;EACjD,OAAO;AACH,eAAW,OAAO,IAAI,MAAM;AACxB,UAAI,KAAK,OAAO;AACZ,YAAI,IAAI,MAAM,IAAI,WAAW,sBAAsB,GAAG;AAClD,oBAAU,MAAM,KAAK,IAAI,KAAK;QAClC,WACI,IAAI,MAAM,QAAQ,SAAS,UAC3B,aAAa,SAAS,KAAK,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,GACzD;AACE,oBAAU,IAAI,MAAM,OAAO,IAAI,EAAE,KAAK,IAAI,KAAK;QACnD,OAAO;AAEH,oBAAU,GAAG,EAAE,KAAK,IAAI,KAAK;QACjC;MACJ;IACJ;EACJ;AAEA,SAAO,CAAC,GAAG,UAAU,OAAO,GAAG,UAAU,GAAG,GAAG,GAAG,UAAU,GAAG,GAAG,GAAG,UAAU,GAAG,CAAC;AACvF;AAcM,SAAU,mBAAmB,SAAkC;AACjE,QAAM,EAAE,aAAa,cAAa,IAAK;AAEvC,MAAI,kBAAkB,QAAW;AAC7B,WAAO;EACX;AAEA,SAAO,cAAc,WAAW,GAAG,qBAAQ,YAAW,CAAE,IAAI,WAAW,EAAE;AAC7E;AAKM,SAAU,uBAAoB;AAChC,QAAM,WAAW,CAAC,GAAG,mCAAkB;AAEvC,MAAI,KAAC,6CAA8B,GAAI;AACnC,UAAM,MAAM,SAAS,QAAQ,uBAAuB;AACpD,QAAI,QAAQ,IAAI;AACZ,eAAS,OAAO,KAAK,CAAC;IAC1B;EACJ;AAEA,SAAO;AACX;",
4
+ "sourcesContent": ["import type { Client as ObjectsClient } from '@iobroker/db-objects-redis';\nimport { appName, isControllerUiUpgradeSupported } from '@iobroker/js-controller-common-db/tools';\nimport type { InternalLogger } from '@iobroker/js-controller-common-db/tools';\nimport { SUPPORTED_FEATURES, type SupportedFeature } from './constants.js';\n\n/** Instances grouped by their startup priority tier */\nexport interface OrderedInstancesObject {\n /** Instances in tier 1, started first */\n 1: ioBroker.InstanceObject[];\n /** Instances in tier 2, started after tier 1 */\n 2: ioBroker.InstanceObject[];\n /** Instances in tier 3, started last */\n 3: ioBroker.InstanceObject[];\n /** Admin instances, handled separately from the regular tiers */\n admin: ioBroker.InstanceObject[];\n}\n\n/**\n * Get ordered instances according to tier level\n *\n * @param objects - Objects DB\n * @param logger - logger object\n * @param logPrefix prefix for logging\n */\nexport async function getInstancesOrderedByStartPrio(\n objects: ObjectsClient,\n logger: InternalLogger | typeof console,\n logPrefix = '',\n): Promise<ioBroker.InstanceObject[]> {\n const instances: OrderedInstancesObject = { 1: [], 2: [], 3: [], admin: [] };\n const allowedTiers = [1, 2, 3];\n\n if (logPrefix) {\n // append space if we have a prefix\n logPrefix += ' ';\n }\n\n let doc: Awaited<ioBroker.GetObjectViewPromise<ioBroker.InstanceObject>> = { rows: [] };\n try {\n doc = await objects.getObjectViewAsync('system', 'instance', {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999',\n });\n } catch (e) {\n if (e.message?.startsWith('Cannot find ')) {\n logger.error(`${logPrefix} _design/system missing - call node ${appName}.js setup`);\n } else {\n logger.error(`${logPrefix} Can not get instances: ${e.message}`);\n }\n }\n\n if (!doc.rows || doc.rows.length === 0) {\n logger.info(`${logPrefix} no instances found`);\n } else {\n for (const row of doc.rows) {\n if (row?.value) {\n if (row.value._id.startsWith('system.adapter.admin')) {\n instances.admin.push(row.value);\n } else if (\n row.value.common?.tier !== undefined &&\n allowedTiers.includes(Math.round(row.value.common.tier))\n ) {\n instances[row.value.common.tier].push(row.value);\n } else {\n // no valid tier, so put it in the last one\n instances['3'].push(row.value);\n }\n }\n }\n }\n\n return [...instances.admin, ...instances['1'], ...instances['2'], ...instances['3']];\n}\n\ninterface IsInstalledFromNpmOptions {\n /** Installed from attribute of instance/adapter object */\n installedFrom?: ioBroker.InstalledFrom;\n /** Name of the adapter */\n adapterName: string;\n}\n\n/**\n * Check if the adapter has been installed from NPM\n *\n * @param options installedFrom and name information\n */\nexport function isInstalledFromNpm(options: IsInstalledFromNpmOptions): boolean {\n const { adapterName, installedFrom } = options;\n\n if (installedFrom === undefined) {\n return true;\n }\n\n return installedFrom.startsWith(`${appName.toLowerCase()}.${adapterName}`);\n}\n\n/**\n * Get the supported features for the current running controller\n */\nexport function getSupportedFeatures(): SupportedFeature[] {\n const features = [...SUPPORTED_FEATURES];\n\n if (!isControllerUiUpgradeSupported()) {\n const idx = features.indexOf('CONTROLLER_UI_UPGRADE');\n if (idx !== -1) {\n features.splice(idx, 1);\n }\n }\n\n return features;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AACA;;;;;;;AAAA,mBAAwD;AAExD,uBAA0D;AAqB1D,eAAsB,+BAClB,SACA,QACA,YAAY,IAAE;AAEd,QAAM,YAAoC,EAAE,GAAG,CAAA,GAAI,GAAG,CAAA,GAAI,GAAG,CAAA,GAAI,OAAO,CAAA,EAAE;AAC1E,QAAM,eAAe,CAAC,GAAG,GAAG,CAAC;AAE7B,MAAI,WAAW;AAEX,iBAAa;EACjB;AAEA,MAAI,MAAuE,EAAE,MAAM,CAAA,EAAE;AACrF,MAAI;AACA,UAAM,MAAM,QAAQ,mBAAmB,UAAU,YAAY;MACzD,UAAU;MACV,QAAQ;KACX;EACL,SAAS,GAAG;AACR,QAAI,EAAE,SAAS,WAAW,cAAc,GAAG;AACvC,aAAO,MAAM,GAAG,SAAS,uCAAuC,oBAAO,WAAW;IACtF,OAAO;AACH,aAAO,MAAM,GAAG,SAAS,2BAA2B,EAAE,OAAO,EAAE;IACnE;EACJ;AAEA,MAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,WAAW,GAAG;AACpC,WAAO,KAAK,GAAG,SAAS,qBAAqB;EACjD,OAAO;AACH,eAAW,OAAO,IAAI,MAAM;AACxB,UAAI,KAAK,OAAO;AACZ,YAAI,IAAI,MAAM,IAAI,WAAW,sBAAsB,GAAG;AAClD,oBAAU,MAAM,KAAK,IAAI,KAAK;QAClC,WACI,IAAI,MAAM,QAAQ,SAAS,UAC3B,aAAa,SAAS,KAAK,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,GACzD;AACE,oBAAU,IAAI,MAAM,OAAO,IAAI,EAAE,KAAK,IAAI,KAAK;QACnD,OAAO;AAEH,oBAAU,GAAG,EAAE,KAAK,IAAI,KAAK;QACjC;MACJ;IACJ;EACJ;AAEA,SAAO,CAAC,GAAG,UAAU,OAAO,GAAG,UAAU,GAAG,GAAG,GAAG,UAAU,GAAG,GAAG,GAAG,UAAU,GAAG,CAAC;AACvF;AAhDsB;AA8DhB,SAAU,mBAAmB,SAAkC;AACjE,QAAM,EAAE,aAAa,cAAa,IAAK;AAEvC,MAAI,kBAAkB,QAAW;AAC7B,WAAO;EACX;AAEA,SAAO,cAAc,WAAW,GAAG,qBAAQ,YAAW,CAAE,IAAI,WAAW,EAAE;AAC7E;AARgB;AAaV,SAAU,uBAAoB;AAChC,QAAM,WAAW,CAAC,GAAG,mCAAkB;AAEvC,MAAI,KAAC,6CAA8B,GAAI;AACnC,UAAM,MAAM,SAAS,QAAQ,uBAAuB;AACpD,QAAI,QAAQ,IAAI;AACZ,eAAS,OAAO,KAAK,CAAC;IAC1B;EACJ;AAEA,SAAO;AACX;AAXgB;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,42 @@
1
1
  import type { Client as ObjectsClient } from '@iobroker/db-objects-redis';
2
+ /**
3
+ * Pack all files of a directory into a zip archive
4
+ *
5
+ * @param objects The objects database client
6
+ * @param id The object ID owning the files
7
+ * @param name Path of the directory to read inside the object's file storage
8
+ * @param options Optional settings passed to the objects client, or the callback
9
+ * @param callback Called with the base64 encoded zip archive
10
+ */
2
11
  export declare function readDirAsZip(objects: ObjectsClient, id: string, name: string, options: any, callback: (err?: Error | null, base64?: string) => void): Promise<void>;
12
+ /**
13
+ * Unpack a zip archive and write all contained files into the object's file storage
14
+ *
15
+ * @param objects The objects database client
16
+ * @param id The object ID that should own the files
17
+ * @param name Target directory path inside the object's file storage
18
+ * @param data The zip archive as a buffer
19
+ * @param options Optional settings passed to the objects client
20
+ */
3
21
  export declare function writeDirAsZip(objects: ObjectsClient, id: string, name: string, data: Buffer, options: any): Promise<void>;
22
+ /**
23
+ * Read all objects below the given root ID and pack them into a zip archive
24
+ *
25
+ * @param objects The objects database client
26
+ * @param rootId The root object ID whose child objects should be exported
27
+ * @param adapter The adapter the objects belong to
28
+ * @param options Optional settings passed to the objects client
29
+ */
4
30
  export declare function readObjectsAsZip(objects: ObjectsClient, rootId: string, adapter: string, options?: any): Promise<string>;
31
+ /**
32
+ * Unpack a zip archive of objects and store them below the given root ID
33
+ *
34
+ * @param objects The objects database client
35
+ * @param rootId The root object ID the imported objects should be stored under
36
+ * @param adapter The adapter the objects belong to
37
+ * @param data The zip archive as a buffer
38
+ * @param options Optional settings passed to the objects client
39
+ * @param callback Called when the import has finished or failed
40
+ */
5
41
  export declare function writeObjectsAsZip(objects: ObjectsClient, rootId: string, adapter: string, data: Buffer, options: any, callback: (err?: Error | null) => void): Promise<void>;
6
42
  //# sourceMappingURL=zipFiles.d.ts.map