@iobroker/js-controller-cli 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 (225) hide show
  1. package/build/cjs/index.js +3 -3
  2. package/build/cjs/lib/_Types.d.ts +8 -1
  3. package/build/cjs/lib/cli/cliCert.d.ts +7 -4
  4. package/build/cjs/lib/cli/cliCert.js +10 -6
  5. package/build/cjs/lib/cli/cliCert.js.map +2 -2
  6. package/build/cjs/lib/cli/cliCommand.d.ts +63 -15
  7. package/build/cjs/lib/cli/cliCommand.js +8 -1
  8. package/build/cjs/lib/cli/cliCommand.js.map +2 -2
  9. package/build/cjs/lib/cli/cliCompact.d.ts +5 -2
  10. package/build/cjs/lib/cli/cliCompact.js +9 -2
  11. package/build/cjs/lib/cli/cliCompact.js.map +2 -2
  12. package/build/cjs/lib/cli/cliDebug.d.ts +5 -2
  13. package/build/cjs/lib/cli/cliDebug.js +8 -1
  14. package/build/cjs/lib/cli/cliDebug.js.map +2 -2
  15. package/build/cjs/lib/cli/cliHost.d.ts +13 -10
  16. package/build/cjs/lib/cli/cliHost.js +13 -5
  17. package/build/cjs/lib/cli/cliHost.js.map +2 -2
  18. package/build/cjs/lib/cli/cliLogs.d.ts +9 -3
  19. package/build/cjs/lib/cli/cliLogs.js +12 -1
  20. package/build/cjs/lib/cli/cliLogs.js.map +2 -2
  21. package/build/cjs/lib/cli/cliMessage.d.ts +2 -1
  22. package/build/cjs/lib/cli/cliMessage.js +5 -0
  23. package/build/cjs/lib/cli/cliMessage.js.map +2 -2
  24. package/build/cjs/lib/cli/cliObjects.d.ts +21 -18
  25. package/build/cjs/lib/cli/cliObjects.js +51 -33
  26. package/build/cjs/lib/cli/cliObjects.js.map +2 -2
  27. package/build/cjs/lib/cli/cliPlugin.d.ts +3 -3
  28. package/build/cjs/lib/cli/cliPlugin.js +6 -0
  29. package/build/cjs/lib/cli/cliPlugin.js.map +2 -2
  30. package/build/cjs/lib/cli/cliProcess.d.ts +17 -7
  31. package/build/cjs/lib/cli/cliProcess.js +77 -24
  32. package/build/cjs/lib/cli/cliProcess.js.map +3 -3
  33. package/build/cjs/lib/cli/cliStates.d.ts +7 -4
  34. package/build/cjs/lib/cli/cliStates.js +14 -6
  35. package/build/cjs/lib/cli/cliStates.js.map +2 -2
  36. package/build/cjs/lib/cli/cliTools.js +11 -0
  37. package/build/cjs/lib/cli/cliTools.js.map +1 -1
  38. package/build/cjs/lib/cli/messages.js +47 -46
  39. package/build/cjs/lib/cli/messages.js.map +1 -1
  40. package/build/cjs/lib/progressBar.d.ts +59 -0
  41. package/build/cjs/lib/progressBar.js +115 -0
  42. package/build/cjs/lib/progressBar.js.map +7 -0
  43. package/build/cjs/lib/setup/customError.d.ts +4 -0
  44. package/build/cjs/lib/setup/customError.js +7 -0
  45. package/build/cjs/lib/setup/customError.js.map +2 -2
  46. package/build/cjs/lib/setup/dbConnection.js +69 -64
  47. package/build/cjs/lib/setup/dbConnection.js.map +3 -3
  48. package/build/cjs/lib/setup/formatters.d.ts +4 -4
  49. package/build/cjs/lib/setup/formatters.js +5 -0
  50. package/build/cjs/lib/setup/formatters.js.map +2 -2
  51. package/build/cjs/lib/setup/multihostClient.js +6 -2
  52. package/build/cjs/lib/setup/multihostClient.js.map +1 -1
  53. package/build/cjs/lib/setup/pluginInfos.d.ts +5 -0
  54. package/build/cjs/lib/setup/pluginInfos.js +2 -0
  55. package/build/cjs/lib/setup/pluginInfos.js.map +2 -2
  56. package/build/cjs/lib/setup/setupBackup.d.ts +53 -0
  57. package/build/cjs/lib/setup/setupBackup.js +125 -14
  58. package/build/cjs/lib/setup/setupBackup.js.map +3 -3
  59. package/build/cjs/lib/setup/setupInstall.d.ts +66 -15
  60. package/build/cjs/lib/setup/setupInstall.js +282 -28
  61. package/build/cjs/lib/setup/setupInstall.js.map +2 -2
  62. package/build/cjs/lib/setup/setupLicense.d.ts +13 -0
  63. package/build/cjs/lib/setup/setupLicense.js +33 -2
  64. package/build/cjs/lib/setup/setupLicense.js.map +2 -2
  65. package/build/cjs/lib/setup/setupList.d.ts +55 -1
  66. package/build/cjs/lib/setup/setupList.js +78 -24
  67. package/build/cjs/lib/setup/setupList.js.map +3 -3
  68. package/build/cjs/lib/setup/setupMultihost.d.ts +7 -0
  69. package/build/cjs/lib/setup/setupMultihost.js +78 -11
  70. package/build/cjs/lib/setup/setupMultihost.js.map +3 -3
  71. package/build/cjs/lib/setup/setupPacketManager.d.ts +10 -0
  72. package/build/cjs/lib/setup/setupPacketManager.js +16 -6
  73. package/build/cjs/lib/setup/setupPacketManager.js.map +2 -2
  74. package/build/cjs/lib/setup/setupRepo.d.ts +19 -0
  75. package/build/cjs/lib/setup/setupRepo.js +141 -13
  76. package/build/cjs/lib/setup/setupRepo.js.map +2 -2
  77. package/build/cjs/lib/setup/setupSetup.d.ts +34 -0
  78. package/build/cjs/lib/setup/setupSetup.js +209 -35
  79. package/build/cjs/lib/setup/setupSetup.js.map +3 -3
  80. package/build/cjs/lib/setup/setupUpgrade.d.ts +13 -2
  81. package/build/cjs/lib/setup/setupUpgrade.js +72 -12
  82. package/build/cjs/lib/setup/setupUpgrade.js.map +2 -2
  83. package/build/cjs/lib/setup/setupUpload.d.ts +77 -1
  84. package/build/cjs/lib/setup/setupUpload.js +152 -9
  85. package/build/cjs/lib/setup/setupUpload.js.map +2 -2
  86. package/build/cjs/lib/setup/setupUsers.d.ts +44 -14
  87. package/build/cjs/lib/setup/setupUsers.js +330 -17
  88. package/build/cjs/lib/setup/setupUsers.js.map +2 -2
  89. package/build/cjs/lib/setup/setupVendor.d.ts +14 -1
  90. package/build/cjs/lib/setup/setupVendor.js +40 -8
  91. package/build/cjs/lib/setup/setupVendor.js.map +2 -2
  92. package/build/cjs/lib/setup/setupVisDebug.d.ts +16 -2
  93. package/build/cjs/lib/setup/setupVisDebug.js +41 -17
  94. package/build/cjs/lib/setup/setupVisDebug.js.map +3 -3
  95. package/build/cjs/lib/setup/utils.d.ts +1 -1
  96. package/build/cjs/lib/setup/utils.js +13 -9
  97. package/build/cjs/lib/setup/utils.js.map +3 -3
  98. package/build/cjs/lib/setup.d.ts +1 -1
  99. package/build/cjs/lib/setup.js +858 -1758
  100. package/build/cjs/lib/setup.js.map +3 -3
  101. package/build/esm/lib/_Types.d.ts +8 -1
  102. package/build/esm/lib/_Types.d.ts.map +1 -1
  103. package/build/esm/lib/cli/cliCert.d.ts +7 -4
  104. package/build/esm/lib/cli/cliCert.d.ts.map +1 -1
  105. package/build/esm/lib/cli/cliCert.js +6 -6
  106. package/build/esm/lib/cli/cliCert.js.map +1 -1
  107. package/build/esm/lib/cli/cliCommand.d.ts +63 -15
  108. package/build/esm/lib/cli/cliCommand.d.ts.map +1 -1
  109. package/build/esm/lib/cli/cliCommand.js +4 -1
  110. package/build/esm/lib/cli/cliCommand.js.map +1 -1
  111. package/build/esm/lib/cli/cliCompact.d.ts +5 -2
  112. package/build/esm/lib/cli/cliCompact.d.ts.map +1 -1
  113. package/build/esm/lib/cli/cliCompact.js +5 -2
  114. package/build/esm/lib/cli/cliCompact.js.map +1 -1
  115. package/build/esm/lib/cli/cliDebug.d.ts +5 -2
  116. package/build/esm/lib/cli/cliDebug.d.ts.map +1 -1
  117. package/build/esm/lib/cli/cliDebug.js +4 -1
  118. package/build/esm/lib/cli/cliDebug.js.map +1 -1
  119. package/build/esm/lib/cli/cliHost.d.ts +13 -10
  120. package/build/esm/lib/cli/cliHost.d.ts.map +1 -1
  121. package/build/esm/lib/cli/cliHost.js +8 -5
  122. package/build/esm/lib/cli/cliHost.js.map +1 -1
  123. package/build/esm/lib/cli/cliLogs.d.ts +9 -3
  124. package/build/esm/lib/cli/cliLogs.d.ts.map +1 -1
  125. package/build/esm/lib/cli/cliLogs.js +8 -1
  126. package/build/esm/lib/cli/cliLogs.js.map +1 -1
  127. package/build/esm/lib/cli/cliMessage.d.ts +2 -1
  128. package/build/esm/lib/cli/cliMessage.d.ts.map +1 -1
  129. package/build/esm/lib/cli/cliMessage.js +1 -0
  130. package/build/esm/lib/cli/cliMessage.js.map +1 -1
  131. package/build/esm/lib/cli/cliObjects.d.ts +21 -18
  132. package/build/esm/lib/cli/cliObjects.d.ts.map +1 -1
  133. package/build/esm/lib/cli/cliObjects.js +44 -38
  134. package/build/esm/lib/cli/cliObjects.js.map +1 -1
  135. package/build/esm/lib/cli/cliPlugin.d.ts +3 -3
  136. package/build/esm/lib/cli/cliPlugin.d.ts.map +1 -1
  137. package/build/esm/lib/cli/cliPlugin.js +1 -1
  138. package/build/esm/lib/cli/cliPlugin.js.map +1 -1
  139. package/build/esm/lib/cli/cliProcess.d.ts +17 -7
  140. package/build/esm/lib/cli/cliProcess.d.ts.map +1 -1
  141. package/build/esm/lib/cli/cliProcess.js +73 -12
  142. package/build/esm/lib/cli/cliProcess.js.map +1 -1
  143. package/build/esm/lib/cli/cliStates.d.ts +7 -4
  144. package/build/esm/lib/cli/cliStates.d.ts.map +1 -1
  145. package/build/esm/lib/cli/cliStates.js +6 -2
  146. package/build/esm/lib/cli/cliStates.js.map +1 -1
  147. package/build/esm/lib/progressBar.d.ts +59 -0
  148. package/build/esm/lib/progressBar.d.ts.map +1 -0
  149. package/build/esm/lib/progressBar.js +104 -0
  150. package/build/esm/lib/progressBar.js.map +1 -0
  151. package/build/esm/lib/setup/customError.d.ts +4 -0
  152. package/build/esm/lib/setup/customError.d.ts.map +1 -1
  153. package/build/esm/lib/setup/customError.js +3 -0
  154. package/build/esm/lib/setup/customError.js.map +1 -1
  155. package/build/esm/lib/setup/dbConnection.d.ts.map +1 -1
  156. package/build/esm/lib/setup/dbConnection.js +10 -13
  157. package/build/esm/lib/setup/dbConnection.js.map +1 -1
  158. package/build/esm/lib/setup/formatters.d.ts +4 -4
  159. package/build/esm/lib/setup/formatters.js +4 -4
  160. package/build/esm/lib/setup/pluginInfos.d.ts +5 -0
  161. package/build/esm/lib/setup/pluginInfos.d.ts.map +1 -1
  162. package/build/esm/lib/setup/pluginInfos.js +5 -0
  163. package/build/esm/lib/setup/pluginInfos.js.map +1 -1
  164. package/build/esm/lib/setup/setupBackup.d.ts +53 -0
  165. package/build/esm/lib/setup/setupBackup.d.ts.map +1 -1
  166. package/build/esm/lib/setup/setupBackup.js +132 -13
  167. package/build/esm/lib/setup/setupBackup.js.map +1 -1
  168. package/build/esm/lib/setup/setupInstall.d.ts +66 -15
  169. package/build/esm/lib/setup/setupInstall.d.ts.map +1 -1
  170. package/build/esm/lib/setup/setupInstall.js +309 -23
  171. package/build/esm/lib/setup/setupInstall.js.map +1 -1
  172. package/build/esm/lib/setup/setupLicense.d.ts +13 -0
  173. package/build/esm/lib/setup/setupLicense.d.ts.map +1 -1
  174. package/build/esm/lib/setup/setupLicense.js +31 -1
  175. package/build/esm/lib/setup/setupLicense.js.map +1 -1
  176. package/build/esm/lib/setup/setupList.d.ts +55 -1
  177. package/build/esm/lib/setup/setupList.d.ts.map +1 -1
  178. package/build/esm/lib/setup/setupList.js +61 -8
  179. package/build/esm/lib/setup/setupList.js.map +1 -1
  180. package/build/esm/lib/setup/setupMultihost.d.ts +7 -0
  181. package/build/esm/lib/setup/setupMultihost.d.ts.map +1 -1
  182. package/build/esm/lib/setup/setupMultihost.js +85 -6
  183. package/build/esm/lib/setup/setupMultihost.js.map +1 -1
  184. package/build/esm/lib/setup/setupPacketManager.d.ts +10 -0
  185. package/build/esm/lib/setup/setupPacketManager.d.ts.map +1 -1
  186. package/build/esm/lib/setup/setupPacketManager.js +9 -0
  187. package/build/esm/lib/setup/setupPacketManager.js.map +1 -1
  188. package/build/esm/lib/setup/setupRepo.d.ts +19 -0
  189. package/build/esm/lib/setup/setupRepo.d.ts.map +1 -1
  190. package/build/esm/lib/setup/setupRepo.js +164 -14
  191. package/build/esm/lib/setup/setupRepo.js.map +1 -1
  192. package/build/esm/lib/setup/setupSetup.d.ts +34 -0
  193. package/build/esm/lib/setup/setupSetup.d.ts.map +1 -1
  194. package/build/esm/lib/setup/setupSetup.js +218 -21
  195. package/build/esm/lib/setup/setupSetup.js.map +1 -1
  196. package/build/esm/lib/setup/setupUpgrade.d.ts +13 -2
  197. package/build/esm/lib/setup/setupUpgrade.d.ts.map +1 -1
  198. package/build/esm/lib/setup/setupUpgrade.js +70 -6
  199. package/build/esm/lib/setup/setupUpgrade.js.map +1 -1
  200. package/build/esm/lib/setup/setupUpload.d.ts +77 -1
  201. package/build/esm/lib/setup/setupUpload.d.ts.map +1 -1
  202. package/build/esm/lib/setup/setupUpload.js +164 -7
  203. package/build/esm/lib/setup/setupUpload.js.map +1 -1
  204. package/build/esm/lib/setup/setupUsers.d.ts +44 -14
  205. package/build/esm/lib/setup/setupUsers.d.ts.map +1 -1
  206. package/build/esm/lib/setup/setupUsers.js +346 -14
  207. package/build/esm/lib/setup/setupUsers.js.map +1 -1
  208. package/build/esm/lib/setup/setupVendor.d.ts +14 -1
  209. package/build/esm/lib/setup/setupVendor.d.ts.map +1 -1
  210. package/build/esm/lib/setup/setupVendor.js +33 -2
  211. package/build/esm/lib/setup/setupVendor.js.map +1 -1
  212. package/build/esm/lib/setup/setupVisDebug.d.ts +16 -2
  213. package/build/esm/lib/setup/setupVisDebug.d.ts.map +1 -1
  214. package/build/esm/lib/setup/setupVisDebug.js +39 -14
  215. package/build/esm/lib/setup/setupVisDebug.js.map +1 -1
  216. package/build/esm/lib/setup/utils.d.ts +1 -1
  217. package/build/esm/lib/setup/utils.d.ts.map +1 -1
  218. package/build/esm/lib/setup/utils.js +2 -4
  219. package/build/esm/lib/setup/utils.js.map +1 -1
  220. package/build/esm/lib/setup.d.ts +1 -1
  221. package/build/esm/lib/setup.d.ts.map +1 -1
  222. package/build/esm/lib/setup.js +959 -1910
  223. package/build/esm/lib/setup.js.map +1 -1
  224. package/build/tsconfig.build.tsbuildinfo +1 -1
  225. package/package.json +14 -14
