@iobroker/js-controller-cli 7.0.8-alpha.7-20250928-40cb80c18 → 7.1.0

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 (43) hide show
  1. package/build/cjs/lib/cli/cliLogs.js.map +1 -1
  2. package/build/cjs/lib/setup/dbConnection.js +4 -4
  3. package/build/cjs/lib/setup/dbConnection.js.map +2 -2
  4. package/build/cjs/lib/setup/multihostClient.d.ts +58 -22
  5. package/build/cjs/lib/setup/multihostClient.js +31 -24
  6. package/build/cjs/lib/setup/multihostClient.js.map +3 -3
  7. package/build/cjs/lib/setup/setupMultihost.d.ts +16 -4
  8. package/build/cjs/lib/setup/setupMultihost.js +32 -16
  9. package/build/cjs/lib/setup/setupMultihost.js.map +3 -3
  10. package/build/cjs/lib/setup/setupSetup.d.ts +3 -11
  11. package/build/cjs/lib/setup/setupSetup.js +65 -76
  12. package/build/cjs/lib/setup/setupSetup.js.map +2 -2
  13. package/build/cjs/lib/setup/setupVendor.d.ts +3 -1
  14. package/build/cjs/lib/setup/setupVendor.js +72 -35
  15. package/build/cjs/lib/setup/setupVendor.js.map +2 -2
  16. package/build/cjs/lib/setup.js +5 -2
  17. package/build/cjs/lib/setup.js.map +2 -2
  18. package/build/esm/lib/cli/cliLogs.js +1 -1
  19. package/build/esm/lib/cli/cliLogs.js.map +1 -1
  20. package/build/esm/lib/setup/dbConnection.d.ts.map +1 -1
  21. package/build/esm/lib/setup/dbConnection.js +14 -14
  22. package/build/esm/lib/setup/dbConnection.js.map +1 -1
  23. package/build/esm/lib/setup/multihostClient.d.ts +58 -22
  24. package/build/esm/lib/setup/multihostClient.d.ts.map +1 -1
  25. package/build/esm/lib/setup/multihostClient.js +47 -23
  26. package/build/esm/lib/setup/multihostClient.js.map +1 -1
  27. package/build/esm/lib/setup/setupMultihost.d.ts +16 -4
  28. package/build/esm/lib/setup/setupMultihost.d.ts.map +1 -1
  29. package/build/esm/lib/setup/setupMultihost.js +41 -18
  30. package/build/esm/lib/setup/setupMultihost.js.map +1 -1
  31. package/build/esm/lib/setup/setupSetup.d.ts +3 -11
  32. package/build/esm/lib/setup/setupSetup.d.ts.map +1 -1
  33. package/build/esm/lib/setup/setupSetup.js +66 -80
  34. package/build/esm/lib/setup/setupSetup.js.map +1 -1
  35. package/build/esm/lib/setup/setupVendor.d.ts +3 -1
  36. package/build/esm/lib/setup/setupVendor.d.ts.map +1 -1
  37. package/build/esm/lib/setup/setupVendor.js +72 -35
  38. package/build/esm/lib/setup/setupVendor.js.map +1 -1
  39. package/build/esm/lib/setup.d.ts.map +1 -1
  40. package/build/esm/lib/setup.js +6 -3
  41. package/build/esm/lib/setup.js.map +1 -1
  42. package/build/tsconfig.build.tsbuildinfo +1 -1
  43. package/package.json +7 -7
@@ -34,15 +34,20 @@ module.exports = __toCommonJS(setupMultihost_exports);
34
34
  var import_fs_extra = __toESM(require("fs-extra"), 1);
35
35
  var import_node_path = __toESM(require("node:path"), 1);
36
36
  var import_node_readline = __toESM(require("node:readline"), 1);
37
+ var import_readline_sync = __toESM(require("readline-sync"), 1);
38
+ var import_prompt = __toESM(require("prompt"), 1);
37
39
  var import_js_controller_common = require("@iobroker/js-controller-common");
38
40
  var import_js_controller_common2 = require("@iobroker/js-controller-common");
39
41
  var import_multihostClient = require("./multihostClient.js");
