@iobroker/js-controller-cli 8.0.0-alpha.1-20260921-e5941ca8a → 8.0.0-alpha.12-20261105-0aa407437

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 (53) hide show
  1. package/build/cjs/index.d.ts +2 -0
  2. package/build/cjs/index.js +6 -0
  3. package/build/cjs/index.js.map +2 -2
  4. package/build/cjs/lib/cli/cliLogs.d.ts +20 -0
  5. package/build/cjs/lib/cli/cliLogs.js +44 -3
  6. package/build/cjs/lib/cli/cliLogs.js.map +2 -2
  7. package/build/cjs/lib/setup/adapterCompatibility.d.ts +39 -0
  8. package/build/cjs/lib/setup/adapterCompatibility.js +74 -0
  9. package/build/cjs/lib/setup/adapterCompatibility.js.map +7 -0
  10. package/build/cjs/lib/setup/setupInstall.d.ts +53 -0
  11. package/build/cjs/lib/setup/setupInstall.js +164 -19
  12. package/build/cjs/lib/setup/setupInstall.js.map +2 -2
  13. package/build/cjs/lib/setup/setupMultihost.d.ts +1 -1
  14. package/build/cjs/lib/setup/setupMultihost.js +2 -3
  15. package/build/cjs/lib/setup/setupMultihost.js.map +2 -2
  16. package/build/cjs/lib/setup/setupSetup.js +1 -1
  17. package/build/cjs/lib/setup/setupSetup.js.map +2 -2
  18. package/build/cjs/lib/setup.js +4 -0
  19. package/build/cjs/lib/setup.js.map +2 -2
  20. package/build/esm/index.d.ts +2 -0
  21. package/build/esm/index.d.ts.map +1 -1
  22. package/build/esm/index.js +2 -0
  23. package/build/esm/index.js.map +1 -1
  24. package/build/esm/lib/cli/cliLogs.d.ts +20 -0
  25. package/build/esm/lib/cli/cliLogs.d.ts.map +1 -1
  26. package/build/esm/lib/cli/cliLogs.js +46 -4
  27. package/build/esm/lib/cli/cliLogs.js.map +1 -1
  28. package/build/esm/lib/setup/adapterCompatibility.d.ts +39 -0
  29. package/build/esm/lib/setup/adapterCompatibility.d.ts.map +1 -0
  30. package/build/esm/lib/setup/adapterCompatibility.js +45 -0
  31. package/build/esm/lib/setup/adapterCompatibility.js.map +1 -0
  32. package/build/esm/lib/setup/setupInstall.d.ts +53 -0
  33. package/build/esm/lib/setup/setupInstall.d.ts.map +1 -1
  34. package/build/esm/lib/setup/setupInstall.js +182 -23
  35. package/build/esm/lib/setup/setupInstall.js.map +1 -1
  36. package/build/esm/lib/setup/setupMultihost.d.ts +1 -1
  37. package/build/esm/lib/setup/setupMultihost.d.ts.map +1 -1
  38. package/build/esm/lib/setup/setupMultihost.js +1 -2
  39. package/build/esm/lib/setup/setupMultihost.js.map +1 -1
  40. package/build/esm/lib/setup/setupSetup.js +1 -1
  41. package/build/esm/lib/setup/setupSetup.js.map +1 -1
  42. package/build/esm/lib/setup.d.ts.map +1 -1
  43. package/build/esm/lib/setup.js +4 -0
  44. package/build/esm/lib/setup.js.map +1 -1
  45. package/build/tsconfig.build.tsbuildinfo +1 -1
  46. package/package.json +4 -4
  47. package/build/cjs/lib/setup/multihostClient.d.ts +0 -96
  48. package/build/cjs/lib/setup/multihostClient.js +0 -252
  49. package/build/cjs/lib/setup/multihostClient.js.map +0 -7
  50. package/build/esm/lib/setup/multihostClient.d.ts +0 -96
  51. package/build/esm/lib/setup/multihostClient.d.ts.map +0 -1
  52. package/build/esm/lib/setup/multihostClient.js +0 -242
  53. package/build/esm/lib/setup/multihostClient.js.map +0 -1
@@ -3,7 +3,9 @@ export { dbConnectAsync } from './lib/setup/dbConnection.js';
3
3
  export { Vendor } from './lib/setup/setupVendor.js';
4
4
  export { Upload } from './lib/setup/setupUpload.js';
5
5
  export { Upgrade } from './lib/setup/setupUpgrade.js';
6
+ export { Install } from './lib/setup/setupInstall.js';
6
7
  export { BackupRestore } from './lib/setup/setupBackup.js';
7
8
  export { PacketManager, type UpgradePacket } from './lib/setup/setupPacketManager.js';
9
+ export { checkAdapterCompatibility, type AdapterCompatibilityInput, type AdapterCompatibilityProblem, } from './lib/setup/adapterCompatibility.js';
8
10
  export type * from './lib/_Types.js';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -19,10 +19,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var index_exports = {};
20
20
  __export(index_exports, {
21
21
  BackupRestore: () => import_setupBackup.BackupRestore,
22
+ Install: () => import_setupInstall.Install,
22
23
  PacketManager: () => import_setupPacketManager.PacketManager,
23
24
  Upgrade: () => import_setupUpgrade.Upgrade,
24
25
  Upload: () => import_setupUpload.Upload,
25
26
  Vendor: () => import_setupVendor.Vendor,
27
+ checkAdapterCompatibility: () => import_adapterCompatibility.checkAdapterCompatibility,
26
28
  dbConnectAsync: () => import_dbConnection.dbConnectAsync,
27
29
  execute: () => import_setup.execute
28
30
  });
@@ -32,15 +34,19 @@ var import_dbConnection = require("./lib/setup/dbConnection.js");
32
34
  var import_setupVendor = require("./lib/setup/setupVendor.js");
33
35
  var import_setupUpload = require("./lib/setup/setupUpload.js");
34
36
  var import_setupUpgrade = require("./lib/setup/setupUpgrade.js");
37
+ var import_setupInstall = require("./lib/setup/setupInstall.js");
35
38
  var import_setupBackup = require("./lib/setup/setupBackup.js");
36
39
  var import_setupPacketManager = require("./lib/setup/setupPacketManager.js");
40
+ var import_adapterCompatibility = require("./lib/setup/adapterCompatibility.js");
37
41
  // Annotate the CommonJS export names for ESM import in node:
38
42
  0 && (module.exports = {
39
43
  BackupRestore,
44
+ Install,
40
45
  PacketManager,
41
46
  Upgrade,
42
47
  Upload,
43
48
  Vendor,
49
+ checkAdapterCompatibility,
44
50
  dbConnectAsync,
45
51
  execute
46
52
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["/// <reference types=\"@iobroker/types-dev\" />\nexport { execute } from '@/lib/setup.js';\nexport { dbConnectAsync } from '@/lib/setup/dbConnection.js';\nexport { Vendor } from '@/lib/setup/setupVendor.js';\nexport { Upload } from '@/lib/setup/setupUpload.js';\nexport { Upgrade } from '@/lib/setup/setupUpgrade.js';\nexport { BackupRestore } from '@/lib/setup/setupBackup.js';\nexport { PacketManager, type UpgradePacket } from '@/lib/setup/setupPacketManager.js';\nexport type * from '@/lib/_Types.js';\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;AACA,mBAAwB;AACxB,0BAA+B;AAC/B,yBAAuB;AACvB,yBAAuB;AACvB,0BAAwB;AACxB,yBAA8B;AAC9B,gCAAkD;",
4
+ "sourcesContent": ["/// <reference types=\"@iobroker/types-dev\" />\nexport { execute } from '@/lib/setup.js';\nexport { dbConnectAsync } from '@/lib/setup/dbConnection.js';\nexport { Vendor } from '@/lib/setup/setupVendor.js';\nexport { Upload } from '@/lib/setup/setupUpload.js';\nexport { Upgrade } from '@/lib/setup/setupUpgrade.js';\nexport { Install } from '@/lib/setup/setupInstall.js';\nexport { BackupRestore } from '@/lib/setup/setupBackup.js';\nexport { PacketManager, type UpgradePacket } from '@/lib/setup/setupPacketManager.js';\nexport {\n checkAdapterCompatibility,\n type AdapterCompatibilityInput,\n type AdapterCompatibilityProblem,\n} from '@/lib/setup/adapterCompatibility.js';\nexport type * from '@/lib/_Types.js';\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;AACA,mBAAwB;AACxB,0BAA+B;AAC/B,yBAAuB;AACvB,yBAAuB;AACvB,0BAAwB;AACxB,0BAAwB;AACxB,yBAA8B;AAC9B,gCAAkD;AAClD,kCAIO;",
6
6
  "names": []
7
7
  }
@@ -4,6 +4,8 @@ interface CLILogsOptions {
4
4
  complete?: boolean;
5
5
  /** An optional RegExp to filter by */
6
6
  regex?: RegExp;
7
+ /** The lowest level to still show, if the output is restricted to a severity */
8
+ minLevel?: ioBroker.LogLevel;
7
9
  }
8
10
  /** Command ioBroker state ... */
9
11
  export declare class CLILogs extends CLICommand {
@@ -46,6 +48,24 @@ export declare class CLILogs extends CLICommand {
46
48
  * @param options some options
47
49
  */
48
50
  streamChange(path: string, start: number, options: CLILogsOptions): void;
51
+ /**
52
+ * Create the check of log lines against the active filters, for one read of a file
53
+ *
54
+ * A log entry can span several lines, e.g. a stack trace, and only its first line carries the
55
+ * level. Those follow-up lines inherit the decision made for the entry they belong to, so
56
+ * filtering by level does not cut a stack trace in half. Which lines start an entry is decided
57
+ * by the shared parser, the same one the host commands `getLogs` and `searchLogs` use: it takes
58
+ * a level only where the time stamp of an entry is, so a level quoted inside a message does not
59
+ * count as one.
60
+ *
61
+ * The decision belongs to one read and starts as "not shown". A read can begin with follow-up
62
+ * lines - the last lines of a file, or a stream from an offset - whose entry it does not know,
63
+ * and showing them would ignore the level. Files that are streamed at the same time do not
64
+ * share it either.
65
+ *
66
+ * @param options the active filters
67
+ */
68
+ private createFilter;
49
69
  }
50
70
  export {};
51
71
  //# sourceMappingURL=cliLogs.d.ts.map
@@ -67,6 +67,14 @@ class CLILogs extends import_cliCommand.CLICommand {
67
67
  const options = {
68
68
  complete: this.options.all
69
69
  };
70
+ if (params.level !== void 0) {
71
+ const level = String(params.level).toLowerCase();
72
+ if (!import_js_controller_common.tools.isLogLevel(level)) {
73
+ console.error(`Unknown log level "${params.level}". Use one of: ${import_js_controller_common.LOG_LEVELS.join(", ")}`);
74
+ return void this.options.callback(import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS);
75
+ }
76
+ options.minLevel = level;
77
+ }
70
78
  const config = import_fs_extra.default.readJSONSync(require2.resolve(getConfigFileName()));
71
79
  const logger = (0, import_js_controller_common.logger)(config.log);
72
80
  let fileName = logger.getFileName();
@@ -81,8 +89,9 @@ class CLILogs extends import_cliCommand.CLICommand {
81
89
  regex = new RegExp(`: ${adapterName}\\.`);
82
90
  options.regex = regex;
83
91
  }
92
+ const matches = this.createFilter(options);
84
93
  lines.forEach((line) => {
85
- if (regex && !regex.test(line)) {
94
+ if (!matches(line)) {
86
95
  return;
87
96
  }
88
97
  console.log(line);
@@ -150,12 +159,44 @@ class CLILogs extends import_cliCommand.CLICommand {
150
159
  start,
151
160
  autoClose: true
152
161
  });
153
- if (options.regex) {
154
- input.pipe(import_event_stream.default.split()).pipe(import_event_stream.default.filterSync((line) => options.regex.test(line))).pipe(import_event_stream.default.mapSync((line) => line + import_node_os.default.EOL)).pipe(process.stdout);
162
+ if (options.regex || options.minLevel) {
163
+ input.pipe(import_event_stream.default.split()).pipe(import_event_stream.default.filterSync(this.createFilter(options))).pipe(import_event_stream.default.mapSync((line) => line + import_node_os.default.EOL)).pipe(process.stdout);
155
164
  } else {
156
165
  import_js_controller_common.tools.pipeLinewise(input, process.stdout);
157
166
  }
158
167
  }
168
+ /**
169
+ * Create the check of log lines against the active filters, for one read of a file
170
+ *
171
+ * A log entry can span several lines, e.g. a stack trace, and only its first line carries the
172
+ * level. Those follow-up lines inherit the decision made for the entry they belong to, so
173
+ * filtering by level does not cut a stack trace in half. Which lines start an entry is decided
174
+ * by the shared parser, the same one the host commands `getLogs` and `searchLogs` use: it takes
175
+ * a level only where the time stamp of an entry is, so a level quoted inside a message does not
176
+ * count as one.
177
+ *
178
+ * The decision belongs to one read and starts as "not shown". A read can begin with follow-up
179
+ * lines - the last lines of a file, or a stream from an offset - whose entry it does not know,
180
+ * and showing them would ignore the level. Files that are streamed at the same time do not
181
+ * share it either.
182
+ *
183
+ * @param options the active filters
184
+ */
185
+ createFilter(options) {
186
+ let showEntry = false;
187
+ return (line) => {
188
+ if (options.minLevel) {
189
+ const header = (0, import_js_controller_common.parseLogEntryHeader)(line);
190
+ if (header) {
191
+ showEntry = (0, import_js_controller_common.isLogLevelAtLeast)(header.level, options.minLevel);
192
+ }
193
+ if (!showEntry) {
194
+ return false;
195
+ }
196
+ }
197
+ return !options.regex || options.regex.test(line);
198
+ };
199
+ }
159
200
  }
160
201
  // Annotate the CommonJS export names for ESM import in node:
161
202
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/cli/cliLogs.ts", "../../../../../../node_modules/@alcalzone/esm2cjs/shims/import.meta.url/shim.js"],
4
- "sourcesContent": ["import { CLICommand, type CLICommandOptions } from './cliCommand.js';\nimport { tools, logger as toolsLogger } from '@iobroker/js-controller-common';\nimport chokidar from 'chokidar';\nimport fs from 'fs-extra';\nimport os from 'node:os';\nimport es from 'event-stream';\nimport { createRequire } from 'node:module';\n// eslint-disable-next-line unicorn/prefer-module\nconst require = createRequire(import.meta.url || `file://${__filename}`);\n\nconst { getConfigFileName } = tools;\n\ninterface CLILogsOptions {\n /** Whether to show today's full log */\n complete?: boolean;\n /** An optional RegExp to filter by */\n regex?: RegExp;\n}\n\n/** Command ioBroker state ... */\nexport class CLILogs extends CLICommand {\n private readonly fileSizes = new Map<string, number>();\n private isReady = false;\n\n /**\n * @param options The command options including context and parameters\n */\n constructor(options: CLICommandOptions) {\n super(options);\n }\n\n /**\n * Executes a command\n *\n * @param args The command arguments (the first is the sub-command)\n * @param params additional parsed CLI parameters\n */\n execute(args: string[], params: Record<string, any>): void {\n const adapterName = args[0];\n const watch = params.watch || params.w;\n const count = params.lines || 1_000;\n\n const options: CLILogsOptions = {\n complete: this.options.all,\n };\n\n const config = fs.readJSONSync(require.resolve(getConfigFileName()));\n const logger = toolsLogger(config.log);\n // @ts-expect-error todo adjust logger type\n let fileName = logger.getFileName();\n if (fileName) {\n let lines = fs.readFileSync(fileName).toString('utf-8').split('\\n');\n lines = lines.filter(line => line);\n if (lines.length > count) {\n lines.splice(0, lines.length - count);\n }\n let regex: RegExp;\n if (adapterName) {\n //2019-03-02 13:26:54.698 - debug: iot.0 [ALEXA] Created ALEXA device: Bad.Hauptlicht.Aktor.STATE [\"turnOn\",\"turnOff\"]\n regex = new RegExp(`: ${adapterName}\\\\.`);\n options.regex = regex;\n }\n lines.forEach(line => {\n if (regex && !regex.test(line)) {\n return;\n }\n console.log(line);\n });\n\n if (watch) {\n fileName = fileName.replace(/\\\\/g, '/');\n const parts = fileName.split('/');\n parts.pop();\n chokidar\n .watch(`${parts.join('/')}/iobroker*`, {\n awaitWriteFinish: { stabilityThreshold: 500 },\n followSymlinks: false,\n })\n .on('all', this.watchHandler.bind(this, options))\n .on('ready', () => (this.isReady = true));\n }\n } else {\n console.log('No log file found');\n }\n }\n\n /**\n * Called by chokidar when watched files change\n *\n * @param options some options\n * @param event The type of change\n * @param path Which path has changed\n * @param stats Information about the file\n * @param stats.size The current size of the file in bytes\n */\n watchHandler(\n options: CLILogsOptions,\n event: string,\n path: string,\n stats?: {\n size: number;\n },\n ): void {\n if (!stats) {\n return;\n }\n if (event === 'add' || !this.fileSizes.has(path)) {\n this.fileSizes.set(path, stats.size);\n if (stats.size > 0 && (this.isReady || (options.complete && this.isTodaysLogfile(path)))) {\n this.streamChange(path, 0, options);\n }\n } else if (event === 'change') {\n const oldFileSize = this.fileSizes.get(path)!;\n this.fileSizes.set(path, stats.size);\n if (this.isReady && stats.size > oldFileSize) {\n this.streamChange(path, oldFileSize, options);\n }\n } else if (event === 'unlink') {\n this.fileSizes.delete(path);\n }\n }\n\n /**\n * If the log file belongs to today\n *\n * @param path The log file path\n */\n isTodaysLogfile(path: string): boolean {\n const YYYYMMDDDate = new Date().toJSON().slice(0, 10);\n return path.includes(YYYYMMDDDate);\n }\n\n /**\n * Streams a portion of a file to the console\n *\n * @param path The file to stream\n * @param start The offset in bytes where to start\n * @param options some options\n */\n streamChange(path: string, start: number, options: CLILogsOptions): void {\n const input = fs.createReadStream(path, {\n encoding: 'utf8',\n start,\n autoClose: true,\n });\n if (options.regex) {\n // Read the input line by line and only include the lines matching the filter\n input\n .pipe(es.split())\n .pipe(es.filterSync(line => options.regex!.test(line)))\n .pipe(es.mapSync((line: string) => line + os.EOL))\n .pipe(process.stdout);\n } else {\n // just pipe the input through\n tools.pipeLinewise(input, process.stdout);\n }\n }\n}\n", "export const __import_meta_url =\n typeof document === 'undefined' ? new (require('url'.replace('', '')).URL)('file:' + __filename).href :\n (document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { CLICommand, type CLICommandOptions } from './cliCommand.js';\nimport {\n tools,\n logger as toolsLogger,\n EXIT_CODES,\n LOG_LEVELS,\n isLogLevelAtLeast,\n parseLogEntryHeader,\n} from '@iobroker/js-controller-common';\nimport chokidar from 'chokidar';\nimport fs from 'fs-extra';\nimport os from 'node:os';\nimport es from 'event-stream';\nimport { createRequire } from 'node:module';\n// eslint-disable-next-line unicorn/prefer-module\nconst require = createRequire(import.meta.url || `file://${__filename}`);\n\nconst { getConfigFileName } = tools;\n\ninterface CLILogsOptions {\n /** Whether to show today's full log */\n complete?: boolean;\n /** An optional RegExp to filter by */\n regex?: RegExp;\n /** The lowest level to still show, if the output is restricted to a severity */\n minLevel?: ioBroker.LogLevel;\n}\n\n/** Command ioBroker state ... */\nexport class CLILogs extends CLICommand {\n private readonly fileSizes = new Map<string, number>();\n private isReady = false;\n\n /**\n * @param options The command options including context and parameters\n */\n constructor(options: CLICommandOptions) {\n super(options);\n }\n\n /**\n * Executes a command\n *\n * @param args The command arguments (the first is the sub-command)\n * @param params additional parsed CLI parameters\n */\n execute(args: string[], params: Record<string, any>): void {\n const adapterName = args[0];\n const watch = params.watch || params.w;\n const count = params.lines || 1_000;\n\n const options: CLILogsOptions = {\n complete: this.options.all,\n };\n\n // Optional, so calls without a level keep showing everything as before\n if (params.level !== undefined) {\n const level = String(params.level).toLowerCase();\n\n if (!tools.isLogLevel(level)) {\n console.error(`Unknown log level \"${params.level}\". Use one of: ${LOG_LEVELS.join(', ')}`);\n return void this.options.callback(EXIT_CODES.INVALID_ARGUMENTS);\n }\n\n options.minLevel = level;\n }\n\n const config = fs.readJSONSync(require.resolve(getConfigFileName()));\n const logger = toolsLogger(config.log);\n // @ts-expect-error todo adjust logger type\n let fileName = logger.getFileName();\n if (fileName) {\n let lines = fs.readFileSync(fileName).toString('utf-8').split('\\n');\n lines = lines.filter(line => line);\n if (lines.length > count) {\n lines.splice(0, lines.length - count);\n }\n let regex: RegExp;\n if (adapterName) {\n //2019-03-02 13:26:54.698 - debug: iot.0 [ALEXA] Created ALEXA device: Bad.Hauptlicht.Aktor.STATE [\"turnOn\",\"turnOff\"]\n regex = new RegExp(`: ${adapterName}\\\\.`);\n options.regex = regex;\n }\n const matches = this.createFilter(options);\n lines.forEach(line => {\n if (!matches(line)) {\n return;\n }\n console.log(line);\n });\n\n if (watch) {\n fileName = fileName.replace(/\\\\/g, '/');\n const parts = fileName.split('/');\n parts.pop();\n chokidar\n .watch(`${parts.join('/')}/iobroker*`, {\n awaitWriteFinish: { stabilityThreshold: 500 },\n followSymlinks: false,\n })\n .on('all', this.watchHandler.bind(this, options))\n .on('ready', () => (this.isReady = true));\n }\n } else {\n console.log('No log file found');\n }\n }\n\n /**\n * Called by chokidar when watched files change\n *\n * @param options some options\n * @param event The type of change\n * @param path Which path has changed\n * @param stats Information about the file\n * @param stats.size The current size of the file in bytes\n */\n watchHandler(\n options: CLILogsOptions,\n event: string,\n path: string,\n stats?: {\n size: number;\n },\n ): void {\n if (!stats) {\n return;\n }\n if (event === 'add' || !this.fileSizes.has(path)) {\n this.fileSizes.set(path, stats.size);\n if (stats.size > 0 && (this.isReady || (options.complete && this.isTodaysLogfile(path)))) {\n this.streamChange(path, 0, options);\n }\n } else if (event === 'change') {\n const oldFileSize = this.fileSizes.get(path)!;\n this.fileSizes.set(path, stats.size);\n if (this.isReady && stats.size > oldFileSize) {\n this.streamChange(path, oldFileSize, options);\n }\n } else if (event === 'unlink') {\n this.fileSizes.delete(path);\n }\n }\n\n /**\n * If the log file belongs to today\n *\n * @param path The log file path\n */\n isTodaysLogfile(path: string): boolean {\n const YYYYMMDDDate = new Date().toJSON().slice(0, 10);\n return path.includes(YYYYMMDDDate);\n }\n\n /**\n * Streams a portion of a file to the console\n *\n * @param path The file to stream\n * @param start The offset in bytes where to start\n * @param options some options\n */\n streamChange(path: string, start: number, options: CLILogsOptions): void {\n const input = fs.createReadStream(path, {\n encoding: 'utf8',\n start,\n autoClose: true,\n });\n if (options.regex || options.minLevel) {\n // Read the input line by line and only include the lines matching the filter\n input\n .pipe(es.split())\n .pipe(es.filterSync(this.createFilter(options)))\n .pipe(es.mapSync((line: string) => line + os.EOL))\n .pipe(process.stdout);\n } else {\n // just pipe the input through\n tools.pipeLinewise(input, process.stdout);\n }\n }\n\n /**\n * Create the check of log lines against the active filters, for one read of a file\n *\n * A log entry can span several lines, e.g. a stack trace, and only its first line carries the\n * level. Those follow-up lines inherit the decision made for the entry they belong to, so\n * filtering by level does not cut a stack trace in half. Which lines start an entry is decided\n * by the shared parser, the same one the host commands `getLogs` and `searchLogs` use: it takes\n * a level only where the time stamp of an entry is, so a level quoted inside a message does not\n * count as one.\n *\n * The decision belongs to one read and starts as \"not shown\". A read can begin with follow-up\n * lines - the last lines of a file, or a stream from an offset - whose entry it does not know,\n * and showing them would ignore the level. Files that are streamed at the same time do not\n * share it either.\n *\n * @param options the active filters\n */\n private createFilter(options: CLILogsOptions): (line: string) => boolean {\n let showEntry = false;\n\n return line => {\n if (options.minLevel) {\n const header = parseLogEntryHeader(line);\n\n if (header) {\n showEntry = isLogLevelAtLeast(header.level, options.minLevel);\n }\n\n if (!showEntry) {\n return false;\n }\n }\n\n return !options.regex || options.regex.test(line);\n };\n }\n}\n", "export const __import_meta_url =\n typeof document === 'undefined' ? new (require('url'.replace('', '')).URL)('file:' + __filename).href :\n (document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href)\n"],
5
+ "mappings": "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",
6
6
  "names": ["require", "fs", "toolsLogger", "chokidar", "es", "os"]
7
7
  }
@@ -0,0 +1,39 @@
1
+ import { EXIT_CODES } from '@iobroker/js-controller-common-db';
2
+ /** What is known about an adapter that is about to be installed */
3
+ export interface AdapterCompatibilityInput {
4
+ /** Content of its `io-package.json` */
5
+ ioPackage: {
6
+ common?: Partial<Pick<ioBroker.AdapterCommon, 'os' | 'nogit'>>;
7
+ } | null | undefined;
8
+ /** Content of its `package.json`, if known */
9
+ packageJson?: {
10
+ engines?: {
11
+ node?: string;
12
+ };
13
+ } | null;
14
+ /** Whether it is installed directly from GitHub (`iobroker url <github-url>`) */
15
+ fromGitHub?: boolean;
16
+ /** Operating system to check against, default `process.platform` */
17
+ platform?: string;
18
+ /** Node.js version to check against, default `process.version` */
19
+ nodeVersion?: string;
20
+ }
21
+ /** Why an adapter cannot be installed */
22
+ export interface AdapterCompatibilityProblem {
23
+ /** Exit code of the CLI */
24
+ exitCode: EXIT_CODES;
25
+ /** Message for the user */
26
+ message: string;
27
+ }
28
+ /**
29
+ * Check whether an adapter can be installed on this system: from GitHub only without `common.nogit`, only on a
30
+ * supported operating system (`common.os`) and only with a supported Node.js version (`engines.node`).
31
+ *
32
+ * The same checks run before a GitHub installation (with the files from GitHub) and before an adapter is set up
33
+ * (with the installed files).
34
+ *
35
+ * @param input the adapter files and the system to check against
36
+ * @returns the first problem found, or `null` if the adapter can be installed
37
+ */
38
+ export declare function checkAdapterCompatibility(input: AdapterCompatibilityInput): AdapterCompatibilityProblem | null;
39
+ //# sourceMappingURL=adapterCompatibility.d.ts.map
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var adapterCompatibility_exports = {};
31
+ __export(adapterCompatibility_exports, {
32
+ checkAdapterCompatibility: () => checkAdapterCompatibility
33
+ });
34
+ module.exports = __toCommonJS(adapterCompatibility_exports);
35
+ var import_semver = __toESM(require("semver"), 1);
36
+ var import_js_controller_common_db = require("@iobroker/js-controller-common-db");
37
+ function checkAdapterCompatibility(input) {
38
+ const common = input.ioPackage?.common;
39
+ const platform = input.platform ?? process.platform;
40
+ const nodeVersion = (input.nodeVersion ?? process.version).replace(/^v/, "");
41
+ if (input.fromGitHub && common?.nogit === true) {
42
+ return {
43
+ exitCode: import_js_controller_common_db.EXIT_CODES.CANNOT_INSTALL_NPM_PACKET,
44
+ message: 'Adapter cannot be installed from GitHub ("nogit" is set in io-package.json). Install it from the repository or from npm instead'
45
+ };
46
+ }
47
+ const os = common?.os;
48
+ if (typeof os === "string" && os !== platform) {
49
+ return {
50
+ exitCode: import_js_controller_common_db.EXIT_CODES.INVALID_OS,
51
+ message: `Adapter does not support current os. Required ${os}. Actual platform: ${platform}`
52
+ };
53
+ }
54
+ if (Array.isArray(os) && !os.includes(platform)) {
55
+ return {
56
+ exitCode: import_js_controller_common_db.EXIT_CODES.INVALID_OS,
57
+ message: `Adapter does not support current os. Required one of ${os.join(", ")}. Actual platform: ${platform}`
58
+ };
59
+ }
60
+ const engine = input.packageJson?.engines?.node;
61
+ if (engine && !import_semver.default.satisfies(nodeVersion, engine)) {
62
+ return {
63
+ exitCode: import_js_controller_common_db.EXIT_CODES.INVALID_NODE_VERSION,
64
+ message: `Adapter does not support current nodejs version. Required ${engine}. Actual version: v${nodeVersion}`
65
+ };
66
+ }
67
+ return null;
68
+ }
69
+ __name(checkAdapterCompatibility, "checkAdapterCompatibility");
70
+ // Annotate the CommonJS export names for ESM import in node:
71
+ 0 && (module.exports = {
72
+ checkAdapterCompatibility
73
+ });
74
+ //# sourceMappingURL=adapterCompatibility.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/lib/setup/adapterCompatibility.ts"],
4
+ "sourcesContent": ["import semver from 'semver';\nimport { EXIT_CODES } from '@iobroker/js-controller-common-db';\n\n/** What is known about an adapter that is about to be installed */\nexport interface AdapterCompatibilityInput {\n /** Content of its `io-package.json` */\n ioPackage: { common?: Partial<Pick<ioBroker.AdapterCommon, 'os' | 'nogit'>> } | null | undefined;\n /** Content of its `package.json`, if known */\n packageJson?: { engines?: { node?: string } } | null;\n /** Whether it is installed directly from GitHub (`iobroker url <github-url>`) */\n fromGitHub?: boolean;\n /** Operating system to check against, default `process.platform` */\n platform?: string;\n /** Node.js version to check against, default `process.version` */\n nodeVersion?: string;\n}\n\n/** Why an adapter cannot be installed */\nexport interface AdapterCompatibilityProblem {\n /** Exit code of the CLI */\n exitCode: EXIT_CODES;\n /** Message for the user */\n message: string;\n}\n\n/**\n * Check whether an adapter can be installed on this system: from GitHub only without `common.nogit`, only on a\n * supported operating system (`common.os`) and only with a supported Node.js version (`engines.node`).\n *\n * The same checks run before a GitHub installation (with the files from GitHub) and before an adapter is set up\n * (with the installed files).\n *\n * @param input the adapter files and the system to check against\n * @returns the first problem found, or `null` if the adapter can be installed\n */\nexport function checkAdapterCompatibility(input: AdapterCompatibilityInput): AdapterCompatibilityProblem | null {\n const common = input.ioPackage?.common;\n const platform = input.platform ?? process.platform;\n const nodeVersion = (input.nodeVersion ?? process.version).replace(/^v/, '');\n\n if (input.fromGitHub && common?.nogit === true) {\n return {\n exitCode: EXIT_CODES.CANNOT_INSTALL_NPM_PACKET,\n message:\n 'Adapter cannot be installed from GitHub (\"nogit\" is set in io-package.json). Install it from the repository or from npm instead',\n };\n }\n\n const os = common?.os;\n if (typeof os === 'string' && os !== platform) {\n return {\n exitCode: EXIT_CODES.INVALID_OS,\n message: `Adapter does not support current os. Required ${os}. Actual platform: ${platform}`,\n };\n }\n if (Array.isArray(os) && !(os as string[]).includes(platform)) {\n return {\n exitCode: EXIT_CODES.INVALID_OS,\n message: `Adapter does not support current os. Required one of ${os.join(', ')}. Actual platform: ${platform}`,\n };\n }\n\n const engine = input.packageJson?.engines?.node;\n if (engine && !semver.satisfies(nodeVersion, engine)) {\n return {\n exitCode: EXIT_CODES.INVALID_NODE_VERSION,\n message: `Adapter does not support current nodejs version. Required ${engine}. Actual version: v${nodeVersion}`,\n };\n }\n\n return null;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;AAAA,oBAAmB;AACnB,qCAA2B;AAkCrB,SAAU,0BAA0B,OAAgC;AACtE,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,WAAW,MAAM,YAAY,QAAQ;AAC3C,QAAM,eAAe,MAAM,eAAe,QAAQ,SAAS,QAAQ,MAAM,EAAE;AAE3E,MAAI,MAAM,cAAc,QAAQ,UAAU,MAAM;AAC5C,WAAO;MACH,UAAU,0CAAW;MACrB,SACI;;EAEZ;AAEA,QAAM,KAAK,QAAQ;AACnB,MAAI,OAAO,OAAO,YAAY,OAAO,UAAU;AAC3C,WAAO;MACH,UAAU,0CAAW;MACrB,SAAS,iDAAiD,EAAE,sBAAsB,QAAQ;;EAElG;AACA,MAAI,MAAM,QAAQ,EAAE,KAAK,CAAE,GAAgB,SAAS,QAAQ,GAAG;AAC3D,WAAO;MACH,UAAU,0CAAW;MACrB,SAAS,wDAAwD,GAAG,KAAK,IAAI,CAAC,sBAAsB,QAAQ;;EAEpH;AAEA,QAAM,SAAS,MAAM,aAAa,SAAS;AAC3C,MAAI,UAAU,CAAC,cAAAA,QAAO,UAAU,aAAa,MAAM,GAAG;AAClD,WAAO;MACH,UAAU,0CAAW;MACrB,SAAS,6DAA6D,MAAM,sBAAsB,WAAW;;EAErH;AAEA,SAAO;AACX;AApCgB;",
6
+ "names": ["semver"]
7
+ }
@@ -204,6 +204,21 @@ export declare class Install {
204
204
  * @param adapter adapter name
205
205
  */
206
206
  deleteAdapter(adapter: string): Promise<EXIT_CODES>;
207
+ /**
208
+ * Remove the virtual environment a Python adapter leaves behind in the data directory
209
+ *
210
+ * Host-local state like `node_modules` - rebuildable, but easily a few hundred megabytes - so it goes when
211
+ * the adapter goes. Deliberately not part of the npm uninstall: that one starts by resolving the adapter's
212
+ * `io-package.json`, so for a half-removed installation, where the package directory is already gone, it
213
+ * throws before ever getting here - and that is precisely the case which leaves the environment behind with
214
+ * nothing pointing at it.
215
+ *
216
+ * Removed without looking at `common.platform` for the same reason: the directory only exists for Python
217
+ * adapters, and the `io-package.json` that would say so may no longer be there.
218
+ *
219
+ * @param adapter adapter name, e.g. "pyexample"
220
+ */
221
+ private _removePythonEnvironment;
207
222
  /**
208
223
  * Deletes given instance of an adapter
209
224
  *
@@ -211,6 +226,21 @@ export declare class Install {
211
226
  * @param instance e.g. 1, if undefined deletes all instances
212
227
  */
213
228
  deleteInstance(adapter: string, instance?: number): Promise<void | EXIT_CODES.CANNOT_DELETE_DEPENDENCY>;
229
+ /**
230
+ * Free all exclusive resources (serial ports, TCP/UDP ports, ...) the given instance(s) had registered.
231
+ *
232
+ * This is needed because an instance can be deleted via the CLI while a js-controller is not running: it
233
+ * cannot notice that the instance object disappeared, so its `system.host.<host>.usedResources.<type>`
234
+ * states would keep listing the resources of an instance that no longer exists.
235
+ *
236
+ * Hosts that are running are deliberately skipped. Such a host cleans its own registry up when it sees the
237
+ * instance object being deleted, and it holds the registry in memory: it rewrites the state from that copy
238
+ * on its next change, which would silently undo a write made here.
239
+ *
240
+ * @param adapter adapter name, e.g. "mqtt"
241
+ * @param instance instance number; if undefined, all instances of the adapter are freed
242
+ */
243
+ private _freeUsedResources;
214
244
  /**
215
245
  * Remove all node modules that has been installed by this instance
216
246
  *
@@ -224,6 +254,29 @@ export declare class Install {
224
254
  * @param ids - id of the adapter/instance to check for
225
255
  */
226
256
  private _removeCustomFromObjects;
257
+ /**
258
+ * Read a JSON file of a GitHub repository at the given commit
259
+ *
260
+ * @param user GitHub user or organization
261
+ * @param repo repository name
262
+ * @param commit commit hash, branch or tag
263
+ * @param fileName file in the root of the repository
264
+ * @returns the parsed file, or `null` if it cannot be read
265
+ */
266
+ private _readGitHubJson;
267
+ /**
268
+ * Check an adapter on GitHub before it is installed from there: `common.nogit`, the operating system and the
269
+ * Node.js version, from its `io-package.json` and `package.json` at the commit to be installed
270
+ *
271
+ * Without these checks the adapter would be installed first and fail later, e.g. because files that only the
272
+ * npm package contains are missing.
273
+ *
274
+ * @param user GitHub user or organization
275
+ * @param repo repository name
276
+ * @param commit commit hash, branch or tag; without it the default branch, which npm installs then as well
277
+ * @returns the problem that prevents the installation, or `null`
278
+ */
279
+ private _checkGitHubAdapter;
227
280
  /**
228
281
  * Installs an adapter from given url
229
282
  *