@@ -6,25 +6,30 @@
6
6
  * MIT License
7
7
  *
8
8
  */
9
- import { tools, EXIT_CODES } from '@iobroker/js-controller-common';
10
- import fs from 'fs-extra';
11
9
  import path from 'node:path';
12
- import semver from 'semver';
13
10
  import child_process from 'node:child_process';
14
- import axios from 'axios';
15
11
  import { URL } from 'node:url';
12
+ import { createRequire } from 'node:module';
13
+ import axios from 'axios';
14
+ import fs from 'fs-extra';
15
+ import semver from 'semver';
16
+ import { tools, EXIT_CODES } from '@iobroker/js-controller-common';
16
17
  import { Upload } from '../../lib/setup/setupUpload.js';
17
18
  import { PacketManager } from '../../lib/setup/setupPacketManager.js';
18
19
  import { getRepository } from '../../lib/setup/utils.js';
19
20
  import { IoBrokerError } from '../../lib/setup/customError.js';
21
+ import { dbConnect } from '../../lib/setup/dbConnection.js';
22
+ import * as CLITools from '../../lib/cli/cliTools.js';
20
23
  import { SYSTEM_ADAPTER_PREFIX } from '@iobroker/js-controller-common-db/constants';
21
- import { createRequire } from 'node:module';
22
24
  // eslint-disable-next-line unicorn/prefer-module