40
- var import_readline_sync = __toESM(require("readline-sync"), 1);
41
- var import_prompt = __toESM(require("prompt"), 1);
42
42
  class Multihost {
43
43
  configName;
44
44
  params;
45
45
  objects;
46
+ /**
47
+ * Constructor
48
+ *
49
+ * @param options options for the Multihost CLI
50
+ */
46
51
  constructor(options) {
47
52
  this.configName = import_js_controller_common.tools.getConfigFileName();
48
53
  this.params = options.params || {};
@@ -84,8 +89,7 @@ class Multihost {
84
89
  async browse() {
85
90
  const mhClient = new import_multihostClient.MHClient();
86
91
  try {
87
- const res = await mhClient.browse(2e3, !!this.params.debug);
88
- return res;
92
+ return await mhClient.browse(2e3, !!this.params.debug);
89
93
  } catch (e) {
90
94
  throw new Error(`Multihost discovery client: Cannot browse: ${e.message}`);
91
95
  }
@@ -134,8 +138,8 @@ Change "bind 127.0.0.1" to "bind ${import_js_controller_common.tools.getListenAl
134
138
  console.log(`Multihost discovery server: ${config.multihostService.enabled ? "enabled" : "disabled"}`);
135
139
  console.log(`Discovery authentication: ${config.multihostService.secure ? "enabled" : "disabled"}`);
136
140
  console.log(`Persistent activation: ${config.multihostService.enabled && config.multihostService.persist ? "enabled" : "disabled"}`);
137
- console.log(`Objects: ${config.objects.type} on ${config.objects.host}`);
138
- console.log(`States: ${config.states.type} on ${config.states.host}`);
141
+ console.log(`Objects: ${config.objects.type} on ${Array.isArray(config.objects.host) ? config.objects.host.join(", ") : config.objects.host}`);
142
+ console.log(`States: ${config.states.type} on ${Array.isArray(config.states.host) ? config.states.host.join(", ") : config.states.host}`);
139
143
  }
140
144
  /**
141
145
  * Enables or disables the multihost discovery server in the config json
@@ -151,7 +155,7 @@ Change "bind 127.0.0.1" to "bind ${import_js_controller_common.tools.getListenAl
151
155
  changed = true;
152
156
  config.multihostService.enabled = true;
153
157
  config.multihostService.password = "";
154
- console.log("Multihost discovery server activated on this host. If iobroker is currently not running please start befeore trying to discover this host.");
158
+ console.log("Multihost discovery server activated on this host. If iobroker is currently not running please start before trying to discover this host.");
155
159
  console.log("Important: Multihost discovery works with UDP packets. Make sure they are routed correctly in your network. If you use Docker you also need to configure this correctly.");
156
160
  if (!this.params.persist) {
157
161
  console.log("Multihost discovery will be automatically deactivated after 15 minutes. If you want to activate it permanently use the --persist flag");
@@ -191,12 +195,12 @@ Change "bind 127.0.0.1" to "bind ${import_js_controller_common.tools.getListenAl
191
195
  }
192
196
  };
193
197
  import_prompt.default.start();
194
- import_prompt.default.get(schema, (err, password) => {
198
+ import_prompt.default.get(schema, (_err, password) => {
195
199
  if (password?.password) {
196
200
  if (password.password !== password.passwordRepeat) {
197
201
  callback(new Error("Secret phrases are not equal!"));
198
202
  } else {
199
- this.objects.getObject("system.config", (err2, obj) => {
203
+ this.objects.getObject("system.config", (_err2, obj) => {
200
204
  config.multihostService.password = import_js_controller_common.tools.encrypt(obj.native.secret, password.password);
201
205
  this.showMHState(config, changed);
202
206
  callback();
@@ -232,10 +236,10 @@ Change "bind 127.0.0.1" to "bind ${import_js_controller_common.tools.getListenAl
232
236
  /**
233
237
  * Connect to given MH server
234
238
  *
235
- * @param mhClient mhclient used for connection
236
- * @param ip ip address of server
239
+ * @param mhClient MultiHost Client used for connection
240
+ * @param ip IP address of server
237
241
  * @param pass password
238
- * @param callback
242
+ * @param callback callback
239
243
  */
240
244
  connectHelper(mhClient, ip, pass, callback) {
241
245
  mhClient.connect(ip, pass, async (err, oObjects, oStates, ipHost) => {
@@ -249,16 +253,28 @@ Change "bind 127.0.0.1" to "bind ${import_js_controller_common.tools.getListenAl
249
253
  const hasLocalStatesServer = await (0, import_js_controller_common2.isLocalStatesDbServer)(config.states.type, config.states.host, true);
250
254
  if (hasLocalObjectsServer || hasLocalStatesServer) {
251
255
  callback(new Error(`IP Address of the remote host is ${import_js_controller_common.tools.getLocalAddress()}. Connections from this host will not be accepted. Please change the configuration of this host to accept remote connections.`));
252
- } else {
253
- if (import_js_controller_common.tools.isListenAllAddress(config.states.host)) {
256
+ } else if ((!Array.isArray(config.states.host) || config.states.host.length === 1) && (!Array.isArray(config.objects.host) || config.objects.host.length === 1)) {
257
+ const sHost = Array.isArray(config.states.host) ? config.states.host[0] : config.states.host;
258
+ if (import_js_controller_common.tools.isListenAllAddress(sHost)) {
254
259
  config.states.host = ipHost ?? "";
255
260
  }
256
- if (import_js_controller_common.tools.isListenAllAddress(config.objects.host)) {
261
+ const oHost = Array.isArray(config.objects.host) ? config.objects.host[0] : config.objects.host;
262
+ if (import_js_controller_common.tools.isListenAllAddress(oHost)) {
257
263
  config.objects.host = ipHost ?? "";
258
264
  }
259
265
  import_fs_extra.default.writeFileSync(this.configName, JSON.stringify(config, null, 2));
260
266
  console.log('Config ok. Please restart ioBroker: "iobroker restart"');
261
267
  callback();
268
+ } else {
269
+ if (Array.isArray(config.states.host)) {
270
+ config.states.host = config.states.host.map((sHost) => import_js_controller_common.tools.isListenAllAddress(sHost) ? ipHost ?? "" : sHost);
271
+ }
272
+ if (Array.isArray(config.objects.host)) {
273
+ config.objects.host = config.objects.host.map((oHost) => import_js_controller_common.tools.isListenAllAddress(oHost) ? ipHost ?? "" : oHost);
274
+ }
275
+ import_fs_extra.default.writeFileSync(this.configName, JSON.stringify(config, null, 2));
276
+ console.log('Config ok. Please restart ioBroker: "iobroker restart"');
277
+ callback();
262
278
  }
263
279
  } else {
264
280
  callback(new Error("No configuration received!"));
@@ -270,7 +286,7 @@ Change "bind 127.0.0.1" to "bind ${import_js_controller_common.tools.getListenAl
270
286
  *
271
287
  * @param index index of host to connect to
272
288
  * @param pass password
273
- * @param callback
289
+ * @param callback callback
274
290
  */
275
291
  async connect(index, pass, callback) {
276
292
  if (typeof pass === "function") {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/setup/setupMultihost.ts"],
4
- "sourcesContent": ["import fs from 'fs-extra';\nimport path from 'node:path';\nimport readline from 'node:readline';\nimport { tools } from '@iobroker/js-controller-common';\nimport { isLocalObjectsDbServer, isLocalStatesDbServer } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';\nimport { MHClient, type BrowseResultEntry } from './multihostClient.js';\nimport readlineSync from 'readline-sync';\nimport prompt from 'prompt';\n\ninterface MHParams {\n secure?: boolean;\n persist?: boolean;\n debug?: boolean;\n}\n\nexport interface CLIMultihostOptions {\n objects: ObjectsRedisClient;\n params?: MHParams;\n}\n\nexport class Multihost {\n private readonly configName: string;\n private params: MHParams;\n private objects: ObjectsRedisClient;\n\n constructor(options: CLIMultihostOptions) {\n this.configName = tools.getConfigFileName();\n this.params = options.params || {};\n this.objects = options.objects;\n }\n\n /**\n * Retrieve config (iobroker.json content)\n */\n getConfig(): ioBroker.IoBrokerJson {\n let config;\n // read actual configuration\n try {\n if (fs.existsSync(this.configName)) {\n config = fs.readJsonSync(this.configName);\n } else {\n config = fs.readJsonSync(\n path.join(tools.getControllerDir(), 'conf', `${tools.appName.toLowerCase()}-dist.json`),\n );\n }\n } catch {\n config = fs.readJsonSync(\n path.join(tools.getControllerDir(), 'conf', `${tools.appName.toLowerCase()}-dist.json`),\n );\n }\n return config;\n }\n\n /**\n * Show hosts on CLI\n *\n * @param list list of hosts\n */\n showHosts(list: BrowseResultEntry[]): void {\n if (!list || !list.length) {\n console.info(\n 'No Multihost server found. Make sure iobroker is running on the host where you enabled multihost discovery (and it is not this host)!',\n );\n } else {\n for (let i = 0; i < list.length; i++) {\n console.log(\n `${i + 1} | ${list[i].hostname!.padStart(20)} | ${list[i].slave ? 'slave' : ' host'} | ${list[\n i\n ].ip!.padStart(20)} | ${JSON.stringify(list[i].info)}`,\n );\n }\n }\n }\n\n /**\n * Start MH browsing\n */\n async browse(): Promise<BrowseResultEntry[]> {\n const mhClient = new MHClient();\n try {\n const res = await mhClient.browse(2_000, !!this.params.debug);\n return res;\n } catch (e) {\n throw new Error(`Multihost discovery client: Cannot browse: ${e.message}`);\n }\n }\n\n /**\n * Show MH state on CLI\n *\n * @param config iob config\n * @param changed if config has changed\n */\n private async showMHState(config: ioBroker.IoBrokerJson, changed: boolean): Promise<void> {\n if (config.multihostService.enabled) {\n let warningShown = false;\n\n const hasLocalObjectsServer = await isLocalObjectsDbServer(config.objects.type, config.objects.host, true);\n\n if (hasLocalObjectsServer) {\n console.log('Changing objects server to accept connections on all IP addresses.');\n config.objects.host = tools.getListenAllAddress();\n changed = true;\n } else if (config.objects.type === 'redis') {\n warningShown = true;\n console.log(\n `Please check the binding of redis service. By default it is only local: http://download.redis.io/redis-stable/redis.conf\\nChange \"bind 127.0.0.1\" to \"bind ${tools.getListenAllAddress()}\" or to others.`,\n );\n } else {\n warningShown = true;\n console.log(\n `Please check the binding of the configured ${config.objects.type} server to allow remote connections.`,\n );\n }\n\n const hasLocalStatesServer = await isLocalStatesDbServer(config.states.type, config.states.host, true);\n\n if (hasLocalStatesServer) {\n console.log('Changing states server to accept connections on all IP addresses.');\n config.states.host = tools.getListenAllAddress();\n changed = true;\n } else if (config.states.type === 'redis') {\n !warningShown &&\n console.log(\n `Please check the binding of redis service. By default it is only local: http://download.redis.io/redis-stable/redis.conf\\nChange \"bind 127.0.0.1\" to \"bind ${tools.getListenAllAddress()}\" or to others.`,\n );\n } else {\n !warningShown &&\n console.log(\n `Please check the binding of the configured ${config.states.type} server to allow remote connections.`,\n );\n }\n }\n if (!changed) {\n console.log('No configuration change needed.');\n } else {\n fs.writeFileSync(this.configName, JSON.stringify(config, null, 2));\n console.log('Please restart ioBroker for the changes to take effect: \"iobroker restart\"');\n }\n console.log('\\n');\n console.log(`Multihost discovery server: ${config.multihostService.enabled ? 'enabled' : 'disabled'}`);\n console.log(`Discovery authentication: ${config.multihostService.secure ? 'enabled' : 'disabled'}`);\n console.log(\n `Persistent activation: ${\n config.multihostService.enabled && config.multihostService.persist ? 'enabled' : 'disabled'\n }`,\n );\n console.log(`Objects: ${config.objects.type} on ${config.objects.host}`);\n console.log(`States: ${config.states.type} on ${config.states.host}`);\n }\n\n /**\n * Enables or disables the multihost discovery server in the config json\n *\n * @param isEnable - if the server should be activated or deactivated\n * @param callback - callback function to be executed\n */\n enable(isEnable: boolean, callback: (err?: Error) => void): void {\n let changed = false;\n const config = this.getConfig();\n config.multihostService = config.multihostService || { enabled: false, secure: true };\n\n if (isEnable && !config.multihostService.enabled) {\n changed = true;\n config.multihostService.enabled = true;\n config.multihostService.password = '';\n console.log(\n 'Multihost discovery server activated on this host. If iobroker is currently not running please start befeore trying to discover this host.',\n );\n console.log(\n 'Important: Multihost discovery works with UDP packets. Make sure they are routed correctly in your network. If you use Docker you also need to configure this correctly.',\n );\n if (!this.params.persist) {\n console.log(\n 'Multihost discovery will be automatically deactivated after 15 minutes. If you want to activate it permanently use the --persist flag',\n );\n }\n } else if (!isEnable && config.multihostService.enabled) {\n changed = true;\n config.multihostService.enabled = false;\n config.multihostService.password = '';\n console.log('Multihost discovery server deactivated on this host.');\n }\n if (this.params.secure === undefined) {\n this.params.secure = true;\n }\n\n this.params.persist = !!this.params.persist;\n\n if (\n isEnable &&\n (config.multihostService.secure !== this.params.secure ||\n (config.multihostService.secure && !config.multihostService.password) ||\n config.multihostService.persist !== this.params.persist)\n ) {\n changed = true;\n config.multihostService.secure = this.params.secure;\n config.multihostService.persist = this.params.persist;\n console.log(`Discovery authentication ${this.params.secure ? 'activated' : 'deactivated'}.`);\n if (config.multihostService.secure) {\n prompt.message = '';\n prompt.delimiter = '';\n const schema = {\n properties: {\n password: {\n description: 'Enter secret phrase for connection:',\n pattern: /^[^'\"]+$/,\n message: 'No \" are allowed',\n hidden: true,\n },\n passwordRepeat: {\n description: 'Repeat secret phrase for connection:',\n pattern: /^[^'\"]+$/,\n message: 'No \" are allowed',\n hidden: true,\n },\n },\n };\n prompt.start();\n\n prompt.get(schema, (err, password) => {\n if (password?.password) {\n if (password.password !== password.passwordRepeat) {\n callback(new Error('Secret phrases are not equal!'));\n } else {\n this.objects.getObject('system.config', (err, obj) => {\n config.multihostService.password = tools.encrypt(\n obj!.native.secret,\n password.password as string,\n );\n this.showMHState(config, changed);\n callback();\n });\n }\n } else {\n callback(new Error('No secret phrase entered!'));\n }\n });\n } else {\n this.showMHState(config, changed);\n callback();\n }\n } else {\n this.showMHState(config, changed);\n callback();\n }\n }\n\n /**\n * Show the MH status\n */\n status(): void {\n const config = this.getConfig();\n config.multihostService = config.multihostService || { enabled: false, secure: true };\n this.showMHState(config, false);\n }\n\n /**\n * Read password from cli\n */\n readPassword(): string {\n return readlineSync.question('Enter secret phrase for connection: ', { hideEchoBack: true });\n }\n\n /**\n * Connect to given MH server\n *\n * @param mhClient mhclient used for connection\n * @param ip ip address of server\n * @param pass password\n * @param callback\n */\n connectHelper(mhClient: MHClient, ip: string, pass: string, callback: (err?: Error) => void): void {\n mhClient.connect(ip, pass, async (err, oObjects, oStates, ipHost) => {\n if (err) {\n callback(new Error(`Cannot connect to \"${ip}\": ${err.message}`));\n } else if (oObjects && oStates) {\n const config = this.getConfig();\n config.objects = oObjects;\n config.states = oStates;\n\n const hasLocalObjectsServer = await isLocalObjectsDbServer(\n config.objects.type,\n config.objects.host,\n true,\n );\n const hasLocalStatesServer = await isLocalStatesDbServer(config.states.type, config.states.host, true);\n\n if (hasLocalObjectsServer || hasLocalStatesServer) {\n callback(\n new Error(\n `IP Address of the remote host is ${tools.getLocalAddress()}. Connections from this host will not be accepted. Please change the configuration of this host to accept remote connections.`,\n ),\n );\n } else {\n if (tools.isListenAllAddress(config.states.host)) {\n // TODO: why we set the remote IP only when the local config allows full connectivity?\n config.states.host = ipHost ?? '';\n }\n if (tools.isListenAllAddress(config.objects.host)) {\n // TODO: why we set the remote IP only when the local config allows full connectivity?\n config.objects.host = ipHost ?? '';\n }\n\n fs.writeFileSync(this.configName, JSON.stringify(config, null, 2));\n console.log('Config ok. Please restart ioBroker: \"iobroker restart\"');\n callback();\n }\n } else {\n callback(new Error('No configuration received!'));\n }\n });\n }\n\n /**\n * Connect to MH Server\n *\n * @param index index of host to connect to\n * @param pass password\n * @param callback\n */\n async connect(\n index: number | null,\n pass: string | null,\n callback: (err?: Error, list?: BrowseResultEntry[]) => void,\n ): Promise<void> {\n if (typeof pass === 'function') {\n callback = pass;\n pass = null;\n }\n if (typeof index === 'function') {\n callback = index;\n index = null;\n }\n\n const mhClient = new MHClient();\n let list: BrowseResultEntry[];\n\n try {\n list = await mhClient.browse(2_000, !!this.params.debug);\n } catch (e) {\n callback(new Error(`Cannot browse: ${e.message}`));\n return;\n }\n\n this.showHosts(list);\n\n if (index !== null && index !== undefined && index > 0) {\n if (list && index < list.length + 1) {\n if (!pass) {\n callback(new Error('No password defined: please use \"multihost connect <NUMBER> <PASSWORD>\"'));\n } else {\n this.connectHelper(mhClient, list[index - 1].ip!, pass, callback);\n }\n } else {\n callback(new Error(`Invalid index: ${index}`));\n }\n } else if (list && list.length) {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n rl.question('Please select host [1]: ', answer => {\n if (answer === '' || answer === null || answer === undefined) {\n index = 1;\n }\n index = parseInt(answer, 10) - 1;\n const listEntry = list[index];\n if (!listEntry) {\n rl.close();\n callback(new Error(`Invalid index: ${answer}`));\n } else {\n if (listEntry.auth) {\n const password = this.readPassword();\n if (password) {\n this.connectHelper(mhClient, listEntry.ip!, password, callback);\n } else {\n callback(new Error('No password entered!'));\n }\n } else {\n this.connectHelper(mhClient, listEntry.ip!, '', callback);\n }\n }\n });\n } else {\n callback(undefined, list);\n }\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_js_controller_common", "fs", "path", "prompt", "err", "readlineSync", "readline"]
4
+ "sourcesContent": ["import fs from 'fs-extra';\nimport path from 'node:path';\nimport readline from 'node:readline';\nimport readlineSync from 'readline-sync';\nimport prompt from 'prompt';\n\nimport { tools } from '@iobroker/js-controller-common';\nimport { isLocalObjectsDbServer, isLocalStatesDbServer } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';\nimport { MHClient, type BrowseResultEntry } from './multihostClient.js';\n\ninterface MHParams {\n secure?: boolean;\n persist?: boolean;\n debug?: boolean;\n}\n\n/** Options for Multihost CLI */\nexport interface CLIMultihostOptions {\n /** Redis client for objects DB */\n objects: ObjectsRedisClient;\n /** Additional parameters */\n params?: MHParams;\n}\n\n/**\n * Multihost CLI class\n * Handles multihost related commands\n */\nexport class Multihost {\n private readonly configName: string;\n private params: MHParams;\n private objects: ObjectsRedisClient;\n\n /**\n * Constructor\n *\n * @param options options for the Multihost CLI\n */\n constructor(options: CLIMultihostOptions) {\n this.configName = tools.getConfigFileName();\n this.params = options.params || {};\n this.objects = options.objects;\n }\n\n /**\n * Retrieve config (iobroker.json content)\n */\n getConfig(): ioBroker.IoBrokerJson {\n let config;\n // read actual configuration\n try {\n if (fs.existsSync(this.configName)) {\n config = fs.readJsonSync(this.configName);\n } else {\n config = fs.readJsonSync(\n path.join(tools.getControllerDir(), 'conf', `${tools.appName.toLowerCase()}-dist.json`),\n );\n }\n } catch {\n config = fs.readJsonSync(\n path.join(tools.getControllerDir(), 'conf', `${tools.appName.toLowerCase()}-dist.json`),\n );\n }\n return config;\n }\n\n /**\n * Show hosts on CLI\n *\n * @param list list of hosts\n */\n showHosts(list: BrowseResultEntry[]): void {\n if (!list || !list.length) {\n console.info(\n 'No Multihost server found. Make sure iobroker is running on the host where you enabled multihost discovery (and it is not this host)!',\n );\n } else {\n for (let i = 0; i < list.length; i++) {\n console.log(\n `${i + 1} | ${list[i].hostname!.padStart(20)} | ${list[i].slave ? 'slave' : ' host'} | ${list[\n i\n ].ip!.padStart(20)} | ${JSON.stringify(list[i].info)}`,\n );\n }\n }\n }\n\n /**\n * Start MH browsing\n */\n async browse(): Promise<BrowseResultEntry[]> {\n const mhClient = new MHClient();\n try {\n return await mhClient.browse(2_000, !!this.params.debug);\n } catch (e) {\n throw new Error(`Multihost discovery client: Cannot browse: ${e.message}`);\n }\n }\n\n /**\n * Show MH state on CLI\n *\n * @param config iob config\n * @param changed if config has changed\n */\n private async showMHState(config: ioBroker.IoBrokerJson, changed: boolean): Promise<void> {\n if (config.multihostService.enabled) {\n let warningShown = false;\n\n const hasLocalObjectsServer = await isLocalObjectsDbServer(config.objects.type, config.objects.host, true);\n\n if (hasLocalObjectsServer) {\n console.log('Changing objects server to accept connections on all IP addresses.');\n config.objects.host = tools.getListenAllAddress();\n changed = true;\n } else if (config.objects.type === 'redis') {\n warningShown = true;\n console.log(\n `Please check the binding of redis service. By default it is only local: http://download.redis.io/redis-stable/redis.conf\\nChange \"bind 127.0.0.1\" to \"bind ${tools.getListenAllAddress()}\" or to others.`,\n );\n } else {\n warningShown = true;\n console.log(\n `Please check the binding of the configured ${config.objects.type} server to allow remote connections.`,\n );\n }\n\n const hasLocalStatesServer = await isLocalStatesDbServer(config.states.type, config.states.host, true);\n\n if (hasLocalStatesServer) {\n console.log('Changing states server to accept connections on all IP addresses.');\n config.states.host = tools.getListenAllAddress();\n changed = true;\n } else if (config.states.type === 'redis') {\n !warningShown &&\n console.log(\n `Please check the binding of redis service. By default it is only local: http://download.redis.io/redis-stable/redis.conf\\nChange \"bind 127.0.0.1\" to \"bind ${tools.getListenAllAddress()}\" or to others.`,\n );\n } else {\n !warningShown &&\n console.log(\n `Please check the binding of the configured ${config.states.type} server to allow remote connections.`,\n );\n }\n }\n if (!changed) {\n console.log('No configuration change needed.');\n } else {\n fs.writeFileSync(this.configName, JSON.stringify(config, null, 2));\n console.log('Please restart ioBroker for the changes to take effect: \"iobroker restart\"');\n }\n console.log('\\n');\n console.log(`Multihost discovery server: ${config.multihostService.enabled ? 'enabled' : 'disabled'}`);\n console.log(`Discovery authentication: ${config.multihostService.secure ? 'enabled' : 'disabled'}`);\n console.log(\n `Persistent activation: ${\n config.multihostService.enabled && config.multihostService.persist ? 'enabled' : 'disabled'\n }`,\n );\n console.log(\n `Objects: ${config.objects.type} on ${Array.isArray(config.objects.host) ? config.objects.host.join(', ') : config.objects.host}`,\n );\n console.log(\n `States: ${config.states.type} on ${Array.isArray(config.states.host) ? config.states.host.join(', ') : config.states.host}`,\n );\n }\n\n /**\n * Enables or disables the multihost discovery server in the config json\n *\n * @param isEnable - if the server should be activated or deactivated\n * @param callback - callback function to be executed\n */\n enable(isEnable: boolean, callback: (err?: Error) => void): void {\n let changed = false;\n const config = this.getConfig();\n config.multihostService = config.multihostService || { enabled: false, secure: true };\n\n if (isEnable && !config.multihostService.enabled) {\n changed = true;\n config.multihostService.enabled = true;\n config.multihostService.password = '';\n console.log(\n 'Multihost discovery server activated on this host. If iobroker is currently not running please start before trying to discover this host.',\n );\n console.log(\n 'Important: Multihost discovery works with UDP packets. Make sure they are routed correctly in your network. If you use Docker you also need to configure this correctly.',\n );\n if (!this.params.persist) {\n console.log(\n 'Multihost discovery will be automatically deactivated after 15 minutes. If you want to activate it permanently use the --persist flag',\n );\n }\n } else if (!isEnable && config.multihostService.enabled) {\n changed = true;\n config.multihostService.enabled = false;\n config.multihostService.password = '';\n console.log('Multihost discovery server deactivated on this host.');\n }\n if (this.params.secure === undefined) {\n this.params.secure = true;\n }\n\n this.params.persist = !!this.params.persist;\n\n if (\n isEnable &&\n (config.multihostService.secure !== this.params.secure ||\n (config.multihostService.secure && !config.multihostService.password) ||\n config.multihostService.persist !== this.params.persist)\n ) {\n changed = true;\n config.multihostService.secure = this.params.secure;\n config.multihostService.persist = this.params.persist;\n console.log(`Discovery authentication ${this.params.secure ? 'activated' : 'deactivated'}.`);\n if (config.multihostService.secure) {\n prompt.message = '';\n prompt.delimiter = '';\n const schema = {\n properties: {\n password: {\n description: 'Enter secret phrase for connection:',\n pattern: /^[^'\"]+$/,\n message: 'No \" are allowed',\n hidden: true,\n },\n passwordRepeat: {\n description: 'Repeat secret phrase for connection:',\n pattern: /^[^'\"]+$/,\n message: 'No \" are allowed',\n hidden: true,\n },\n },\n };\n prompt.start();\n\n prompt.get(schema, (_err, password) => {\n if (password?.password) {\n if (password.password !== password.passwordRepeat) {\n callback(new Error('Secret phrases are not equal!'));\n } else {\n this.objects.getObject('system.config', (_err, obj) => {\n config.multihostService.password = tools.encrypt(\n obj!.native.secret,\n password.password as string,\n );\n this.showMHState(config, changed);\n callback();\n });\n }\n } else {\n callback(new Error('No secret phrase entered!'));\n }\n });\n } else {\n this.showMHState(config, changed);\n callback();\n }\n } else {\n this.showMHState(config, changed);\n callback();\n }\n }\n\n /**\n * Show the MH status\n */\n status(): void {\n const config = this.getConfig();\n config.multihostService = config.multihostService || { enabled: false, secure: true };\n this.showMHState(config, false);\n }\n\n /**\n * Read password from cli\n */\n readPassword(): string {\n return readlineSync.question('Enter secret phrase for connection: ', { hideEchoBack: true });\n }\n\n /**\n * Connect to given MH server\n *\n * @param mhClient MultiHost Client used for connection\n * @param ip IP address of server\n * @param pass password\n * @param callback callback\n */\n connectHelper(mhClient: MHClient, ip: string, pass: string, callback: (err?: Error) => void): void {\n mhClient.connect(ip, pass, async (err, oObjects, oStates, ipHost) => {\n if (err) {\n callback(new Error(`Cannot connect to \"${ip}\": ${err.message}`));\n } else if (oObjects && oStates) {\n const config = this.getConfig();\n config.objects = oObjects;\n config.states = oStates;\n\n const hasLocalObjectsServer = await isLocalObjectsDbServer(\n config.objects.type,\n config.objects.host,\n true,\n );\n const hasLocalStatesServer = await isLocalStatesDbServer(config.states.type, config.states.host, true);\n\n if (hasLocalObjectsServer || hasLocalStatesServer) {\n callback(\n new Error(\n `IP Address of the remote host is ${tools.getLocalAddress()}. Connections from this host will not be accepted. Please change the configuration of this host to accept remote connections.`,\n ),\n );\n } else if (\n (!Array.isArray(config.states.host) || config.states.host.length === 1) &&\n (!Array.isArray(config.objects.host) || config.objects.host.length === 1)\n ) {\n const sHost = Array.isArray(config.states.host) ? config.states.host[0] : config.states.host;\n // If server delivers 0.0.0.0 or ::, set to actual IP of the host\n if (tools.isListenAllAddress(sHost)) {\n config.states.host = ipHost ?? '';\n }\n const oHost = Array.isArray(config.objects.host) ? config.objects.host[0] : config.objects.host;\n // If server delivers 0.0.0.0 or ::, set to actual IP of the host\n if (tools.isListenAllAddress(oHost)) {\n config.objects.host = ipHost ?? '';\n }\n\n fs.writeFileSync(this.configName, JSON.stringify(config, null, 2));\n console.log('Config ok. Please restart ioBroker: \"iobroker restart\"');\n callback();\n } else {\n // Find if any of the hosts is \"listen all\" or reachable\n if (Array.isArray(config.states.host)) {\n config.states.host = config.states.host.map((sHost: string) =>\n tools.isListenAllAddress(sHost) ? (ipHost ?? '') : sHost,\n );\n }\n if (Array.isArray(config.objects.host)) {\n config.objects.host = config.objects.host.map((oHost: string) =>\n tools.isListenAllAddress(oHost) ? (ipHost ?? '') : oHost,\n );\n }\n\n fs.writeFileSync(this.configName, JSON.stringify(config, null, 2));\n console.log('Config ok. Please restart ioBroker: \"iobroker restart\"');\n callback();\n }\n } else {\n callback(new Error('No configuration received!'));\n }\n });\n }\n\n /**\n * Connect to MH Server\n *\n * @param index index of host to connect to\n * @param pass password\n * @param callback callback\n */\n async connect(\n index: number | null,\n pass: string | null,\n callback: (err?: Error, list?: BrowseResultEntry[]) => void,\n ): Promise<void> {\n if (typeof pass === 'function') {\n callback = pass;\n pass = null;\n }\n if (typeof index === 'function') {\n callback = index;\n index = null;\n }\n\n const mhClient = new MHClient();\n let list: BrowseResultEntry[];\n\n try {\n list = await mhClient.browse(2_000, !!this.params.debug);\n } catch (e) {\n callback(new Error(`Cannot browse: ${e.message}`));\n return;\n }\n\n this.showHosts(list);\n\n if (index !== null && index !== undefined && index > 0) {\n if (list && index < list.length + 1) {\n if (!pass) {\n callback(new Error('No password defined: please use \"multihost connect <NUMBER> <PASSWORD>\"'));\n } else {\n this.connectHelper(mhClient, list[index - 1].ip!, pass, callback);\n }\n } else {\n callback(new Error(`Invalid index: ${index}`));\n }\n } else if (list && list.length) {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n rl.question('Please select host [1]: ', answer => {\n if (answer === '' || answer === null || answer === undefined) {\n index = 1;\n }\n index = parseInt(answer, 10) - 1;\n const listEntry = list[index];\n if (!listEntry) {\n rl.close();\n callback(new Error(`Invalid index: ${answer}`));\n } else {\n if (listEntry.auth) {\n const password = this.readPassword();\n if (password) {\n this.connectHelper(mhClient, listEntry.ip!, password, callback);\n } else {\n callback(new Error('No password entered!'));\n }\n } else {\n this.connectHelper(mhClient, listEntry.ip!, '', callback);\n }\n }\n });\n } else {\n callback(undefined, list);\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_js_controller_common", "fs", "path", "prompt", "_err", "readlineSync", "readline"]
7
7
  }
@@ -1,11 +1,3 @@
1
- /**
2
- * Setup
3
- *
4
- * Copyright 2013-2024 bluefox <dogafox@gmail.com>
5
- *
6
- * MIT License
7
- *
8
- */
9
1
  import type { CleanDatabaseHandler, IoPackage, ProcessExitCallback, RestartController } from '../../lib/_Types.js';
10
2
  import { EXIT_CODES } from '@iobroker/js-controller-common';
11
3
  export interface CLISetupOptions {
@@ -75,9 +67,9 @@ export declare class Setup {
75
67
  */
76
68
  private _ensureHostObject;
77
69
  /**
78
- * Add adapter-core in supported version in the overrides field of the root package.json and call install there to apply it
70
+ * Add or update adapter-core in supported version in the overrides field of the root package.json and call install there to apply it
79
71
  */
80
- private addAdapterCoreRequirement;
72
+ private addOrUpdateAdapterCoreRequirement;
81
73
  /**
82
74
  * Create the adapters object per host if not yet existing
83
75
  */
@@ -111,7 +103,7 @@ export declare class Setup {
111
103
  */
112
104
  private _cleanupInvalidGroupAssignments;
113
105
  /**
114
- * Setup the installation with config file, host object, scripts etc
106
+ * Set up the installation with config file, host object, scripts etc
115
107
  *
116
108
  * @param options setup options
117
109
  */
@@ -59,7 +59,7 @@ class Setup {
59
59
  /** Object IDs which are not allowed to exist but could be generated due to errors in the past */
60
60
  KNOWN_GARBAGE_OBJECT_IDS = ["null", "undefined"];
61
61
  /** Adapter core version supported by this js-controller */
62
- SUPPORTED_ADAPTER_CORE_VERSION = "^3.2.1";
62
+ SUPPORTED_ADAPTER_CORE_VERSION = "^3.3.2";
63
63
  /** Default name for redis sentinels */
64
64
  DEFAULT_SENTINEL_NAME = "mymaster";
65
65
  processExit;
@@ -167,7 +167,7 @@ class Setup {
167
167
  await this._fixWindowsControllerJs();
168
168
  }
169
169
  try {
170
- await this.addAdapterCoreRequirement();
170
+ await this.addOrUpdateAdapterCoreRequirement();
171
171
  } catch (e) {
172
172
  console.error(`Could not add "@iobroker/adapter-core" requirement: ${e.message}`);
173
173
  }
@@ -262,7 +262,7 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
262
262
  }
263
263
  if (!configObj.native?.secret) {
264
264
  const buf = import_node_crypto.default.randomBytes(24);
265
- configObj.native = configObj.native || {};
265
+ configObj.native ||= {};
266
266
  configObj.native.secret = buf.toString("hex");
267
267
  configObj.from = `system.host.${import_js_controller_common.tools.getHostName()}.cli`;
268
268
  configObj.ts = Date.now();
@@ -295,14 +295,14 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
295
295
  let certObj;
296
296
  if (iopkg?.objects) {
297
297
  for (const obj of iopkg.objects) {
298
- if (obj && obj._id === "system.certificates") {
298
+ if (obj?._id === "system.certificates") {
299
299
  certObj = obj;
300
300
  break;
301
301
  }
302
302
  }
303
303
  }
304
304
  if (certObj) {
305
- let obj;
305
+ let obj = null;
306
306
  try {
307
307
  obj = await this.objects.getObjectAsync("system.certificates");
308
308
  } catch {
@@ -529,31 +529,30 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
529
529
  }
530
530
  async setupCustom() {
531
531
  let config;
532
- let originalConfig;
533
532
  try {
534
533
  if (import_fs_extra.default.existsSync(import_js_controller_common.tools.getConfigFileName())) {
535
534
  config = import_fs_extra.default.readJsonSync(import_js_controller_common.tools.getConfigFileName());
536
- originalConfig = (0, import_deep_clone.default)(config);
537
535
  } else {
538
536
  config = import_fs_extra.default.readJsonSync(import_node_path.default.join(CONTROLLER_DIR, "conf", `${import_js_controller_common.tools.appName.toLowerCase()}-dist.json`));
539
537
  }
540
538
  } catch {
541
539
  config = import_fs_extra.default.readJsonSync(import_node_path.default.join(CONTROLLER_DIR, "conf", `${import_js_controller_common.tools.appName.toLowerCase()}-dist.json`));
542
540
  }
541
+ const originalConfig = (0, import_deep_clone.default)(config);
543
542
  const currentObjectsType = originalConfig.objects.type || "jsonl";
544
543
  const currentStatesType = originalConfig.states.type || "jsonl";
545
544
  console.log("Current configuration:");
546
545
  console.log("- Objects database:");
547
546
  console.log(` - Type: ${originalConfig.objects.type}`);
548
- console.log(` - Host/Unix Socket: ${originalConfig.objects.host}`);
549
- console.log(` - Port: ${originalConfig.objects.port}`);
547
+ console.log(` - Host/Unix Socket: ${Array.isArray(originalConfig.objects.host) ? originalConfig.objects.host.join(",") : originalConfig.objects.host}`);
548
+ console.log(` - Port: ${Array.isArray(originalConfig.objects.port) ? originalConfig.objects.port.join(",") : originalConfig.objects.port}`);
550
549
  if (Array.isArray(originalConfig.objects.host)) {
551
550
  console.log(` - Sentinel-Master-Name: ${originalConfig.objects.sentinelName ? originalConfig.objects.sentinelName : this.DEFAULT_SENTINEL_NAME}`);
552
551
  }
553
552
  console.log("- States database:");
554
553
  console.log(` - Type: ${originalConfig.states.type}`);
555
- console.log(` - Host/Unix Socket: ${originalConfig.states.host}`);
556
- console.log(` - Port: ${originalConfig.states.port}`);
554
+ console.log(` - Host/Unix Socket: ${Array.isArray(originalConfig.states.host) ? originalConfig.states.host.join(",") : originalConfig.states.host}`);
555
+ console.log(` - Port: ${Array.isArray(originalConfig.states.port) ? originalConfig.states.port.join(",") : originalConfig.states.port}`);
557
556
  if (Array.isArray(originalConfig.states.host)) {
558
557
  console.log(` - Sentinel-Master-Name: ${originalConfig.states.sentinelName ? originalConfig.states.sentinelName : this.DEFAULT_SENTINEL_NAME}`);
559
558
  }
@@ -562,37 +561,37 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
562
561
  if (hasObjectsServer || hasStatesServer) {
563
562
  console.log(`- Data Directory: ${import_js_controller_common.tools.getDefaultDataDir()}`);
564
563
  }
565
- if (originalConfig && originalConfig.system && originalConfig.system.hostname) {
564
+ if (originalConfig?.system?.hostname) {
566
565
  console.log(`- Host name: ${originalConfig.system.hostname}`);
567
566
  }
568
567
  console.log("");
569
- let otype = import_readline_sync.default.question(`Type of objects DB [(j)sonl, (f)ile, (r)edis, ...], default [${currentObjectsType}]: `, {
568
+ let oType = import_readline_sync.default.question(`Type of objects DB [(j)sonl, (f)ile, (r)edis, ...], default [${currentObjectsType}]: `, {
570
569
  defaultInput: currentObjectsType
571
570
  });
572
- otype = otype.toLowerCase();
573
- if (otype === "r") {
574
- otype = "redis";
575
- } else if (otype === "f") {
576
- otype = "file";
577
- } else if (otype === "j") {
578
- otype = "jsonl";
571
+ oType = oType.toLowerCase();
572
+ if (oType === "r") {
573
+ oType = "redis";
574
+ } else if (oType === "f") {
575
+ oType = "file";
576
+ } else if (oType === "j") {
577
+ oType = "jsonl";
579
578
  }
580
579
  let getDefaultObjectsPort;
581
580
  try {
582
- const path2 = require2.resolve(`@iobroker/db-objects-${otype}`);
581
+ const path2 = require2.resolve(`@iobroker/db-objects-${oType}`);
583
582
  getDefaultObjectsPort = require2(path2).getDefaultPort;
584
583
  } catch {
585
- console.log(`${COLOR_RED}Unknown objects type: ${otype}${COLOR_RESET}`);
586
- if (otype !== "file" && otype !== "redis") {
584
+ console.log(`${COLOR_RED}Unknown objects type: ${oType}${COLOR_RESET}`);
585
+ if (oType !== "file" && oType !== "redis") {
587
586
  console.log(COLOR_YELLOW);
588
587
  console.log(`Please check that the objects db type you entered is really correct!`);
589
- console.log(`If yes please use "npm i @iobroker/db-objects-${otype}" to install it manually.`);
588
+ console.log(`If yes please use "npm i @iobroker/db-objects-${oType}" to install it manually.`);
590
589
  console.log(`You also need to make sure you stay up to date with this package in the future!`);
591
590
  console.log(COLOR_RESET);
592
591
  }
593
592
  return import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS;
594
593
  }
595
- if (otype === "redis" && originalConfig.objects.type !== "redis") {
594
+ if (oType === "redis" && originalConfig.objects.type !== "redis") {
596
595
  console.log(COLOR_YELLOW);
597
596
  console.log("When Objects and Files are stored in a Redis database please consider the following:");
598
597
  console.log("1. All data will be stored in RAM, make sure to have enough free RAM available!");
@@ -600,18 +599,18 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
600
599
  console.log("3. The Redis persistence files can get big, make sure not to use an SD card to store them.");
601
600
  console.log(COLOR_RESET);
602
601
  }
603
- const defaultObjectsHost = otype === originalConfig.objects.type ? originalConfig.objects.host : import_js_controller_common.tools.getLocalAddress();
604
- let oHost = import_readline_sync.default.question(`Host / Unix Socket of objects DB(${otype}), default[${Array.isArray(defaultObjectsHost) ? defaultObjectsHost.join(",") : defaultObjectsHost}]: `, {
602
+ const defaultObjectsHost = oType === originalConfig.objects.type ? originalConfig.objects.host : import_js_controller_common.tools.getLocalAddress();
603
+ let oHost = import_readline_sync.default.question(`Host / Unix Socket of objects DB(${oType}), default[${Array.isArray(defaultObjectsHost) ? defaultObjectsHost.join(",") : defaultObjectsHost}]: `, {
605
604
  defaultInput: Array.isArray(defaultObjectsHost) ? defaultObjectsHost.join(",") : defaultObjectsHost
606
605
  });
607
606
  oHost = oHost.toLowerCase();
608
607
  const op = getDefaultObjectsPort(oHost);
609
- const oSentinel = otype === "redis" && oHost.includes(",");
608
+ const oSentinel = oType === "redis" && oHost.includes(",");
610
609
  if (oSentinel) {
611
610
  oHost = oHost.split(",").map((host) => host.trim());
612
611
  }
613
- const defaultObjectsPort = otype === originalConfig.objects.type && oHost === originalConfig.objects.host ? originalConfig.objects.port : op;
614
- const userObjPort = import_readline_sync.default.question(`Port of objects DB(${otype}), default[${Array.isArray(defaultObjectsPort) ? defaultObjectsPort.join(",") : defaultObjectsPort}]: `, {
612
+ const defaultObjectsPort = oType === originalConfig.objects.type && oHost === originalConfig.objects.host ? originalConfig.objects.port : op;
613
+ const userObjPort = import_readline_sync.default.question(`Port of objects DB(${oType}), default[${Array.isArray(defaultObjectsPort) ? defaultObjectsPort.join(",") : defaultObjectsPort}]: `, {
615
614
  defaultInput: Array.isArray(defaultObjectsPort) ? defaultObjectsPort.join(",") : defaultObjectsPort,
616
615
  limit: /^[0-9, ]+$/
617
616
  });
@@ -637,7 +636,7 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
637
636
  return import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS;
638
637
  }
639
638
  }
640
- config.objects = await (0, import_js_controller_common2.performObjectsInterview)({ dbType: otype, config: config.objects });
639
+ config.objects = await (0, import_js_controller_common2.performObjectsInterview)({ dbType: oType, config: config.objects });
641
640
  let oSentinelName = null;
642
641
  if (oSentinel) {
643
642
  const defaultSentinelName = originalConfig.objects.sentinelName ? originalConfig.objects.sentinelName : this.DEFAULT_SENTINEL_NAME;
@@ -647,61 +646,61 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
647
646
  }
648
647
  let defaultStatesType = currentStatesType;
649
648
  try {
650
- require2.resolve(`@iobroker/db-states-${otype}`);
651
- defaultStatesType = otype;
649
+ require2.resolve(`@iobroker/db-states-${oType}`);
650
+ defaultStatesType = oType;
652
651
  } catch {
653
652
  }
654
- let stype = import_readline_sync.default.question(`Type of states DB [(j)sonl, (f)file, (r)edis, ...], default [${defaultStatesType}]: `, {
653
+ let sType = import_readline_sync.default.question(`Type of states DB [(j)sonl, (f)file, (r)edis, ...], default [${defaultStatesType}]: `, {
655
654
  defaultInput: defaultStatesType
656
655
  });
657
- stype = stype.toLowerCase();
658
- if (stype === "r") {
659
- stype = "redis";
660
- } else if (stype === "f") {
661
- stype = "file";
662
- } else if (stype === "j") {
663
- stype = "jsonl";
656
+ sType = sType.toLowerCase();
657
+ if (sType === "r") {
658
+ sType = "redis";
659
+ } else if (sType === "f") {
660
+ sType = "file";
661
+ } else if (sType === "j") {
662
+ sType = "jsonl";
664
663
  }
665
664
  let getDefaultStatesPort;
666
665
  try {
667
- const path2 = require2.resolve(`@iobroker/db-states-${stype}`);
666
+ const path2 = require2.resolve(`@iobroker/db-states-${sType}`);
668
667
  getDefaultStatesPort = require2(path2).getDefaultPort;
669
668
  } catch {
670
- console.log(`${COLOR_RED}Unknown states type: ${stype}${COLOR_RESET}`);
671
- if (stype !== "file" && stype !== "redis") {
669
+ console.log(`${COLOR_RED}Unknown states type: ${sType}${COLOR_RESET}`);
670
+ if (sType !== "file" && sType !== "redis") {
672
671
  console.log(COLOR_YELLOW);
673
672
  console.log(`Please check that the states db type you entered is really correct!`);
674
- console.log(`If yes please use "npm i @iobroker/db-states-${stype}" to install it manually.`);
673
+ console.log(`If yes please use "npm i @iobroker/db-states-${sType}" to install it manually.`);
675
674
  console.log(`You also need to make sure you stay up to date with this package in the future!`);
676
675
  console.log(COLOR_RESET);
677
676
  }
678
677
  return import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS;
679
678
  }
680
- if (stype === "redis" && originalConfig.states.type !== "redis" && otype !== "redis") {
679
+ if (sType === "redis" && originalConfig.states.type !== "redis" && oType !== "redis") {
681
680
  console.log(COLOR_YELLOW);
682
681
  console.log("When States are stored in a Redis database please make sure to configure Redis");
683
682
  console.log("persistence to make sure a Redis problem will not cause data loss!");
684
683
  console.log(COLOR_RESET);
685
684
  }
686
- let defaultStatesHost = stype === originalConfig.states.type ? originalConfig.states.host : oHost || import_js_controller_common.tools.getLocalAddress();
687
- if (stype === otype) {
685
+ let defaultStatesHost = sType === originalConfig.states.type ? originalConfig.states.host : oHost || import_js_controller_common.tools.getLocalAddress();
686
+ if (sType === oType) {
688
687
  defaultStatesHost = oHost;
689
688
  }
690
- let sHost = import_readline_sync.default.question(`Host / Unix Socket of states DB (${stype}), default[${Array.isArray(defaultStatesHost) ? defaultStatesHost.join(",") : defaultStatesHost}]: `, {
689
+ let sHost = import_readline_sync.default.question(`Host / Unix Socket of states DB (${sType}), default[${Array.isArray(defaultStatesHost) ? defaultStatesHost.join(",") : defaultStatesHost}]: `, {
691
690
  defaultInput: Array.isArray(defaultStatesHost) ? defaultStatesHost.join(",") : defaultStatesHost
692
691
  });
693
692
  sHost = sHost.toLowerCase();
694
693
  const sp = getDefaultStatesPort(sHost);
695
- const sSentinel = stype === "redis" && sHost.includes(",");
694
+ const sSentinel = sType === "redis" && sHost.includes(",");
696
695
  if (sSentinel) {
697
696
  sHost = sHost.split(",").map((host) => host.trim());
698
697
  }
699
- let defaultStatesPort = stype === originalConfig.states.type && sHost === originalConfig.states.host ? originalConfig.states.port : sp;
700
- const statesHasServer = await (0, import_js_controller_common2.statesDbHasServer)(stype);
701
- if (stype === otype && !statesHasServer && sHost === oHost) {
698
+ let defaultStatesPort = sType === originalConfig.states.type && sHost === originalConfig.states.host ? originalConfig.states.port : sp;
699
+ const statesHasServer = await (0, import_js_controller_common2.statesDbHasServer)(sType);
700
+ if (sType === oType && !statesHasServer && sHost === oHost) {
702
701
  defaultStatesPort = oPort;
703
702
  }
704
- const userStatePort = import_readline_sync.default.question(`Port of states DB (${stype}), default[${Array.isArray(defaultStatesPort) ? defaultStatesPort.join(",") : defaultStatesPort}]: `, {
703
+ const userStatePort = import_readline_sync.default.question(`Port of states DB (${sType}), default[${Array.isArray(defaultStatesPort) ? defaultStatesPort.join(",") : defaultStatesPort}]: `, {
705
704
  defaultInput: Array.isArray(defaultStatesPort) ? defaultStatesPort.join(",") : defaultStatesPort,
706
705
  limit: /^[0-9, ]+$/
707
706
  });
@@ -728,7 +727,7 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
728
727
  return import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS;
729
728
  }
730
729
  }
731
- config.states = await (0, import_js_controller_common2.performStatesInterview)({ dbType: stype, config: config.states });
730
+ config.states = await (0, import_js_controller_common2.performStatesInterview)({ dbType: sType, config: config.states });
732
731
  let sSentinelName = null;
733
732
  if (sSentinel) {
734
733
  const defaultSentinelName = originalConfig.states.sentinelName ? originalConfig.states.sentinelName : oSentinelName && oPort === sPort ? oSentinelName : this.DEFAULT_SENTINEL_NAME;
@@ -738,8 +737,8 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
738
737
  }
739
738
  let dir;
740
739
  let hname;
741
- const hasLocalObjectsServer = await (0, import_js_controller_common2.isLocalObjectsDbServer)(otype, oHost);
742
- const hasLocalStatesServer = await (0, import_js_controller_common2.isLocalStatesDbServer)(stype, sHost);
740
+ const hasLocalObjectsServer = await (0, import_js_controller_common2.isLocalObjectsDbServer)(oType, oHost);
741
+ const hasLocalStatesServer = await (0, import_js_controller_common2.isLocalStatesDbServer)(sType, sHost);
743
742
  if (hasLocalStatesServer || hasLocalObjectsServer) {
744
743
  let validDataDir = false;
745
744
  while (!validDataDir) {
@@ -765,13 +764,13 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
765
764
  console.log(`${COLOR_RED}Invalid host name: ${hname}${COLOR_RESET}`);
766
765
  return import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS;
767
766
  }
768
- config.system = config.system || {};
767
+ config.system ||= {};
769
768
  config.system.hostname = hname;
770
769
  config.objects.host = oHost;
771
- config.objects.type = otype;
770
+ config.objects.type = oType;
772
771
  config.objects.port = oPort;
773
772
  config.states.host = sHost;
774
- config.states.type = stype;
773
+ config.states.type = sType;
775
774
  config.states.port = sPort;
776
775
  config.states.dataDir = void 0;
777
776
  config.objects.dataDir = void 0;
@@ -787,8 +786,7 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
787
786
  if (config.states.type === "redis" && sSentinel && sSentinelName && sSentinelName !== this.DEFAULT_SENTINEL_NAME) {
788
787
  config.states.sentinelName = sSentinelName;
789
788
  }
790
- const exitCode = await this.migrateObjects(config, originalConfig);
791
- return exitCode;
789
+ return await this.migrateObjects(config, originalConfig);
792
790
  }
793
791
  /**
794
792
  * Checks if single host setup and if so migrates and activates Redis Sets Usage
@@ -825,9 +823,9 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
825
823
  }
826
824
  }
827
825
  /**
828
- * Add adapter-core in supported version in the overrides field of the root package.json and call install there to apply it
826
+ * Add or update adapter-core in supported version in the overrides field of the root package.json and call install there to apply it
829
827
  */
830
- async addAdapterCoreRequirement() {
828
+ async addOrUpdateAdapterCoreRequirement() {
831
829
  if (import_js_controller_common.tools.isDevInstallation()) {
832
830
  return;
833
831
  }
@@ -1099,7 +1097,7 @@ Please DO NOT copy files manually into ioBroker storage directories!`);
1099
1097
  }
1100
1098
  }
1101
1099
  /**
1102
- * Setup the installation with config file, host object, scripts etc
1100
+ * Set up the installation with config file, host object, scripts etc
1103
1101
  *
1104
1102
  * @param options setup options
1105
1103
  */
@@ -1214,19 +1212,10 @@ require('${import_node_path.default.normalize(`${thisDir}/..`)}/setup').execute(
1214
1212
  console.log(`Non-critical error: ${e.message}`);
1215
1213
  }
1216
1214
  } else if (ignoreIfExist) {
1217
- try {
1218
- config = import_fs_extra.default.readJSONSync(configFileName);
1219
- if (!Object.prototype.hasOwnProperty.call(config, "dataDir")) {
1220
- config.dataDir = import_js_controller_common.tools.getDefaultDataDir();
1221
- import_fs_extra.default.writeJSONSync(configFileName, config, { spaces: 2 });
1222
- }
1223
- } catch (e) {
1224
- console.warn(`Cannot check config file: ${e.message}`);
1225
- }
1226
- this.setupObjects(() => callback && callback(), true);
1215
+ this.setupObjects(() => callback?.(), true);
1227
1216
  return;
1228
1217
  }
1229
- this.setupObjects(() => callback && callback(isCreated));
1218
+ this.setupObjects(() => callback?.(isCreated));
1230
1219
  }
1231
1220
  }
1232
1221
  // Annotate the CommonJS export names for ESM import in node: