@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.
- package/build/cjs/index.js +3 -3
- package/build/cjs/lib/_Types.d.ts +8 -1
- package/build/cjs/lib/cli/cliCert.d.ts +7 -4
- package/build/cjs/lib/cli/cliCert.js +10 -6
- package/build/cjs/lib/cli/cliCert.js.map +2 -2
- package/build/cjs/lib/cli/cliCommand.d.ts +63 -15
- package/build/cjs/lib/cli/cliCommand.js +8 -1
- package/build/cjs/lib/cli/cliCommand.js.map +2 -2
- package/build/cjs/lib/cli/cliCompact.d.ts +5 -2
- package/build/cjs/lib/cli/cliCompact.js +9 -2
- package/build/cjs/lib/cli/cliCompact.js.map +2 -2
- package/build/cjs/lib/cli/cliDebug.d.ts +5 -2
- package/build/cjs/lib/cli/cliDebug.js +8 -1
- package/build/cjs/lib/cli/cliDebug.js.map +2 -2
- package/build/cjs/lib/cli/cliHost.d.ts +13 -10
- package/build/cjs/lib/cli/cliHost.js +13 -5
- package/build/cjs/lib/cli/cliHost.js.map +2 -2
- package/build/cjs/lib/cli/cliLogs.d.ts +9 -3
- package/build/cjs/lib/cli/cliLogs.js +12 -1
- package/build/cjs/lib/cli/cliLogs.js.map +2 -2
- package/build/cjs/lib/cli/cliMessage.d.ts +2 -1
- package/build/cjs/lib/cli/cliMessage.js +5 -0
- package/build/cjs/lib/cli/cliMessage.js.map +2 -2
- package/build/cjs/lib/cli/cliObjects.d.ts +21 -18
- package/build/cjs/lib/cli/cliObjects.js +51 -33
- package/build/cjs/lib/cli/cliObjects.js.map +2 -2
- package/build/cjs/lib/cli/cliPlugin.d.ts +3 -3
- package/build/cjs/lib/cli/cliPlugin.js +6 -0
- package/build/cjs/lib/cli/cliPlugin.js.map +2 -2
- package/build/cjs/lib/cli/cliProcess.d.ts +17 -7
- package/build/cjs/lib/cli/cliProcess.js +77 -24
- package/build/cjs/lib/cli/cliProcess.js.map +3 -3
- package/build/cjs/lib/cli/cliStates.d.ts +7 -4
- package/build/cjs/lib/cli/cliStates.js +14 -6
- package/build/cjs/lib/cli/cliStates.js.map +2 -2
- package/build/cjs/lib/cli/cliTools.js +11 -0
- package/build/cjs/lib/cli/cliTools.js.map +1 -1
- package/build/cjs/lib/cli/messages.js +47 -46
- package/build/cjs/lib/cli/messages.js.map +1 -1
- package/build/cjs/lib/progressBar.d.ts +59 -0
- package/build/cjs/lib/progressBar.js +115 -0
- package/build/cjs/lib/progressBar.js.map +7 -0
- package/build/cjs/lib/setup/customError.d.ts +4 -0
- package/build/cjs/lib/setup/customError.js +7 -0
- package/build/cjs/lib/setup/customError.js.map +2 -2
- package/build/cjs/lib/setup/dbConnection.js +69 -64
- package/build/cjs/lib/setup/dbConnection.js.map +3 -3
- package/build/cjs/lib/setup/formatters.d.ts +4 -4
- package/build/cjs/lib/setup/formatters.js +5 -0
- package/build/cjs/lib/setup/formatters.js.map +2 -2
- package/build/cjs/lib/setup/multihostClient.js +6 -2
- package/build/cjs/lib/setup/multihostClient.js.map +1 -1
- package/build/cjs/lib/setup/pluginInfos.d.ts +5 -0
- package/build/cjs/lib/setup/pluginInfos.js +2 -0
- package/build/cjs/lib/setup/pluginInfos.js.map +2 -2
- package/build/cjs/lib/setup/setupBackup.d.ts +53 -0
- package/build/cjs/lib/setup/setupBackup.js +125 -14
- package/build/cjs/lib/setup/setupBackup.js.map +3 -3
- package/build/cjs/lib/setup/setupInstall.d.ts +66 -15
- package/build/cjs/lib/setup/setupInstall.js +282 -28
- package/build/cjs/lib/setup/setupInstall.js.map +2 -2
- package/build/cjs/lib/setup/setupLicense.d.ts +13 -0
- package/build/cjs/lib/setup/setupLicense.js +33 -2
- package/build/cjs/lib/setup/setupLicense.js.map +2 -2
- package/build/cjs/lib/setup/setupList.d.ts +55 -1
- package/build/cjs/lib/setup/setupList.js +78 -24
- package/build/cjs/lib/setup/setupList.js.map +3 -3
- package/build/cjs/lib/setup/setupMultihost.d.ts +7 -0
- package/build/cjs/lib/setup/setupMultihost.js +78 -11
- package/build/cjs/lib/setup/setupMultihost.js.map +3 -3
- package/build/cjs/lib/setup/setupPacketManager.d.ts +10 -0
- package/build/cjs/lib/setup/setupPacketManager.js +16 -6
- package/build/cjs/lib/setup/setupPacketManager.js.map +2 -2
- package/build/cjs/lib/setup/setupRepo.d.ts +19 -0
- package/build/cjs/lib/setup/setupRepo.js +141 -13
- package/build/cjs/lib/setup/setupRepo.js.map +2 -2
- package/build/cjs/lib/setup/setupSetup.d.ts +34 -0
- package/build/cjs/lib/setup/setupSetup.js +209 -35
- package/build/cjs/lib/setup/setupSetup.js.map +3 -3
- package/build/cjs/lib/setup/setupUpgrade.d.ts +13 -2
- package/build/cjs/lib/setup/setupUpgrade.js +72 -12
- package/build/cjs/lib/setup/setupUpgrade.js.map +2 -2
- package/build/cjs/lib/setup/setupUpload.d.ts +77 -1
- package/build/cjs/lib/setup/setupUpload.js +152 -9
- package/build/cjs/lib/setup/setupUpload.js.map +2 -2
- package/build/cjs/lib/setup/setupUsers.d.ts +44 -14
- package/build/cjs/lib/setup/setupUsers.js +330 -17
- package/build/cjs/lib/setup/setupUsers.js.map +2 -2
- package/build/cjs/lib/setup/setupVendor.d.ts +14 -1
- package/build/cjs/lib/setup/setupVendor.js +40 -8
- package/build/cjs/lib/setup/setupVendor.js.map +2 -2
- package/build/cjs/lib/setup/setupVisDebug.d.ts +16 -2
- package/build/cjs/lib/setup/setupVisDebug.js +41 -17
- package/build/cjs/lib/setup/setupVisDebug.js.map +3 -3
- package/build/cjs/lib/setup/utils.d.ts +1 -1
- package/build/cjs/lib/setup/utils.js +13 -9
- package/build/cjs/lib/setup/utils.js.map +3 -3
- package/build/cjs/lib/setup.d.ts +1 -1
- package/build/cjs/lib/setup.js +858 -1758
- package/build/cjs/lib/setup.js.map +3 -3
- package/build/esm/lib/_Types.d.ts +8 -1
- package/build/esm/lib/_Types.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCert.d.ts +7 -4
- package/build/esm/lib/cli/cliCert.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCert.js +6 -6
- package/build/esm/lib/cli/cliCert.js.map +1 -1
- package/build/esm/lib/cli/cliCommand.d.ts +63 -15
- package/build/esm/lib/cli/cliCommand.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCommand.js +4 -1
- package/build/esm/lib/cli/cliCommand.js.map +1 -1
- package/build/esm/lib/cli/cliCompact.d.ts +5 -2
- package/build/esm/lib/cli/cliCompact.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCompact.js +5 -2
- package/build/esm/lib/cli/cliCompact.js.map +1 -1
- package/build/esm/lib/cli/cliDebug.d.ts +5 -2
- package/build/esm/lib/cli/cliDebug.d.ts.map +1 -1
- package/build/esm/lib/cli/cliDebug.js +4 -1
- package/build/esm/lib/cli/cliDebug.js.map +1 -1
- package/build/esm/lib/cli/cliHost.d.ts +13 -10
- package/build/esm/lib/cli/cliHost.d.ts.map +1 -1
- package/build/esm/lib/cli/cliHost.js +8 -5
- package/build/esm/lib/cli/cliHost.js.map +1 -1
- package/build/esm/lib/cli/cliLogs.d.ts +9 -3
- package/build/esm/lib/cli/cliLogs.d.ts.map +1 -1
- package/build/esm/lib/cli/cliLogs.js +8 -1
- package/build/esm/lib/cli/cliLogs.js.map +1 -1
- package/build/esm/lib/cli/cliMessage.d.ts +2 -1
- package/build/esm/lib/cli/cliMessage.d.ts.map +1 -1
- package/build/esm/lib/cli/cliMessage.js +1 -0
- package/build/esm/lib/cli/cliMessage.js.map +1 -1
- package/build/esm/lib/cli/cliObjects.d.ts +21 -18
- package/build/esm/lib/cli/cliObjects.d.ts.map +1 -1
- package/build/esm/lib/cli/cliObjects.js +44 -38
- package/build/esm/lib/cli/cliObjects.js.map +1 -1
- package/build/esm/lib/cli/cliPlugin.d.ts +3 -3
- package/build/esm/lib/cli/cliPlugin.d.ts.map +1 -1
- package/build/esm/lib/cli/cliPlugin.js +1 -1
- package/build/esm/lib/cli/cliPlugin.js.map +1 -1
- package/build/esm/lib/cli/cliProcess.d.ts +17 -7
- package/build/esm/lib/cli/cliProcess.d.ts.map +1 -1
- package/build/esm/lib/cli/cliProcess.js +73 -12
- package/build/esm/lib/cli/cliProcess.js.map +1 -1
- package/build/esm/lib/cli/cliStates.d.ts +7 -4
- package/build/esm/lib/cli/cliStates.d.ts.map +1 -1
- package/build/esm/lib/cli/cliStates.js +6 -2
- package/build/esm/lib/cli/cliStates.js.map +1 -1
- package/build/esm/lib/progressBar.d.ts +59 -0
- package/build/esm/lib/progressBar.d.ts.map +1 -0
- package/build/esm/lib/progressBar.js +104 -0
- package/build/esm/lib/progressBar.js.map +1 -0
- package/build/esm/lib/setup/customError.d.ts +4 -0
- package/build/esm/lib/setup/customError.d.ts.map +1 -1
- package/build/esm/lib/setup/customError.js +3 -0
- package/build/esm/lib/setup/customError.js.map +1 -1
- package/build/esm/lib/setup/dbConnection.d.ts.map +1 -1
- package/build/esm/lib/setup/dbConnection.js +10 -13
- package/build/esm/lib/setup/dbConnection.js.map +1 -1
- package/build/esm/lib/setup/formatters.d.ts +4 -4
- package/build/esm/lib/setup/formatters.js +4 -4
- package/build/esm/lib/setup/pluginInfos.d.ts +5 -0
- package/build/esm/lib/setup/pluginInfos.d.ts.map +1 -1
- package/build/esm/lib/setup/pluginInfos.js +5 -0
- package/build/esm/lib/setup/pluginInfos.js.map +1 -1
- package/build/esm/lib/setup/setupBackup.d.ts +53 -0
- package/build/esm/lib/setup/setupBackup.d.ts.map +1 -1
- package/build/esm/lib/setup/setupBackup.js +132 -13
- package/build/esm/lib/setup/setupBackup.js.map +1 -1
- package/build/esm/lib/setup/setupInstall.d.ts +66 -15
- package/build/esm/lib/setup/setupInstall.d.ts.map +1 -1
- package/build/esm/lib/setup/setupInstall.js +309 -23
- package/build/esm/lib/setup/setupInstall.js.map +1 -1
- package/build/esm/lib/setup/setupLicense.d.ts +13 -0
- package/build/esm/lib/setup/setupLicense.d.ts.map +1 -1
- package/build/esm/lib/setup/setupLicense.js +31 -1
- package/build/esm/lib/setup/setupLicense.js.map +1 -1
- package/build/esm/lib/setup/setupList.d.ts +55 -1
- package/build/esm/lib/setup/setupList.d.ts.map +1 -1
- package/build/esm/lib/setup/setupList.js +61 -8
- package/build/esm/lib/setup/setupList.js.map +1 -1
- package/build/esm/lib/setup/setupMultihost.d.ts +7 -0
- package/build/esm/lib/setup/setupMultihost.d.ts.map +1 -1
- package/build/esm/lib/setup/setupMultihost.js +85 -6
- package/build/esm/lib/setup/setupMultihost.js.map +1 -1
- package/build/esm/lib/setup/setupPacketManager.d.ts +10 -0
- package/build/esm/lib/setup/setupPacketManager.d.ts.map +1 -1
- package/build/esm/lib/setup/setupPacketManager.js +9 -0
- package/build/esm/lib/setup/setupPacketManager.js.map +1 -1
- package/build/esm/lib/setup/setupRepo.d.ts +19 -0
- package/build/esm/lib/setup/setupRepo.d.ts.map +1 -1
- package/build/esm/lib/setup/setupRepo.js +164 -14
- package/build/esm/lib/setup/setupRepo.js.map +1 -1
- package/build/esm/lib/setup/setupSetup.d.ts +34 -0
- package/build/esm/lib/setup/setupSetup.d.ts.map +1 -1
- package/build/esm/lib/setup/setupSetup.js +218 -21
- package/build/esm/lib/setup/setupSetup.js.map +1 -1
- package/build/esm/lib/setup/setupUpgrade.d.ts +13 -2
- package/build/esm/lib/setup/setupUpgrade.d.ts.map +1 -1
- package/build/esm/lib/setup/setupUpgrade.js +70 -6
- package/build/esm/lib/setup/setupUpgrade.js.map +1 -1
- package/build/esm/lib/setup/setupUpload.d.ts +77 -1
- package/build/esm/lib/setup/setupUpload.d.ts.map +1 -1
- package/build/esm/lib/setup/setupUpload.js +164 -7
- package/build/esm/lib/setup/setupUpload.js.map +1 -1
- package/build/esm/lib/setup/setupUsers.d.ts +44 -14
- package/build/esm/lib/setup/setupUsers.d.ts.map +1 -1
- package/build/esm/lib/setup/setupUsers.js +346 -14
- package/build/esm/lib/setup/setupUsers.js.map +1 -1
- package/build/esm/lib/setup/setupVendor.d.ts +14 -1
- package/build/esm/lib/setup/setupVendor.d.ts.map +1 -1
- package/build/esm/lib/setup/setupVendor.js +33 -2
- package/build/esm/lib/setup/setupVendor.js.map +1 -1
- package/build/esm/lib/setup/setupVisDebug.d.ts +16 -2
- package/build/esm/lib/setup/setupVisDebug.d.ts.map +1 -1
- package/build/esm/lib/setup/setupVisDebug.js +39 -14
- package/build/esm/lib/setup/setupVisDebug.js.map +1 -1
- package/build/esm/lib/setup/utils.d.ts +1 -1
- package/build/esm/lib/setup/utils.d.ts.map +1 -1
- package/build/esm/lib/setup/utils.js +2 -4
- package/build/esm/lib/setup/utils.js.map +1 -1
- package/build/esm/lib/setup.d.ts +1 -1
- package/build/esm/lib/setup.d.ts.map +1 -1
- package/build/esm/lib/setup.js +959 -1910
- package/build/esm/lib/setup.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +14 -14
|
@@ -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 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": "
|
|
6
|
-
"names": ["
|
|
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 { isLocalObjectsDbServer, isLocalStatesDbServer, tools, EXIT_CODES } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';\nimport { MHClient, type BrowseResultEntry } from './multihostClient.js';\nimport type { ProcessCommandOptions } from '@/lib/cli/cliCommand.js';\nimport { dbConnect } from '@/lib/setup/dbConnection.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).catch(e =>\n console.error(`Cannot show multihost state: ${e.message}`),\n );\n callback();\n });\n }\n } else {\n callback(new Error('No secret phrase entered!'));\n }\n });\n } else {\n this.showMHState(config, changed).catch(e =>\n console.error(`Cannot show multihost state: ${e.message}`),\n );\n callback();\n }\n } else {\n this.showMHState(config, changed).catch(e => console.error(`Cannot show multihost state: ${e.message}`));\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).catch(e => console.error(`Cannot show multihost state: ${e.message}`));\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\n/**\n * Handles the `multihost` / `mh` CLI command.\n *\n * @param options the process command options\n */\nexport function processCommandMultihost(options: ProcessCommandOptions): void {\n const { args, params, callback } = options;\n\n const cmd = args[0];\n if (\n cmd !== 'c' &&\n cmd !== 'connect' &&\n cmd !== 's' &&\n cmd !== 'status' &&\n cmd !== 'b' &&\n cmd !== 'browse' &&\n cmd !== 'e' &&\n cmd !== 'enable' &&\n cmd !== 'd' &&\n cmd !== 'disable'\n ) {\n console.log('Invalid parameters. Following is possible: enable, browse, connect, status');\n return void callback(EXIT_CODES.INVALID_ARGUMENTS);\n }\n dbConnect(params, async ({ objects, states }) => {\n const mh = new Multihost({\n params,\n objects,\n });\n\n if (cmd === 's' || cmd === 'status') {\n mh.status();\n return void callback();\n } else if (cmd === 'b' || cmd === 'browse') {\n try {\n const list = await mh.browse();\n mh.showHosts(list);\n return void callback();\n } catch (e) {\n console.error(e.message);\n return void callback(EXIT_CODES.CANNOT_CREATE_USER_OR_GROUP);\n }\n } else if (cmd === 'e' || cmd === 'enable') {\n mh.enable(true, async (err: Error | null | undefined) => {\n if (err) {\n console.error(err);\n return void callback(EXIT_CODES.CANNOT_ENABLE_MULTIHOST);\n }\n await states.pushMessage(`system.host.${tools.getHostName()}`, {\n command: 'updateMultihost',\n message: null,\n from: 'setup',\n });\n\n callback();\n });\n } else if (cmd === 'd' || cmd === 'disable') {\n mh.enable(false, async (err: Error | null | undefined) => {\n if (err) {\n console.error(err);\n return void callback(EXIT_CODES.CANNOT_ENABLE_MULTIHOST);\n }\n await states.pushMessage(`system.host.${tools.getHostName()}`, {\n command: 'updateMultihost',\n message: null,\n from: 'setup',\n });\n\n callback();\n });\n } else if (cmd === 'c' || cmd === 'connect') {\n mh.connect(parseInt(args[1]), args[2], (err: Error | null | undefined) => {\n if (err) {\n console.error(err);\n }\n return void callback(err ? 1 : 0);\n }).catch(e => console.error(`Cannot connect multihost: ${e.message}`));\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["fs", "path", "prompt", "_err", "readlineSync", "readline"]
|
|
7
7
|
}
|
|
@@ -16,12 +16,16 @@ interface PacketManagerOptions {
|
|
|
16
16
|
manager?: Manager;
|
|
17
17
|
logger?: Logger;
|
|
18
18
|
}
|
|
19
|
+
/** Describes a system packet that should be upgraded */
|
|
19
20
|
export interface UpgradePacket {
|
|
20
21
|
/** Name of the packet which should be upgraded */
|
|
21
22
|
name: string;
|
|
22
23
|
/** Optional version */
|
|
23
24
|
version?: string;
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Wrapper around the system packet manager (apt or yum) to query and upgrade system packages
|
|
28
|
+
*/
|
|
25
29
|
export declare class PacketManager {
|
|
26
30
|
private manager;
|
|
27
31
|
private readonly logger;
|
|
@@ -29,9 +33,15 @@ export declare class PacketManager {
|
|
|
29
33
|
private sudo;
|
|
30
34
|
private readonly _readyPromise;
|
|
31
35
|
private readonly COMMANDS;
|
|
36
|
+
/**
|
|
37
|
+
* @param options The packet manager to use, a logger and the log level
|
|
38
|
+
*/
|
|
32
39
|
constructor(options?: PacketManagerOptions);
|
|
33
40
|
/** Starts the initialization process */
|
|
34
41
|
private _init;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve once the packet manager has finished its asynchronous initialization
|
|
44
|
+
*/
|
|
35
45
|
ready(): Promise<void>;
|
|
36
46
|
/**
|
|
37
47
|
* Tests if the given command can be executed
|
|
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
7
|
var __export = (target, all) => {
|
|
7
8
|
for (var name in all)
|
|
8
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -32,6 +33,9 @@ var LOG_LEVELS;
|
|
|
32
33
|
LOG_LEVELS2[LOG_LEVELS2["error"] = 0] = "error";
|
|
33
34
|
})(LOG_LEVELS || (LOG_LEVELS = {}));
|
|
34
35
|
class PacketManager {
|
|
36
|
+
static {
|
|
37
|
+
__name(this, "PacketManager");
|
|
38
|
+
}
|
|
35
39
|
manager;
|
|
36
40
|
logger;
|
|
37
41
|
dpkg;
|
|
@@ -43,15 +47,18 @@ class PacketManager {
|
|
|
43
47
|
yum: "check-update"
|
|
44
48
|
}
|
|
45
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* @param options The packet manager to use, a logger and the log level
|
|
52
|
+
*/
|
|
46
53
|
constructor(options = { logLevel: LOG_LEVELS.info }) {
|
|
47
54
|
this.manager = options?.manager || "";
|
|
48
55
|
this.logger = options?.logger || {
|
|
49
|
-
silly: (text) => options.logLevel >= LOG_LEVELS.silly && console.log(text),
|
|
50
|
-
info: (text) => options.logLevel >= LOG_LEVELS.info && console.log(text),
|
|
51
|
-
log: (text) => options.logLevel >= LOG_LEVELS.log && console.log(text),
|
|
52
|
-
warn: (text) => options.logLevel >= LOG_LEVELS.warn && console.warn(text),
|
|
53
|
-
error: (text) => options.logLevel >= LOG_LEVELS.error && console.error(text),
|
|
54
|
-
debug: (text) => options.logLevel >= LOG_LEVELS.debug && console.log(text)
|
|
56
|
+
silly: /* @__PURE__ */ __name((text) => options.logLevel >= LOG_LEVELS.silly && console.log(text), "silly"),
|
|
57
|
+
info: /* @__PURE__ */ __name((text) => options.logLevel >= LOG_LEVELS.info && console.log(text), "info"),
|
|
58
|
+
log: /* @__PURE__ */ __name((text) => options.logLevel >= LOG_LEVELS.log && console.log(text), "log"),
|
|
59
|
+
warn: /* @__PURE__ */ __name((text) => options.logLevel >= LOG_LEVELS.warn && console.warn(text), "warn"),
|
|
60
|
+
error: /* @__PURE__ */ __name((text) => options.logLevel >= LOG_LEVELS.error && console.error(text), "error"),
|
|
61
|
+
debug: /* @__PURE__ */ __name((text) => options.logLevel >= LOG_LEVELS.debug && console.log(text), "debug")
|
|
55
62
|
};
|
|
56
63
|
this.dpkg = false;
|
|
57
64
|
this.sudo = false;
|
|
@@ -71,6 +78,9 @@ class PacketManager {
|
|
|
71
78
|
this.logger.debug(`Detected dpkg: ${this.dpkg}`);
|
|
72
79
|
}
|
|
73
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolve once the packet manager has finished its asynchronous initialization
|
|
83
|
+
*/
|
|
74
84
|
ready() {
|
|
75
85
|
return this._readyPromise;
|
|
76
86
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/setup/setupPacketManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { execAsync, type InternalLogger } from '@iobroker/js-controller-common-db/tools';\n\nenum LOG_LEVELS {\n silly = 5,\n debug = 4,\n log = 3,\n info = 2,\n warn = 1,\n error = 0,\n}\n\ninterface Logger extends InternalLogger {\n log(message: string): void;\n}\n\ntype Manager = 'apt' | 'yum' | '';\n\ninterface PacketManagerOptions {\n logLevel: LOG_LEVELS;\n manager?: Manager;\n logger?: Logger;\n}\n\nexport interface UpgradePacket {\n /** Name of the packet which should be upgraded */\n name: string;\n /** Optional version */\n version?: string;\n}\n\nexport class PacketManager {\n private manager: Manager;\n private readonly logger: Logger;\n private dpkg: boolean;\n private sudo: boolean;\n private readonly _readyPromise: Promise<void>;\n private readonly COMMANDS = {\n listUpgradeable: {\n apt: 'list --upgradeable',\n yum: 'check-update',\n },\n } as const;\n\n constructor(options: PacketManagerOptions = { logLevel: LOG_LEVELS.info }) {\n // detect apt or yum\n this.manager = options?.manager || '';\n this.logger = options?.logger || {\n silly: text => options.logLevel >= LOG_LEVELS.silly && console.log(text),\n info: text => options.logLevel >= LOG_LEVELS.info && console.log(text),\n log: text => options.logLevel >= LOG_LEVELS.log && console.log(text),\n warn: text => options.logLevel >= LOG_LEVELS.warn && console.warn(text),\n error: text => options.logLevel >= LOG_LEVELS.error && console.error(text),\n debug: text => options.logLevel >= LOG_LEVELS.debug && console.log(text),\n };\n this.dpkg = false;\n this.sudo = false;\n this._readyPromise = this._init();\n }\n\n /** Starts the initialization process */\n private async _init(): Promise<void> {\n if (process.platform !== 'win32') {\n if (!this.manager) {\n const manager = await this._detectManager();\n if (manager) {\n this.logger.debug(`Detected packet manager: ${manager}`);\n // Check if sudo is available for packet manager and store information\n this.sudo = (await this._isSudoAvailable()) && (await this._isSudoAvailableForManager());\n }\n }\n\n // Check if dpkg is available\n this.dpkg = await this._isDpkgAvailable();\n this.logger.debug(`Detected dpkg: ${this.dpkg}`);\n }\n }\n\n ready(): Promise<void> {\n return this._readyPromise;\n }\n\n /**\n * Tests if the given command can be executed\n *\n * @param cmd The command to test\n * @returns True if the execution was successful, false otherwise\n */\n private async _isCmd(cmd: string): Promise<boolean> {\n try {\n const { stderr } = await execAsync(cmd);\n return !stderr;\n } catch (e) {\n // non zero exit code, however lets check if ok\n if (e.stderr === '') {\n return true;\n }\n console.error(e.stderr || e.stdout || e);\n return false;\n }\n }\n\n private async _isDpkgAvailable(): Promise<boolean> {\n try {\n const { stdout, stderr } = await execAsync('dpkg');\n return !!((stdout && stdout.includes('dpkg --help')) || (stderr && stderr.includes('dpkg --help')));\n } catch (err) {\n // non zero exit code, however lets check if ok\n if (\n (err.stdout && err.stdout.includes('dpkg --help')) ||\n (err.stderr && err.stderr.includes('dpkg --help'))\n ) {\n return true;\n }\n this.logger.error(`Cannot detect dpkg: ${err.stderr || err.stdout || err}`);\n return false;\n }\n }\n\n private async _isSudoAvailable(): Promise<boolean> {\n try {\n const { stdout, stderr } = await execAsync('sudo');\n return !!((stdout && stdout.includes('sudo -h')) || (stderr && stderr.includes('sudo -h')));\n } catch (err) {\n // non zero exit code, however lets check if ok\n if ((err.stdout && err.stdout.includes('sudo -h')) || (err.stderr && err.stderr.includes('sudo -h'))) {\n return true;\n }\n this.logger.error(`Cannot detect sudo: ${err.stderr || err.stdout || err}`);\n return false;\n }\n }\n\n private async _isSudoAvailableForManager(): Promise<boolean> {\n try {\n await execAsync(`sudo -n ${this.manager} -v`);\n return true;\n } catch (err) {\n this.logger.error(`Cannot detect \\\\\"sudo -n ${this.manager} -v\\\\\": ${err.stderr || err.stdout || err}`);\n return false;\n }\n }\n\n /**\n * Detects which package manager is installed. Throws if none can be found\n */\n private async _detectManager(): Promise<Manager | void> {\n for (const cmd of ['apt', 'yum'] as const) {\n if (await this._isCmd(cmd)) {\n this.manager = cmd;\n return cmd;\n }\n }\n this.logger.info('No supported packet manager found');\n }\n\n /**\n * Updates the sources if apt is used\n */\n async update(): Promise<void> {\n await this.ready();\n\n if (this.manager !== 'apt') {\n // ignore\n return;\n }\n\n try {\n await execAsync(`${(this.sudo ? 'sudo ' : '') + this.manager} update`);\n } catch (e) {\n this.logger.warn(`Cannot update apt sources: ${e.message}`);\n }\n }\n\n private async _listPackages(): Promise<string> {\n if (!this.dpkg) {\n throw new Error('No dpkg detected');\n }\n\n try {\n const { stdout } = await execAsync(`${this.sudo ? 'sudo ' : ''}dpkg -l`);\n const res = Buffer.isBuffer(stdout) ? stdout.toString('utf-8') : stdout;\n return res || '';\n } catch {\n // Ignore error\n return '';\n }\n }\n\n /**\n * Checks which packages are installed and returns them\n *\n * @param packets The packets to test\n */\n async checkInstalled(packets: string[] | string): Promise<string[]> {\n if (!(packets instanceof Array)) {\n packets = [packets];\n }\n\n const installed = await this._listPackages();\n return packets.filter(p => installed.includes(p));\n }\n\n /**\n * Installs a single packet using the configured manager and returns the stdout if there was any\n *\n * @param packet The packet to install\n */\n private async _installPacket(packet: string): Promise<void> {\n if (!this.manager) {\n // ignore\n return;\n }\n\n // if it fails, let it throw and get caught by _installPackets\n await execAsync(`${(this.sudo ? 'sudo ' : '') + this.manager} install ${packet} -y`);\n }\n\n /**\n * List all packages for which updates are available\n */\n async listUpgradeablePackages(): Promise<string[]> {\n if (!this.manager) {\n return [];\n }\n\n const { stdout } = await execAsync(\n `${(this.sudo ? 'sudo ' : '') + this.manager} ${this.COMMANDS.listUpgradeable[this.manager]}`,\n );\n\n const res = Buffer.isBuffer(stdout) ? stdout.toString('utf-8') : stdout;\n\n if (!res) {\n return [];\n }\n\n const packagesList = res.split('\\n').filter(packageInfo => packageInfo.trim() !== '');\n // first line is no package, just Listing...\n packagesList.shift();\n\n return packagesList;\n }\n\n /**\n * Installs multiple packets. The returned Promise contains the list of failed packets\n *\n * @param packets list of packets to install\n */\n private async _installPackets(packets: string[]): Promise<string[]> {\n const failed: string[] = [];\n\n if (packets?.length) {\n // Install all packets\n for (const packet of packets) {\n try {\n await this._installPacket(packet);\n } catch (err) {\n failed.push(packet);\n this.logger.error(`Cannot install \"${packet}\": ${err.stderr || err.stdout || err}`);\n // Continue with the next packet\n }\n }\n }\n return failed;\n }\n\n /**\n * Upgrade given OS packets to given version or newest available version\n *\n * @param packets the packet names and version information\n */\n async upgrade(packets: UpgradePacket[]): Promise<void> {\n await this.ready();\n\n if (!this.manager) {\n return;\n }\n\n for (const packet of packets) {\n let upgradeCmd = `upgrade -y ${packet.name}`;\n\n if (packet.version) {\n if (this.manager === 'apt') {\n upgradeCmd += `=${packet.version}`;\n } else {\n upgradeCmd = `install ${packet.name}-${packet.version}`;\n }\n }\n\n await execAsync(`${(this.sudo ? 'sudo ' : '') + this.manager} ${upgradeCmd}`);\n }\n }\n\n /**\n * Installs all given packets\n *\n * @param packets list of packets or single packet to upgrade\n */\n async install(packets: string[] | string): Promise<void> {\n packets = packets || [];\n if (!(packets instanceof Array)) {\n packets = [packets];\n }\n\n await this.ready();\n\n // Filter empty packets out\n packets = packets && packets.filter(p => p && p.trim());\n\n if (!packets || !packets.length) {\n // nothing must be installed\n return;\n }\n const installed = await this.checkInstalled(packets);\n const notInstalled = packets.filter(packet => !installed.includes(packet));\n // Install all non-installed packets\n const failed = await this._installPackets(notInstalled);\n if (this.logger) {\n if (failed.length > 0) {\n this.logger.warn(\n `The following ${this.manager || 'OS'} packages could not be installed: ${failed.join(\n ', ',\n )}. Please install them manually.`,\n );\n\n if (notInstalled.length) {\n this.logger.info(\n `Installed the following ${this.manager || 'OS'} packages: ${notInstalled.join(', ')}`,\n );\n }\n\n if (installed.length) {\n this.logger.info(\n `These ${this.manager || 'OS'} packages were already installed: ${installed.join(', ')}`,\n );\n }\n }\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { execAsync, type InternalLogger } from '@iobroker/js-controller-common-db/tools';\n\nenum LOG_LEVELS {\n silly = 5,\n debug = 4,\n log = 3,\n info = 2,\n warn = 1,\n error = 0,\n}\n\ninterface Logger extends InternalLogger {\n log(message: string): void;\n}\n\ntype Manager = 'apt' | 'yum' | '';\n\ninterface PacketManagerOptions {\n logLevel: LOG_LEVELS;\n manager?: Manager;\n logger?: Logger;\n}\n\n/** Describes a system packet that should be upgraded */\nexport interface UpgradePacket {\n /** Name of the packet which should be upgraded */\n name: string;\n /** Optional version */\n version?: string;\n}\n\n/**\n * Wrapper around the system packet manager (apt or yum) to query and upgrade system packages\n */\nexport class PacketManager {\n private manager: Manager;\n private readonly logger: Logger;\n private dpkg: boolean;\n private sudo: boolean;\n private readonly _readyPromise: Promise<void>;\n private readonly COMMANDS = {\n listUpgradeable: {\n apt: 'list --upgradeable',\n yum: 'check-update',\n },\n } as const;\n\n /**\n * @param options The packet manager to use, a logger and the log level\n */\n constructor(options: PacketManagerOptions = { logLevel: LOG_LEVELS.info }) {\n // detect apt or yum\n this.manager = options?.manager || '';\n this.logger = options?.logger || {\n silly: text => options.logLevel >= LOG_LEVELS.silly && console.log(text),\n info: text => options.logLevel >= LOG_LEVELS.info && console.log(text),\n log: text => options.logLevel >= LOG_LEVELS.log && console.log(text),\n warn: text => options.logLevel >= LOG_LEVELS.warn && console.warn(text),\n error: text => options.logLevel >= LOG_LEVELS.error && console.error(text),\n debug: text => options.logLevel >= LOG_LEVELS.debug && console.log(text),\n };\n this.dpkg = false;\n this.sudo = false;\n this._readyPromise = this._init();\n }\n\n /** Starts the initialization process */\n private async _init(): Promise<void> {\n if (process.platform !== 'win32') {\n if (!this.manager) {\n const manager = await this._detectManager();\n if (manager) {\n this.logger.debug(`Detected packet manager: ${manager}`);\n // Check if sudo is available for packet manager and store information\n this.sudo = (await this._isSudoAvailable()) && (await this._isSudoAvailableForManager());\n }\n }\n\n // Check if dpkg is available\n this.dpkg = await this._isDpkgAvailable();\n this.logger.debug(`Detected dpkg: ${this.dpkg}`);\n }\n }\n\n /**\n * Resolve once the packet manager has finished its asynchronous initialization\n */\n ready(): Promise<void> {\n return this._readyPromise;\n }\n\n /**\n * Tests if the given command can be executed\n *\n * @param cmd The command to test\n * @returns True if the execution was successful, false otherwise\n */\n private async _isCmd(cmd: string): Promise<boolean> {\n try {\n const { stderr } = await execAsync(cmd);\n return !stderr;\n } catch (e) {\n // non zero exit code, however lets check if ok\n if (e.stderr === '') {\n return true;\n }\n console.error(e.stderr || e.stdout || e);\n return false;\n }\n }\n\n private async _isDpkgAvailable(): Promise<boolean> {\n try {\n const { stdout, stderr } = await execAsync('dpkg');\n return !!((stdout && stdout.includes('dpkg --help')) || (stderr && stderr.includes('dpkg --help')));\n } catch (err) {\n // non zero exit code, however lets check if ok\n if (\n (err.stdout && err.stdout.includes('dpkg --help')) ||\n (err.stderr && err.stderr.includes('dpkg --help'))\n ) {\n return true;\n }\n this.logger.error(`Cannot detect dpkg: ${err.stderr || err.stdout || err}`);\n return false;\n }\n }\n\n private async _isSudoAvailable(): Promise<boolean> {\n try {\n const { stdout, stderr } = await execAsync('sudo');\n return !!((stdout && stdout.includes('sudo -h')) || (stderr && stderr.includes('sudo -h')));\n } catch (err) {\n // non zero exit code, however lets check if ok\n if ((err.stdout && err.stdout.includes('sudo -h')) || (err.stderr && err.stderr.includes('sudo -h'))) {\n return true;\n }\n this.logger.error(`Cannot detect sudo: ${err.stderr || err.stdout || err}`);\n return false;\n }\n }\n\n private async _isSudoAvailableForManager(): Promise<boolean> {\n try {\n await execAsync(`sudo -n ${this.manager} -v`);\n return true;\n } catch (err) {\n this.logger.error(`Cannot detect \\\\\"sudo -n ${this.manager} -v\\\\\": ${err.stderr || err.stdout || err}`);\n return false;\n }\n }\n\n /**\n * Detects which package manager is installed. Throws if none can be found\n */\n private async _detectManager(): Promise<Manager | void> {\n for (const cmd of ['apt', 'yum'] as const) {\n if (await this._isCmd(cmd)) {\n this.manager = cmd;\n return cmd;\n }\n }\n this.logger.info('No supported packet manager found');\n }\n\n /**\n * Updates the sources if apt is used\n */\n async update(): Promise<void> {\n await this.ready();\n\n if (this.manager !== 'apt') {\n // ignore\n return;\n }\n\n try {\n await execAsync(`${(this.sudo ? 'sudo ' : '') + this.manager} update`);\n } catch (e) {\n this.logger.warn(`Cannot update apt sources: ${e.message}`);\n }\n }\n\n private async _listPackages(): Promise<string> {\n if (!this.dpkg) {\n throw new Error('No dpkg detected');\n }\n\n try {\n const { stdout } = await execAsync(`${this.sudo ? 'sudo ' : ''}dpkg -l`);\n const res = Buffer.isBuffer(stdout) ? stdout.toString('utf-8') : stdout;\n return res || '';\n } catch {\n // Ignore error\n return '';\n }\n }\n\n /**\n * Checks which packages are installed and returns them\n *\n * @param packets The packets to test\n */\n async checkInstalled(packets: string[] | string): Promise<string[]> {\n if (!(packets instanceof Array)) {\n packets = [packets];\n }\n\n const installed = await this._listPackages();\n return packets.filter(p => installed.includes(p));\n }\n\n /**\n * Installs a single packet using the configured manager and returns the stdout if there was any\n *\n * @param packet The packet to install\n */\n private async _installPacket(packet: string): Promise<void> {\n if (!this.manager) {\n // ignore\n return;\n }\n\n // if it fails, let it throw and get caught by _installPackets\n await execAsync(`${(this.sudo ? 'sudo ' : '') + this.manager} install ${packet} -y`);\n }\n\n /**\n * List all packages for which updates are available\n */\n async listUpgradeablePackages(): Promise<string[]> {\n if (!this.manager) {\n return [];\n }\n\n const { stdout } = await execAsync(\n `${(this.sudo ? 'sudo ' : '') + this.manager} ${this.COMMANDS.listUpgradeable[this.manager]}`,\n );\n\n const res = Buffer.isBuffer(stdout) ? stdout.toString('utf-8') : stdout;\n\n if (!res) {\n return [];\n }\n\n const packagesList = res.split('\\n').filter(packageInfo => packageInfo.trim() !== '');\n // first line is no package, just Listing...\n packagesList.shift();\n\n return packagesList;\n }\n\n /**\n * Installs multiple packets. The returned Promise contains the list of failed packets\n *\n * @param packets list of packets to install\n */\n private async _installPackets(packets: string[]): Promise<string[]> {\n const failed: string[] = [];\n\n if (packets?.length) {\n // Install all packets\n for (const packet of packets) {\n try {\n await this._installPacket(packet);\n } catch (err) {\n failed.push(packet);\n this.logger.error(`Cannot install \"${packet}\": ${err.stderr || err.stdout || err}`);\n // Continue with the next packet\n }\n }\n }\n return failed;\n }\n\n /**\n * Upgrade given OS packets to given version or newest available version\n *\n * @param packets the packet names and version information\n */\n async upgrade(packets: UpgradePacket[]): Promise<void> {\n await this.ready();\n\n if (!this.manager) {\n return;\n }\n\n for (const packet of packets) {\n let upgradeCmd = `upgrade -y ${packet.name}`;\n\n if (packet.version) {\n if (this.manager === 'apt') {\n upgradeCmd += `=${packet.version}`;\n } else {\n upgradeCmd = `install ${packet.name}-${packet.version}`;\n }\n }\n\n await execAsync(`${(this.sudo ? 'sudo ' : '') + this.manager} ${upgradeCmd}`);\n }\n }\n\n /**\n * Installs all given packets\n *\n * @param packets list of packets or single packet to upgrade\n */\n async install(packets: string[] | string): Promise<void> {\n packets = packets || [];\n if (!(packets instanceof Array)) {\n packets = [packets];\n }\n\n await this.ready();\n\n // Filter empty packets out\n packets = packets && packets.filter(p => p && p.trim());\n\n if (!packets || !packets.length) {\n // nothing must be installed\n return;\n }\n const installed = await this.checkInstalled(packets);\n const notInstalled = packets.filter(packet => !installed.includes(packet));\n // Install all non-installed packets\n const failed = await this._installPackets(notInstalled);\n if (this.logger) {\n if (failed.length > 0) {\n this.logger.warn(\n `The following ${this.manager || 'OS'} packages could not be installed: ${failed.join(\n ', ',\n )}. Please install them manually.`,\n );\n\n if (notInstalled.length) {\n this.logger.info(\n `Installed the following ${this.manager || 'OS'} packages: ${notInstalled.join(', ')}`,\n );\n }\n\n if (installed.length) {\n this.logger.info(\n `These ${this.manager || 'OS'} packages were already installed: ${installed.join(', ')}`,\n );\n }\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["LOG_LEVELS"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';
|
|
2
2
|
import type { Client as StatesRedisClient } from '@iobroker/db-states-redis';
|
|
3
|
+
import type { ProcessCommandOptions } from '../../lib/cli/cliCommand.js';
|
|
3
4
|
/** The options passed to the Repo constructor */
|
|
4
5
|
export interface CLIRepoOptions {
|
|
5
6
|
/** Instance of objects DB */
|
|
@@ -24,11 +25,17 @@ export interface RepoFlags {
|
|
|
24
25
|
/** Force update even if hash hasn't changed */
|
|
25
26
|
force?: boolean;
|
|
26
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* CLI command to manage the ioBroker repositories
|
|
30
|
+
*/
|
|
27
31
|
export declare class Repo {
|
|
28
32
|
private readonly defaultSystemRepo;
|
|
29
33
|
private readonly objects;
|
|
30
34
|
private readonly states;
|
|
31
35
|
private readonly controllerVersion;
|
|
36
|
+
/**
|
|
37
|
+
* @param options The objects/states clients and the controller version
|
|
38
|
+
*/
|
|
32
39
|
constructor(options: CLIRepoOptions);
|
|
33
40
|
/**
|
|
34
41
|
* Get the repository name by index
|
|
@@ -110,4 +117,16 @@ export declare class Repo {
|
|
|
110
117
|
*/
|
|
111
118
|
rename(oldName: string, newName: string, repoUrl: string): Promise<void>;
|
|
112
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Handles the `update` CLI command
|
|
122
|
+
*
|
|
123
|
+
* @param options the process command options
|
|
124
|
+
*/
|
|
125
|
+
export declare function processCommandUpdate(options: ProcessCommandOptions): void;
|
|
126
|
+
/**
|
|
127
|
+
* Handles the `repo` CLI command
|
|
128
|
+
*
|
|
129
|
+
* @param options the process command options
|
|
130
|
+
*/
|
|
131
|
+
export declare function processCommandRepo(options: ProcessCommandOptions): Promise<void>;
|
|
113
132
|
//# sourceMappingURL=setupRepo.d.ts.map
|
|
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
9
|
var __export = (target, all) => {
|
|
9
10
|
for (var name in all)
|
|
10
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -28,20 +29,29 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
29
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
30
|
var setupRepo_exports = {};
|
|
30
31
|
__export(setupRepo_exports, {
|
|
31
|
-
Repo: () => Repo
|
|
32
|
+
Repo: () => Repo,
|
|
33
|
+
processCommandRepo: () => processCommandRepo,
|
|
34
|
+
processCommandUpdate: () => processCommandUpdate
|
|
32
35
|
});
|
|
33
36
|
module.exports = __toCommonJS(setupRepo_exports);
|
|
34
|
-
var import_js_controller_common = require("@iobroker/js-controller-common");
|
|
35
37
|
var import_axios = __toESM(require("axios"), 1);
|
|
36
38
|
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
37
|
-
var import_utils = require("../../lib/setup/utils.js");
|
|
38
39
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
40
|
+
var import_js_controller_common = require("@iobroker/js-controller-common");
|
|
39
41
|
var import_constants = require("@iobroker/js-controller-common-db/constants");
|
|
42
|
+
var import_utils = require("../../lib/setup/utils.js");
|
|
43
|
+
var import_dbConnection = require("../../lib/setup/dbConnection.js");
|
|
40
44
|
class Repo {
|
|
45
|
+
static {
|
|
46
|
+
__name(this, "Repo");
|
|
47
|
+
}
|
|
41
48
|
defaultSystemRepo;
|
|
42
49
|
objects;
|
|
43
50
|
states;
|
|
44
51
|
controllerVersion;
|
|
52
|
+
/**
|
|
53
|
+
* @param options The objects/states clients and the controller version
|
|
54
|
+
*/
|
|
45
55
|
constructor(options) {
|
|
46
56
|
if (!options?.objects) {
|
|
47
57
|
throw new Error("Invalid arguments: objects is missing");
|
|
@@ -207,7 +217,9 @@ class Repo {
|
|
|
207
217
|
};
|
|
208
218
|
}
|
|
209
219
|
const sources = await this.updateRepo(url, flags.force || flags.f, systemConfig, systemRepos);
|
|
210
|
-
|
|
220
|
+
if (sources) {
|
|
221
|
+
Object.assign(allSources, sources);
|
|
222
|
+
}
|
|
211
223
|
} else {
|
|
212
224
|
console.error(`Error: unknown repository is active - "${url}". Known: ${Object.keys(systemRepos.native.repositories).join(", ")}`);
|
|
213
225
|
}
|
|
@@ -230,11 +242,15 @@ class Repo {
|
|
|
230
242
|
const adapters = Object.keys(sources).sort();
|
|
231
243
|
for (const name of adapters) {
|
|
232
244
|
let updatable = false;
|
|
233
|
-
|
|
245
|
+
if (name === "repoInfo") {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
const adapter = sources[name];
|
|
249
|
+
let text = adapter.controller ? "Controller " : "Adapter ";
|
|
234
250
|
text += `"${name}"`;
|
|
235
251
|
text = text.padEnd(11 + 15);
|
|
236
|
-
if (
|
|
237
|
-
text += `: ${
|
|
252
|
+
if (adapter.version) {
|
|
253
|
+
text += `: ${adapter.version}`;
|
|
238
254
|
}
|
|
239
255
|
text = text.padEnd(11 + 15 + 11);
|
|
240
256
|
if (!(flags.all || flags.a) && !installed[name]) {
|
|
@@ -243,13 +259,13 @@ class Repo {
|
|
|
243
259
|
if (installed[name]?.version) {
|
|
244
260
|
text += `, installed ${installed[name].version}`;
|
|
245
261
|
try {
|
|
246
|
-
if (
|
|
262
|
+
if (adapter.version !== installed[name].version && adapter.version && !import_js_controller_common.tools.upToDate(adapter.version, installed[name].version)) {
|
|
247
263
|
updatable = true;
|
|
248
264
|
text = text.padEnd(11 + 15 + 11 + 18);
|
|
249
265
|
const isIgnored = await (0, import_utils.isVersionIgnored)({
|
|
250
266
|
adapterName: name,
|
|
251
267
|
objects: this.objects,
|
|
252
|
-
version:
|
|
268
|
+
version: adapter.version
|
|
253
269
|
});
|
|
254
270
|
text += isIgnored ? " [Ignored]" : " [Updatable]";
|
|
255
271
|
}
|
|
@@ -271,10 +287,14 @@ class Repo {
|
|
|
271
287
|
async updateInfo(sources) {
|
|
272
288
|
const installed = import_js_controller_common.tools.getInstalledInfo();
|
|
273
289
|
const list = [];
|
|
274
|
-
for (const name
|
|
275
|
-
if (
|
|
290
|
+
for (const name in sources) {
|
|
291
|
+
if (name === "repoInfo") {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
const adapter = sources[name];
|
|
295
|
+
if (installed[name]?.version && adapter.version) {
|
|
276
296
|
try {
|
|
277
|
-
if (
|
|
297
|
+
if (adapter.version !== installed[name].version && !import_js_controller_common.tools.upToDate(adapter.version, installed[name].version)) {
|
|
278
298
|
const n = name.indexOf(".");
|
|
279
299
|
list.push(n === -1 ? name : name.substring(n + 1));
|
|
280
300
|
}
|
|
@@ -499,8 +519,116 @@ Active repo(s): ${activeRepo.join(", ")}`);
|
|
|
499
519
|
}
|
|
500
520
|
}
|
|
501
521
|
}
|
|
522
|
+
function processCommandUpdate(options) {
|
|
523
|
+
const { args, params, callback } = options;
|
|
524
|
+
const repoUrl = args[0];
|
|
525
|
+
(0, import_dbConnection.dbConnect)(params, async ({ objects, states }) => {
|
|
526
|
+
const repo = new Repo({
|
|
527
|
+
objects,
|
|
528
|
+
states
|
|
529
|
+
});
|
|
530
|
+
await repo.showRepo(repoUrl, params);
|
|
531
|
+
setTimeout(callback, 1e3);
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
__name(processCommandUpdate, "processCommandUpdate");
|
|
535
|
+
async function processCommandRepo(options) {
|
|
536
|
+
const { args, params, callback } = options;
|
|
537
|
+
let repoUrlOrCommand = args[0];
|
|
538
|
+
let repoName = args[1];
|
|
539
|
+
let repoUrl = args[2];
|
|
540
|
+
if (repoUrlOrCommand !== "add" && repoUrlOrCommand !== "del" && repoUrlOrCommand !== "set" && repoUrlOrCommand !== "show" && repoUrlOrCommand !== "addset" && repoUrlOrCommand !== "unset") {
|
|
541
|
+
repoUrl = repoUrlOrCommand;
|
|
542
|
+
repoUrlOrCommand = "show";
|
|
543
|
+
}
|
|
544
|
+
const { objects, states } = await (0, import_dbConnection.dbConnectAsync)(false, params);
|
|
545
|
+
const repo = new Repo({
|
|
546
|
+
objects,
|
|
547
|
+
states
|
|
548
|
+
});
|
|
549
|
+
if (repoUrlOrCommand === "show") {
|
|
550
|
+
try {
|
|
551
|
+
await repo.showRepoStatus();
|
|
552
|
+
return void callback();
|
|
553
|
+
} catch (e) {
|
|
554
|
+
console.error(`Cannot show repository status: ${e.message}`);
|
|
555
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_REPO);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (repoUrlOrCommand === "add" || repoUrlOrCommand === "del" || repoUrlOrCommand === "set" || repoUrlOrCommand === "addset" || repoUrlOrCommand === "unset") {
|
|
559
|
+
if (!repoName || !repoName.match(/[-_\w]+/)) {
|
|
560
|
+
console.error(`Invalid repository name: "${repoName}"`);
|
|
561
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS);
|
|
562
|
+
}
|
|
563
|
+
if ((0, import_utils.isIntegerLikeInput)(repoName)) {
|
|
564
|
+
try {
|
|
565
|
+
repoName = await repo.getNameByIndex(parseInt(repoName));
|
|
566
|
+
} catch (e) {
|
|
567
|
+
console.error(e.message);
|
|
568
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if (repoUrlOrCommand === "add" || repoUrlOrCommand === "addset") {
|
|
572
|
+
if (!repoUrl) {
|
|
573
|
+
console.warn(`Please define repository URL or path: ${import_js_controller_common.tools.appName.toLowerCase()} add <repoName> <repoUrlOrPath>`);
|
|
574
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS);
|
|
575
|
+
}
|
|
576
|
+
try {
|
|
577
|
+
await repo.add(repoName, repoUrl);
|
|
578
|
+
if (repoUrlOrCommand === "addset") {
|
|
579
|
+
await repo.setActive(repoName);
|
|
580
|
+
console.log(`Repository "${repoName}" set as active: "${repoUrl}"`);
|
|
581
|
+
await repo.showRepoStatus();
|
|
582
|
+
return void callback();
|
|
583
|
+
}
|
|
584
|
+
console.log(`Repository "${repoName}" added as "${repoUrl}"`);
|
|
585
|
+
await repo.showRepoStatus();
|
|
586
|
+
return void callback();
|
|
587
|
+
} catch (e) {
|
|
588
|
+
console.error(`Cannot add repository location: ${e.message}`);
|
|
589
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_REPO);
|
|
590
|
+
}
|
|
591
|
+
} else if (repoUrlOrCommand === "set") {
|
|
592
|
+
try {
|
|
593
|
+
await repo.setActive(repoName);
|
|
594
|
+
console.log(`Repository "${repoName}" set as active.`);
|
|
595
|
+
await repo.showRepoStatus();
|
|
596
|
+
return void callback();
|
|
597
|
+
} catch (e) {
|
|
598
|
+
console.error(`Cannot activate repository: ${e.message}`);
|
|
599
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_REPO);
|
|
600
|
+
}
|
|
601
|
+
} else if (repoUrlOrCommand === "del") {
|
|
602
|
+
try {
|
|
603
|
+
await repo.del(repoName);
|
|
604
|
+
console.log(`Repository "${repoName}" deleted.`);
|
|
605
|
+
await repo.showRepoStatus();
|
|
606
|
+
return void callback();
|
|
607
|
+
} catch (e) {
|
|
608
|
+
console.error(`Cannot remove repository: ${e.message}`);
|
|
609
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_REPO);
|
|
610
|
+
}
|
|
611
|
+
} else if (repoUrlOrCommand === "unset") {
|
|
612
|
+
try {
|
|
613
|
+
await repo.setInactive(repoName);
|
|
614
|
+
console.log(`Repository "${repoName}" deactivated.`);
|
|
615
|
+
await repo.showRepoStatus();
|
|
616
|
+
return void callback();
|
|
617
|
+
} catch (e) {
|
|
618
|
+
console.error(`Cannot deactivate repository: ${e.message}`);
|
|
619
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_REPO);
|
|
620
|
+
}
|
|
621
|
+
} else {
|
|
622
|
+
console.warn(`Unknown repo command: ${repoUrlOrCommand}`);
|
|
623
|
+
return void callback(import_js_controller_common.EXIT_CODES.INVALID_ARGUMENTS);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
__name(processCommandRepo, "processCommandRepo");
|
|
502
628
|
// Annotate the CommonJS export names for ESM import in node:
|
|
503
629
|
0 && (module.exports = {
|
|
504
|
-
Repo
|
|
630
|
+
Repo,
|
|
631
|
+
processCommandRepo,
|
|
632
|
+
processCommandUpdate
|
|
505
633
|
});
|
|
506
634
|
//# sourceMappingURL=setupRepo.js.map
|