23
25
  const require = createRequire(import.meta.url || `file://${__filename}`);
24
26
  const hostname = tools.getHostName();
25
27
  const osPlatform = process.platform;
26
28
  /** Note: this is duplicated in preinstallCheck */
27
29
  const RECOMMENDED_NPM_VERSION = 8;
30
+ /**
31
+ * CLI command to install and download adapters and create their instances
32
+ */
28
33
  export class Install {
29
34
  isRootOnUnix;
30
35
  objects;
@@ -34,6 +39,9 @@ export class Install {
34
39
  tarballRegex;
35
40
  upload;
36
41
  packetManager;
42
+ /**
43
+ * @param options The states/objects clients, CLI parameters and the process-exit callback
44
+ */
37
45
  constructor(options) {
38
46
  this.isRootOnUnix = typeof process.getuid === 'function' && process.getuid() === 0;
39
47
  options = options || {};
@@ -88,7 +96,7 @@ export class Install {
88
96
  if (!options || typeof options !== 'object') {
89
97
  options = {};
90
98
  }
91
- stoppedList = stoppedList || [];
99
+ stoppedList ||= [];
92
100
  let sources;
93
101
  if (!repoUrlOrRepo || !tools.isObject(repoUrlOrRepo)) {
94
102
  sources = await getRepository({ repoName: repoUrlOrRepo, objects: this.objects });
@@ -250,7 +258,8 @@ export class Install {
250
258
  unsafePerm: !!options.unsafePerm,
251
259
  });
252
260
  // code 1 is sometimes a real error and sometimes a strange error, where everything is installed but still the error
253
- const isSuccess = result.success || (result.exitCode === 1 && !result.stderr.startsWith('npm ERR!'));
261
+ const isSuccess = result.success ||
262
+ (result.exitCode === 1 && !result.stderr.startsWith('npm ERR!') && !result.stderr.startsWith('npm error '));
254
263
  if (isSuccess) {
255
264
  // Determine where the packet would be installed if npm succeeds
256
265
  // TODO: There's probably a better way to figure this out
@@ -309,7 +318,7 @@ export class Install {
309
318
  console.info('Try to solve ENOTEMPTY error automatically');
310
319
  const errorFilePath = result.stderr
311
320
  .split('\n')
312
- ?.find(line => line.startsWith('npm ERR! dest'))
321
+ ?.find(line => line.startsWith('npm ERR! dest') || line.startsWith('npm error dest'))
313
322
  ?.split('dest')[1]
314
323
  .trim();
315
324
  const affectedNodeModulesPath = errorFilePath ? path.join(errorFilePath, '..') : undefined;
@@ -464,7 +473,7 @@ export class Install {
464
473
  obj.from = `system.host.${hostname}.cli`;
465
474
  obj.ts = Date.now();
466
475
  try {
467
- await this.objects.extendObjectAsync(obj._id, obj);
476
+ await this.objects.extendObject(obj._id, obj);
468
477
  }
469
478
  catch (err) {
470
479
  console.error(`host.${hostname} error setObject ${obj._id} ${err.message}`);
@@ -478,8 +487,8 @@ export class Install {
478
487
  * Installs given adapter
479
488
  *
480
489
  * @param adapter The adapter name
481
- * @param repoUrl
482
- * @param _installCount
490
+ * @param repoUrl Optional repository URL to install the adapter from
491
+ * @param _installCount Internal recursion counter limiting the number of dependency installs
483
492
  */
484
493
  async installAdapter(adapter, repoUrl, _installCount) {
485
494
  _installCount = _installCount || 0;
@@ -546,6 +555,11 @@ export class Install {
546
555
  await this.upload.upgradeAdapterObjects(adapter);
547
556
  return adapter;
548
557
  }
558
+ /**
559
+ * Install the OS packages required by an adapter
560
+ *
561
+ * @param osDependencies The OS dependencies declared by the adapter, keyed by platform
562
+ */
549
563
  async installOSPackages(osDependencies) {
550
564
  if (osPlatform in osDependencies) {
551
565
  try {
@@ -559,6 +573,12 @@ export class Install {
559
573
  }
560
574
  }
561
575
  }
576
+ /**
577
+ * Run the custom install script of an adapter if it defines one
578
+ *
579
+ * @param adapter The adapter name
580
+ * @param config The adapter object containing the install configuration
581
+ */
562
582
  async callInstallOfAdapter(adapter, config) {
563
583
  if (config.common.install) {
564
584
  // Install node modules
@@ -814,10 +834,10 @@ export class Install {
814
834
  /**
815
835
  * Enumerate all instances of an adapter
816
836
  *
817
- * @param knownObjIDs
818
- * @param notDeleted
819
- * @param adapter
820
- * @param instance
837
+ * @param knownObjIDs Accumulator of object IDs found so far
838
+ * @param notDeleted Accumulator of object IDs that must not be deleted
839
+ * @param adapter The adapter name
840
+ * @param instance Optional instance number to restrict the search to
821
841
  */
822
842
  async _enumerateAdapterInstances(knownObjIDs, notDeleted, adapter, instance) {
823
843
  if (!notDeleted) {
@@ -867,9 +887,9 @@ export class Install {
867
887
  /**
868
888
  * Enumerate all meta objects of an adapter
869
889
  *
870
- * @param knownObjIDs
871
- * @param adapter
872
- * @param metaFilesToDelete
890
+ * @param knownObjIDs Accumulator of object IDs found so far
891
+ * @param adapter The adapter name
892
+ * @param metaFilesToDelete Accumulator of meta files that should be deleted
873
893
  */
874
894
  async _enumerateAdapterMeta(knownObjIDs, adapter, metaFilesToDelete) {
875
895
  try {
@@ -1076,9 +1096,9 @@ export class Install {
1076
1096
  /**
1077
1097
  * Enumerate all state IDs of an adapter (or instance)
1078
1098
  *
1079
- * @param knownStateIDs
1080
- * @param adapter
1081
- * @param instance
1099
+ * @param knownStateIDs Accumulator of state IDs found so far
1100
+ * @param adapter The adapter name
1101
+ * @param instance Optional instance number to restrict the search to
1082
1102
  */
1083
1103
  async _enumerateAdapterStates(knownStateIDs, adapter, instance) {
1084
1104
  for (const pattern of [
@@ -1107,8 +1127,8 @@ export class Install {
1107
1127
  /**
1108
1128
  * delete WWW pages, objects and meta files
1109
1129
  *
1110
- * @param adapter
1111
- * @param metaFilesToDelete
1130
+ * @param adapter The adapter name
1131
+ * @param metaFilesToDelete The meta files that should be deleted
1112
1132
  */
1113
1133
  async _deleteAdapterFiles(adapter, metaFilesToDelete) {
1114
1134
  // special files, which are not meta (vis widgets), combined with meta object ids
@@ -1295,6 +1315,9 @@ export class Install {
1295
1315
  await this._deleteAdapterFiles(adapter, metaFilesToDelete);
1296
1316
  await this._deleteAdapterObjects(knownObjectIDs);
1297
1317
  await this._deleteAdapterStates(knownStateIDs);
1318
+ // this path removes the instance objects itself instead of going through deleteInstance,
1319
+ // so the registry entries of every instance of the adapter have to be freed here as well
1320
+ await this._freeUsedResources(adapter);
1298
1321
  if (this.params.custom) {
1299
1322
  // remove adapter from custom
1300
1323
  await this._removeCustomFromObjects([...instances, adapter]);
@@ -1331,11 +1354,89 @@ export class Install {
1331
1354
  await this._enumerateAdapterDocs(knownObjectIDs, adapter, instance);
1332
1355
  await this._deleteAdapterObjects(knownObjectIDs);
1333
1356
  await this._deleteAdapterStates(knownStateIDs);
1357
+ await this._freeUsedResources(adapter, instance);
1334
1358
  if (this.params.custom) {
1335
1359
  // delete instance from custom
1336
1360
  await this._removeCustomFromObjects([`${adapter}.${instance}`]);
1337
1361
  }
1338
1362
  }
1363
+ /**
1364
+ * Free all exclusive resources (serial ports, TCP/UDP ports, ...) the given instance(s) had registered.
1365
+ *
1366
+ * This is needed because an instance can be deleted via the CLI while a js-controller is not running: it
1367
+ * cannot notice that the instance object disappeared, so its `system.host.<host>.usedResources.<type>`
1368
+ * states would keep listing the resources of an instance that no longer exists.
1369
+ *
1370
+ * Hosts that are running are deliberately skipped. Such a host cleans its own registry up when it sees the
1371
+ * instance object being deleted, and it holds the registry in memory: it rewrites the state from that copy
1372
+ * on its next change, which would silently undo a write made here.
1373
+ *
1374
+ * @param adapter adapter name, e.g. "mqtt"
1375
+ * @param instance instance number; if undefined, all instances of the adapter are freed
1376
+ */
1377
+ async _freeUsedResources(adapter, instance) {
1378
+ const matches = (namespace) => instance !== undefined ? namespace === `${adapter}.${instance}` : namespace.startsWith(`${adapter}.`);
1379
+ let keys;
1380
+ try {
1381
+ keys = await this.states.getKeys('system.host.*.usedResources.*');
1382
+ }
1383
+ catch (e) {
1384
+ console.warn(`Cannot read the used resources registry: ${e.message}`);
1385
+ return;
1386
+ }
1387
+ if (!keys?.length) {
1388
+ return;
1389
+ }
1390
+ const hostPrefix = 'system.host.';
1391
+ const registryMarker = '.usedResources.';
1392
+ /** whether a host is currently running, queried once per host */
1393
+ const hostIsRunning = new Map();
1394
+ for (const id of keys) {
1395
+ const markerIndex = id.lastIndexOf(registryMarker);
1396
+ if (!id.startsWith(hostPrefix) || markerIndex <= hostPrefix.length) {
1397
+ continue;
1398
+ }
1399
+ const host = id.substring(hostPrefix.length, markerIndex);
1400
+ let isRunning = hostIsRunning.get(host);
1401
+ if (isRunning === undefined) {
1402
+ try {
1403
+ const aliveState = await this.states.getState(`${hostPrefix}${host}.alive`);
1404
+ isRunning = aliveState?.val === true;
1405
+ }
1406
+ catch (e) {
1407
+ // if it cannot be determined, assume the host is running: leaving an entry behind is
1408
+ // harmless (its controller drops it on the next start) while fighting a live controller
1409
+ // over the same state is not
1410
+ console.warn(`Cannot check whether host "${host}" is running: ${e.message}`);
1411
+ isRunning = true;
1412
+ }
1413
+ hostIsRunning.set(host, isRunning);
1414
+ }
1415
+ if (isRunning) {
1416
+ continue;
1417
+ }
1418
+ try {
1419
+ const state = await this.states.getState(id);
1420
+ if (!state || typeof state.val !== 'string' || !state.val) {
1421
+ continue;
1422
+ }
1423
+ const parsed = JSON.parse(state.val);
1424
+ if (!Array.isArray(parsed)) {
1425
+ continue;
1426
+ }
1427
+ const original = parsed;
1428
+ // keep anything that is malformed: it cannot be attributed to the deleted instance, and one
1429
+ // broken entry must not stop the cleanup of the sound ones in the same state
1430
+ const filtered = original.filter(entry => typeof entry?.instance !== 'string' || !matches(entry.instance));
1431
+ if (filtered.length !== original.length) {
1432
+ await this.states.setStateAsync(id, { val: JSON.stringify(filtered), ack: true });
1433
+ }
1434
+ }
1435
+ catch (e) {
1436
+ console.warn(`Cannot free the used resources in "${id}": ${e.message}`);
1437
+ }
1438
+ }
1439
+ }
1339
1440
  /**
1340
1441
  * Remove all node modules that has been installed by this instance
1341
1442
  *
@@ -1624,4 +1725,189 @@ export class Install {
1624
1725
  return instances;
1625
1726
  }
1626
1727
  }
1728
+ /**
1729
+ * @param options options provided by the processCommand dispatcher
1730
+ */
1731
+ export function processCommandUrl(options) {
1732
+ const { args, params, callback } = options;
1733
+ let url = args[0];
1734
+ const name = args[1];
1735
+ if (!url) {
1736
+ console.log('Please provide a URL to install from and optionally a name of the adapter to install');
1737
+ return void callback(EXIT_CODES.INVALID_ARGUMENTS);
1738
+ }
1739
+ if (url[0] === '"' && url[url.length - 1] === '"') {
1740
+ url = url.substring(1, url.length - 1);
1741
+ }
1742
+ url = url.trim();
1743
+ dbConnect(params, async ({ objects, states }) => {
1744
+ const install = new Install({
1745
+ objects,
1746
+ states,
1747
+ processExit: callback,
1748
+ params,
1749
+ });
1750
+ try {
1751
+ await install.installAdapterFromUrl(url, name);
1752
+ return void callback(EXIT_CODES.NO_ERROR);
1753
+ }
1754
+ catch (e) {
1755
+ console.error(`Could not install adapter from url: ${e.message}`);
1756
+ return void callback(EXIT_CODES.CANNOT_INSTALL_NPM_PACKET);
1757
+ }
1758
+ });
1759
+ }
1760
+ /**
1761
+ * @param options options provided by the processCommand dispatcher
1762
+ */
1763
+ export function processCommandInstall(options) {
1764
+ const { command, args, params, callback } = options;
1765
+ const { showHelp } = options.commandOptions;
1766
+ let name = args[0];
1767
+ let instance = args[1];
1768
+ let repoUrl = args[2];
1769
+ if (parseInt(instance, 10).toString() !== (instance || '').toString()) {
1770
+ repoUrl = instance;
1771
+ instance = undefined;
1772
+ }
1773
+ if (parseInt(repoUrl, 10).toString() === (repoUrl || '').toString()) {
1774
+ const temp = instance;
1775
+ instance = repoUrl;
1776
+ repoUrl = temp;
1777
+ }
1778
+ if (instance && parseInt(instance, 10).toString() === (instance || '').toString()) {
1779
+ params.instance = parseInt(instance, 10);
1780
+ }
1781
+ // If user accidentally wrote tools.appName.adapter => remove adapter
1782
+ name = CLITools.normalizeAdapterName(name);
1783
+ const parsedName = CLITools.splitAdapterOrInstanceIdentifierWithVersion(name);
1784
+ if (!parsedName) {
1785
+ console.log('Invalid adapter name for install');
1786
+ showHelp();
1787
+ return void callback(EXIT_CODES.INVALID_ADAPTER_ID);
1788
+ }
1789
+ // split the adapter into its parts if necessary
1790
+ if (parsedName.instance !== null) {
1791
+ params.instance = parsedName.instance;
1792
+ }
1793
+ name = parsedName.name;
1794
+ const installName = parsedName.nameWithVersion;
1795
+ const adapterDir = tools.getAdapterDir(name);
1796
+ dbConnect(params, async ({ objects, states }) => {
1797
+ const install = new Install({
1798
+ objects,
1799
+ states,
1800
+ processExit: callback,
1801
+ params,
1802
+ });
1803
+ if (params.host && params.host !== tools.getHostName()) {
1804
+ // if host argument provided we should check, that host actually exists in mh environment
1805
+ let obj;
1806
+ try {
1807
+ obj = await objects.getObjectAsync(`system.host.${params.host}`);
1808
+ }
1809
+ catch (err) {
1810
+ console.warn(`Could not check existence of host "${params.host}": ${err.message}`);
1811
+ }
1812
+ if (!obj) {
1813
+ console.error(`Cannot add instance to non-existing host "${params.host}"`);
1814
+ return void callback(EXIT_CODES.NON_EXISTING_HOST);
1815
+ }
1816
+ }
1817
+ if (!adapterDir || !fs.existsSync(adapterDir)) {
1818
+ try {
1819
+ const { stoppedList } = await install.downloadPacket(repoUrl, installName);
1820
+ await install.installAdapter(installName, repoUrl);
1821
+ await install.enableInstances(stoppedList, true); // even if unlikely make sure to re-enable disabled instances
1822
+ if (command !== 'install' && command !== 'i') {
1823
+ await install.createInstance(name, params);
1824
+ }
1825
+ return void callback();
1826
+ }
1827
+ catch (e) {
1828
+ console.error(`adapter "${name}" cannot be installed: ${e.message}`);
1829
+ return void callback(e instanceof IoBrokerError ? e.code : EXIT_CODES.UNKNOWN_ERROR);
1830
+ }
1831
+ }
1832
+ else if (command !== 'install' && command !== 'i') {
1833
+ try {
1834
+ await install.createInstance(name, params);
1835
+ return void callback();
1836
+ }
1837
+ catch (err) {
1838
+ console.error(`adapter "${name}" cannot be installed: ${err.message}`);
1839
+ return void callback(EXIT_CODES.UNKNOWN_ERROR);
1840
+ }
1841
+ }
1842
+ else {
1843
+ console.log(`adapter "${name}" already installed. Use "upgrade" to upgrade to a newer version.`);
1844
+ return void callback(EXIT_CODES.ADAPTER_ALREADY_INSTALLED);
1845
+ }
1846
+ });
1847
+ }
1848
+ /**
1849
+ * @param options options provided by the processCommand dispatcher
1850
+ */
1851
+ export function processCommandDelete(options) {
1852
+ const { args, params, callback } = options;
1853
+ const { showHelp } = options.commandOptions;
1854
+ let adapter = args[0];
1855
+ let instance = args[1];
1856
+ // The adapter argument is required
1857
+ if (!adapter) {
1858
+ showHelp();
1859
+ return void callback(EXIT_CODES.INVALID_ADAPTER_ID);
1860
+ }
1861
+ // If the user accidentally wrote <tools.appName>.adapter,
1862
+ // remove <tools.appName> from the adapter name
1863
+ adapter = CLITools.normalizeAdapterName(adapter);
1864
+ // Avoid deleting stuff we don't want to delete
1865
+ // e.g. `system.adapter.*`
1866
+ if (!instance) {
1867
+ // Ensure that adapter contains a valid adapter (without instance nr)
1868
+ // or instance (with instance nr) identifier
1869
+ if (!CLITools.validateAdapterOrInstanceIdentifier(adapter)) {
1870
+ showHelp();
1871
+ return void callback(EXIT_CODES.INVALID_ADAPTER_ID);
1872
+ }
1873
+ // split the adapter into adapter + instance if necessary
1874
+ if (adapter.indexOf('.') > -1) {
1875
+ [adapter, instance] = adapter.split('.', 2);
1876
+ }
1877
+ }
1878
+ else {
1879
+ // ensure that adapter contains a valid adapter identifier
1880
+ // and the instance is a number
1881
+ if (!CLITools.validateAdapterIdentifier(adapter) || !/^\d+$/.test(instance)) {
1882
+ showHelp();
1883
+ return void callback(EXIT_CODES.INVALID_ADAPTER_ID);
1884
+ }
1885
+ }
1886
+ if (instance) {
1887
+ dbConnect(params, async ({ objects, states }) => {
1888
+ const install = new Install({
1889
+ objects,
1890
+ states,
1891
+ processExit: callback,
1892
+ params,
1893
+ });
1894
+ console.log(`Delete instance "${adapter}.${instance}"`);
1895
+ await install.deleteInstance(adapter, parseInt(instance));
1896
+ callback();
1897
+ });
1898
+ }
1899
+ else {
1900
+ dbConnect(params, async ({ objects, states }) => {
1901
+ const install = new Install({
1902
+ objects,
1903
+ states,
1904
+ processExit: callback,
1905
+ params,
1906
+ });
1907
+ console.log(`Delete adapter "${adapter}"`);
1908
+ const resultCode = await install.deleteAdapter(adapter);
1909
+ callback(resultCode);
1910
+ });
1911
+ }
1912
+ }
1627
1913
  //# sourceMappingURL=setupInstall.js.map