@iobroker/js-controller-cli 6.0.9 → 6.0.10-alpha.0-20240804-d9be20474

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/setup/setupUpgrade.ts"],
4
- "sourcesContent": ["import Debug from 'debug';\nimport fs from 'fs-extra';\nimport { tools, EXIT_CODES } from '@iobroker/js-controller-common';\nimport semver from 'semver';\nimport { Upload } from '@/lib/setup/setupUpload.js';\nimport { Install } from '@/lib/setup/setupInstall.js';\nimport rl from 'readline-sync';\nimport tty from 'node:tty';\nimport path from 'node:path';\nimport { getRepository, isVersionIgnored } from '@/lib/setup/utils.js';\nimport type { Client as ObjectsInRedisClient } from '@iobroker/db-objects-redis';\nimport type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { ProcessExitCallback } from '@/lib/_Types.js';\nimport { IoBrokerError } from '@/lib/setup/customError.js';\n\nconst debug = Debug('iobroker:cli');\n\ntype IoPackDependencies = string[] | Record<string, any>[] | Record<string, any>;\n\ninterface CLIUpgradeOptions {\n processExit: ProcessExitCallback;\n objects: ObjectsInRedisClient;\n states: StatesInRedisClient;\n params: Record<string, any>;\n}\n\nexport class Upgrade {\n private readonly hostname = tools.getHostName();\n private readonly upload: Upload;\n private readonly install: Install;\n private readonly objects: ObjectsInRedisClient;\n private readonly processExit: ProcessExitCallback;\n\n constructor(options: CLIUpgradeOptions) {\n options = options || {};\n\n if (!options.processExit) {\n throw new Error('Invalid arguments: processExit is missing');\n }\n\n this.processExit = options.processExit;\n this.objects = options.objects;\n\n this.upload = new Upload(options);\n this.install = new Install(options);\n }\n\n /**\n * Sorts the adapters by their dependencies and then upgrades multiple adapters from the given repository url\n *\n * @param repo the repository content\n * @param list list of adapters to upgrade\n * @param forceDowngrade flag to force downgrade\n * @param autoConfirm automatically confirm the tty questions (bypass)\n */\n async upgradeAdapterHelper(\n repo: Record<string, any>,\n list: string[],\n forceDowngrade: boolean,\n autoConfirm: boolean\n ): Promise<void> {\n const relevantAdapters = [];\n // check which adapters are upgradeable and sort them according to their dependencies\n for (const adapter of list) {\n if (repo[adapter].controller) {\n // skip controller\n continue;\n }\n const adapterDir = tools.getAdapterDir(adapter);\n if (adapterDir && fs.existsSync(path.join(adapterDir, 'io-package.json'))) {\n const ioInstalled = fs.readJsonSync(path.join(adapterDir, 'io-package.json'));\n if (!tools.upToDate(repo[adapter].version, ioInstalled.common.version)) {\n // not up to date, we need to put it into account for our dependency check\n relevantAdapters.push(adapter);\n }\n }\n }\n\n if (relevantAdapters.length) {\n const sortedAdapters = [];\n\n while (relevantAdapters.length) {\n let oneAdapterAdded = false;\n // create ordered list for upgrades\n for (let i = relevantAdapters.length - 1; i >= 0; i--) {\n const relAdapter = relevantAdapters[i];\n // if new version has no dependencies we can upgrade\n if (!repo[relAdapter].dependencies && !repo[relAdapter].globalDependencies) {\n // no deps, simply add it\n sortedAdapters.push(relAdapter);\n relevantAdapters.splice(relevantAdapters.indexOf(relAdapter), 1);\n oneAdapterAdded = true;\n } else {\n const allDeps: Record<string, string> = {\n ...tools.parseDependencies(repo[relAdapter].dependencies),\n ...tools.parseDependencies(repo[relAdapter].globalDependencies)\n };\n\n // we have to check if the deps are there\n let conflict = false;\n for (const [depName, version] of Object.entries(allDeps)) {\n debug(`adapter \"${relAdapter}\" has dependency \"${depName}\": \"${version}\"`);\n if (version !== '*') {\n // dependency is important, because it affects version range\n if (relevantAdapters.includes(depName)) {\n // the dependency is also in the upgrade list and not previously added, we should add the dependency first\n debug(`conflict for dependency \"${depName}\" at adapter \"${relAdapter}\"`);\n conflict = true;\n break;\n }\n }\n }\n // we reached here and no conflict so every dep is satisfied\n if (!conflict) {\n sortedAdapters.push(relAdapter);\n relevantAdapters.splice(relevantAdapters.indexOf(relAdapter), 1);\n oneAdapterAdded = true;\n }\n }\n }\n\n if (!oneAdapterAdded) {\n // no adapter during this loop -> circular dependency\n console.warn(`Circular dependency detected between adapters \"${relevantAdapters.join(', ')}\"`);\n sortedAdapters.concat(relevantAdapters);\n break; // however, break and try to update\n }\n }\n\n debug(`upgrade order is \"${sortedAdapters.join(', ')}\"`);\n\n for (const sortedAdapter of sortedAdapters) {\n if (repo[sortedAdapter]?.controller) {\n continue;\n }\n await this.upgradeAdapter(repo, sortedAdapter, forceDowngrade, autoConfirm, true);\n }\n } else {\n console.log('All adapters are up to date');\n }\n }\n\n /**\n * Checks that local and global deps are fulfilled else rejects promise\n *\n * @param deps local dependencies - required on this host\n * @param globalDeps global dependencies - required on one of the hosts\n */\n private async _checkDependencies(deps: IoPackDependencies, globalDeps: IoPackDependencies): Promise<void> {\n if (!deps && !globalDeps) {\n return Promise.resolve();\n }\n\n deps = tools.parseDependencies(deps);\n globalDeps = tools.parseDependencies(globalDeps);\n // combine both dependencies\n const allDeps = { ...deps, ...globalDeps };\n\n // Get all installed adapters\n let objs;\n try {\n objs = await this.objects.getObjectViewAsync(\n 'system',\n 'instance',\n {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999'\n },\n undefined\n );\n } catch (e) {\n return Promise.reject(e);\n }\n\n if (objs?.rows?.length) {\n for (const dName in allDeps) {\n if (dName === 'js-controller') {\n const version = allDeps[dName];\n // Check only if version not *, else we don't have to read io-pack unnecessarily\n if (version !== '*') {\n const iopkg_ = fs.readJSONSync(`${tools.getControllerDir()}/package.json`);\n try {\n if (!semver.satisfies(iopkg_.version, version, { includePrerelease: true })) {\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${iopkg_.version}\", required \"${version}`\n )\n );\n }\n } catch (e) {\n console.log(`Can not check js-controller dependency requirement: ${e.message}`);\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${iopkg_.version}\", required \"${version}`\n )\n );\n }\n }\n } else {\n let gInstances: ioBroker.GetObjectViewItem<ioBroker.InstanceObject>[] = [];\n let locInstances: ioBroker.GetObjectViewItem<ioBroker.InstanceObject>[] = [];\n // if global dep get all instances of adapter\n if (globalDeps[dName] !== undefined) {\n gInstances = objs.rows.filter(obj => obj.value.common && obj.value.common.name === dName);\n }\n if (deps[dName] !== undefined) {\n // local dep get all instances on same host\n locInstances = objs.rows.filter(\n obj =>\n obj.value.common &&\n obj.value.common.name === dName &&\n obj.value.common.host === this.hostname\n );\n if (locInstances.length === 0) {\n return Promise.reject(new Error(`Required dependency \"${dName}\" not found on this host.`));\n }\n }\n\n let isFound = false;\n // we check, that all instances match - respect different local and global dep versions\n for (const instance of locInstances) {\n const instanceVersion = instance.value.common.version;\n try {\n if (\n !semver.satisfies(instanceVersion, deps[dName], {\n includePrerelease: true\n })\n ) {\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${deps[dName]}`\n )\n );\n }\n } catch (e) {\n console.log(`Can not check dependency requirement: ${e.message}`);\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${deps[dName]}`\n )\n );\n }\n isFound = true;\n }\n\n for (const instance of gInstances) {\n const instanceVersion = instance.value.common.version;\n try {\n if (\n !semver.satisfies(instanceVersion, globalDeps[dName], {\n includePrerelease: true\n })\n ) {\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${globalDeps[dName]}`\n )\n );\n }\n } catch (e) {\n console.log(`Can not check dependency requirement: ${e.message}`);\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${globalDeps[dName]}`\n )\n );\n }\n isFound = true;\n }\n\n if (isFound === false) {\n return Promise.reject(new Error(`Required dependency \"${dName}\" not found.`));\n }\n }\n }\n }\n }\n\n /**\n * Try to async upgrade adapter from given source with some checks\n *\n * @param repoUrlOrObject url of the selected repository or parsed repo, if undefined use current active repository\n * @param adapter name of the adapter (can also include version like web@3.0.0)\n * @param forceDowngrade flag to force downgrade\n * @param autoConfirm automatically confirm the tty questions (bypass)\n * @param upgradeAll if true, this is an upgrade all call, we don't do major upgrades if no tty\n */\n async upgradeAdapter(\n repoUrlOrObject: string | Record<string, any> | undefined,\n adapter: string,\n forceDowngrade: boolean,\n autoConfirm: boolean,\n upgradeAll: boolean\n ): Promise<void> {\n let sources: Record<string, any>;\n if (!repoUrlOrObject || !tools.isObject(repoUrlOrObject)) {\n try {\n sources = await getRepository({ repoName: repoUrlOrObject, objects: this.objects });\n } catch (e) {\n console.error(e.message);\n return this.processExit(e instanceof IoBrokerError ? e.code : e);\n }\n } else {\n sources = repoUrlOrObject;\n }\n\n let version: string;\n if (adapter.includes('@')) {\n const parts = adapter.split('@');\n adapter = parts[0];\n version = parts[1];\n } else {\n version = '';\n }\n if (version) {\n forceDowngrade = true;\n }\n\n /** Repository entry of this adapter */\n const repoAdapter: Record<string, any> = sources[adapter];\n\n // TODO: not really adapter object but close enough\n const finishUpgrade = async (name: string, ioPack?: ioBroker.AdapterObject): Promise<void> => {\n if (!ioPack) {\n const adapterDir = tools.getAdapterDir(name);\n\n if (!adapterDir) {\n console.error(`Cannot find io-package.json in ${adapterDir}`);\n return this.processExit(EXIT_CODES.MISSING_ADAPTER_FILES);\n }\n\n try {\n // close enough to an AdapterObject\n ioPack = fs.readJSONSync(path.join(adapterDir, 'io-package.json')) as ioBroker.AdapterObject;\n } catch {\n console.error(`Cannot find io-package.json in ${adapterDir}`);\n return this.processExit(EXIT_CODES.MISSING_ADAPTER_FILES);\n }\n }\n\n if (ioPack.common.osDependencies) {\n // install linux/osx libraries\n await this.install.installOSPackages(ioPack.common.osDependencies);\n }\n\n // Upload www and admin files of adapter\n await this.upload.uploadAdapter(name, false, true);\n // extend all adapter instance default configs with current config\n // (introduce potentially new attributes while keeping current settings)\n await this.upload.upgradeAdapterObjects(name, ioPack);\n await this.upload.uploadAdapter(name, true, true);\n };\n\n const adapterDir = tools.getAdapterDir(adapter);\n\n // Read actual description of installed adapter with version\n if (!adapterDir || (!version && !fs.existsSync(path.join(adapterDir, 'io-package.json')))) {\n return console.log(\n `Adapter \"${adapter}\"${\n adapter.length < 15 ? new Array(15 - adapter.length).join(' ') : ''\n } is not installed.`\n );\n }\n // Get the url of io-package.json or direct the version\n if (!repoAdapter) {\n console.log(`Adapter \"${adapter}\" is not in the repository and cannot be updated.`);\n return this.processExit(EXIT_CODES.ADAPTER_NOT_FOUND);\n }\n if (repoAdapter.controller) {\n return console.log(\n `Cannot update ${adapter} using this command. Please use \"iobroker upgrade self\" instead!`\n );\n }\n\n // TODO: not 100 % true but should be correct enough\n let ioInstalled: Pick<ioBroker.AdapterObject, 'common'>;\n if (adapterDir && fs.existsSync(path.join(adapterDir, 'io-package.json'))) {\n ioInstalled = fs.readJsonSync(`${adapterDir}/io-package.json`);\n } else {\n // @ts-expect-error https://github.com/ioBroker/adapter-core/issues/455\n ioInstalled = { common: { version: '0.0.0' } };\n }\n\n const installedVersion = ioInstalled.common.version;\n\n /**\n * We show changelog (news) and ask user if he really wants to upgrade but only if fd is associated with a tty, returns true if upgrade desired\n *\n * @param installedVersion - installed version of adapter\n * @param targetVersion - target version of adapter\n * @param adapterName - name of the adapter\n */\n const showUpgradeDialog = (installedVersion: string, targetVersion: string, adapterName: string): boolean => {\n // major upgrade or downgrade\n const isMajor = semver.major(installedVersion) !== semver.major(targetVersion);\n\n if (autoConfirm || (!tty.isatty(process.stdout.fd) && (!isMajor || !upgradeAll))) {\n // force flag or script on non major or single adapter upgrade -> always upgrade\n return true;\n }\n\n if (!tty.isatty(process.stdout.fd) && isMajor && upgradeAll) {\n // no tty and not forced and multiple adapters, do not upgrade\n console.log(`Skip major upgrade of ${adapterName} from ${installedVersion} to ${targetVersion}`);\n return false;\n }\n\n const isUpgrade = semver.gt(targetVersion, installedVersion);\n const isDowngrade = semver.lt(targetVersion, installedVersion);\n\n // if information in repo files -> show news\n if (repoAdapter?.news) {\n const news = repoAdapter.news;\n\n let first = true;\n // check if upgrade or downgrade\n if (isUpgrade) {\n for (const version in news) {\n try {\n if (semver.lte(version, targetVersion) && semver.gt(version, installedVersion)) {\n if (first === true) {\n const noMissingNews = news[targetVersion] && news[installedVersion];\n console.log(\n `\\nThis upgrade of \"${adapter}\" will ${\n noMissingNews ? '' : 'at least '\n }introduce the following changes:`\n );\n console.log(\n '=========================================================================='\n );\n first = false;\n } else if (first === false) {\n console.log();\n }\n console.log(`-> ${version}:`);\n console.log(news[version].en);\n }\n } catch {\n // ignore\n }\n }\n } else if (isDowngrade) {\n for (const version in news) {\n try {\n if (semver.gt(version, targetVersion) && semver.lte(version, installedVersion)) {\n if (first === true) {\n const noMissingNews = news[targetVersion] && news[installedVersion];\n console.log(\n `\\nThis downgrade of \"${adapter}\" will ${\n noMissingNews ? '' : 'at least '\n }remove the following changes:`\n );\n console.log(\n '=========================================================================='\n );\n first = false;\n } else if (first === false) {\n console.log();\n }\n console.log(`-> ${version}`);\n console.log(news[version].en);\n }\n } catch {\n // ignore\n }\n }\n }\n if (first === false) {\n console.log('==========================================================================\\n');\n }\n }\n\n let answer;\n\n // ask user if he really wants to upgrade/downgrade/reinstall - repeat until (y)es or (n)o given\n do {\n if (isUpgrade || isDowngrade) {\n if (isMajor) {\n console.log(\n `BE CAREFUL: THIS IS A MAJOR ${\n isUpgrade ? 'UPGRADE' : 'DOWNGRADE'\n }, WHICH WILL MOST LIKELY INTRODUCE BREAKING CHANGES!`\n );\n }\n answer = rl.question(\n `Would you like to ${\n isUpgrade ? 'upgrade' : 'downgrade'\n } ${adapter} from @${installedVersion} to @${\n version || repoAdapter.version\n } now? [(y)es, (n)o]: `,\n {\n defaultInput: 'n'\n }\n );\n } else {\n answer = rl.question(\n `Would you like to reinstall version ${\n version || repoAdapter.version\n } of ${adapter} now? [(y)es, (n)o]: `,\n {\n defaultInput: 'n'\n }\n );\n }\n\n answer = answer.toLowerCase();\n\n if (answer === 'n' || answer === 'no') {\n return false;\n }\n } while (answer !== 'y' && answer !== 'yes');\n return true;\n };\n\n // If version is included in repository\n if (repoAdapter.version) {\n if (!forceDowngrade) {\n try {\n await this._checkDependencies(repoAdapter.dependencies, repoAdapter.globalDependencies);\n } catch (e) {\n return console.error(`Cannot check dependencies: ${e.message}`);\n }\n }\n\n if (\n !forceDowngrade &&\n (repoAdapter.version === installedVersion || tools.upToDate(repoAdapter.version, installedVersion))\n ) {\n return console.log(\n `Adapter \"${adapter}\"${\n adapter.length < 15 ? new Array(15 - adapter.length).join(' ') : ''\n } is up to date.`\n );\n } else {\n const targetVersion = version || repoAdapter.version;\n\n const isIgnored = await isVersionIgnored({\n adapterName: adapter,\n version: targetVersion,\n objects: this.objects\n });\n\n if (isIgnored) {\n console.log(\n `No upgrade of \"${adapter}\" desired, because version \"${targetVersion}\" is configured to be ignored by the user. Run \"${tools.appNameLowerCase} version ${adapter} --recognize\" to allow this upgrade!`\n );\n return;\n }\n\n try {\n if (!showUpgradeDialog(installedVersion, targetVersion, adapter)) {\n console.log(`No upgrade of \"${adapter}\" desired.`);\n return;\n }\n } catch (e) {\n console.log(`Can not check version information to display upgrade infos: ${e.message}`);\n }\n console.log(`Update ${adapter} from @${installedVersion} to @${targetVersion}`);\n const npmPacketName = `${tools.appNameLowerCase}.${adapter}`;\n\n try {\n if (!semver.diff(installedVersion, targetVersion)) {\n console.log(`Uninstall npm packet \"${npmPacketName}\" for a clean re-installation`);\n await tools.uninstallNodeModule(npmPacketName, { debug: process.argv.includes('--debug') });\n }\n } catch (e) {\n console.warn(`Could not uninstall npm packet \"${npmPacketName}\": ${e.message}`);\n }\n\n // Get the adapter from website\n const { packetName, stoppedList } = await this.install.downloadPacket(\n sources,\n `${adapter}@${targetVersion}`\n );\n await finishUpgrade(packetName);\n await this.install.enableInstances(stoppedList, true);\n }\n } else if (repoAdapter.meta) {\n // Read repository from url or file\n const ioPack = (await tools.getJsonAsync(repoAdapter.meta)) as ioBroker.AdapterObject;\n if (!ioPack) {\n console.error(`Cannot parse file${repoAdapter.meta}`);\n return;\n }\n\n if (!forceDowngrade) {\n try {\n // @ts-expect-error https://github.com/ioBroker/adapter-core/issues/455\n await this._checkDependencies(ioPack.common.dependencies, ioPack.common.globalDependencies);\n } catch (e) {\n console.error(`Cannot check dependencies: ${e.message}`);\n return;\n }\n }\n\n if (\n !version &&\n (ioPack.common.version === installedVersion ||\n (!forceDowngrade && tools.upToDate(ioPack.common.version, installedVersion)))\n ) {\n console.log(\n `Adapter \"${adapter}\"${\n adapter.length < 15 ? new Array(15 - adapter.length).join(' ') : ''\n } is up to date.`\n );\n } else {\n // Get the adapter from web site\n const targetVersion = version || ioPack.common.version;\n\n const isIgnored = await isVersionIgnored({\n adapterName: adapter,\n version: targetVersion,\n objects: this.objects\n });\n\n if (isIgnored) {\n console.log(\n `No upgrade of \"${adapter}\" desired, because version \"${targetVersion}\" is configured to be ignored by the user. Run \"${tools.appNameLowerCase} version ${adapter} --recognize\" to allow this upgrade!`\n );\n return;\n }\n\n try {\n if (!showUpgradeDialog(installedVersion, targetVersion, adapter)) {\n console.log(`No upgrade of \"${adapter}\" desired.`);\n return;\n }\n } catch (e) {\n console.log(`Can not check version information to display upgrade infos: ${e.message}`);\n }\n console.log(`Update ${adapter} from @${installedVersion} to @${targetVersion}`);\n const { packetName, stoppedList } = await this.install.downloadPacket(\n sources,\n `${adapter}@${targetVersion}`\n );\n await finishUpgrade(packetName, ioPack);\n await this.install.enableInstances(stoppedList, true);\n }\n } else if (forceDowngrade) {\n try {\n if (!showUpgradeDialog(installedVersion, version, adapter)) {\n return console.log(`No upgrade of \"${adapter}\" desired.`);\n }\n } catch (e) {\n console.log(`Can not check version information to display upgrade infos: ${e.message}`);\n }\n console.warn(`Unable to get version for \"${adapter}\". Update anyway.`);\n console.log(`Update ${adapter} from @${installedVersion} to @${version}`);\n // Get the adapter from website\n const { packetName, stoppedList } = await this.install.downloadPacket(sources, `${adapter}@${version}`);\n await finishUpgrade(packetName);\n await this.install.enableInstances(stoppedList, true);\n } else {\n return console.error(`Unable to get version for \"${adapter}\".`);\n }\n }\n\n /**\n * Upgrade the js-controller\n *\n * @param repoUrl the repo or url\n * @param forceDowngrade if downgrades are allowed\n * @param controllerRunning if controller is currently running\n */\n async upgradeController(repoUrl: string, forceDowngrade: boolean, controllerRunning: boolean): Promise<void> {\n let sources: Record<string, any>;\n\n try {\n const result = await getRepository({ repoName: repoUrl, objects: this.objects });\n if (!result) {\n return console.warn(`Cannot get repository under \"${repoUrl}\"`);\n }\n sources = result;\n } catch (e) {\n console.error(e.message);\n return this.processExit(e instanceof IoBrokerError ? e.code : e);\n }\n\n const installed = fs.readJSONSync(`${tools.getControllerDir()}/io-package.json`);\n if (!installed || !installed.common || !installed.common.version) {\n return console.error(\n `Host \"${this.hostname}\"${\n this.hostname.length < 15 ? ''.padStart(15 - this.hostname.length) : ''\n } is not installed.`\n );\n }\n\n const controllerName = installed.common.name;\n /** Repository entry of the controller */\n const repoController = sources[controllerName];\n\n if (!repoController) {\n // no info for controller\n return console.error(`Cannot find this controller \"${controllerName}\" in repository.`);\n }\n\n if (repoController.version) {\n if (\n !forceDowngrade &&\n (repoController.version === installed.common.version ||\n tools.upToDate(repoController.version, installed.common.version))\n ) {\n console.log(\n `Host \"${this.hostname}\"${\n this.hostname.length < 15 ? new Array(15 - this.hostname.length).join(' ') : ''\n } is up to date.`\n );\n } else if (controllerRunning) {\n console.warn(`Controller is running. Please stop ioBroker first.`);\n } else {\n console.log(`Update ${controllerName} from @${installed.common.version} to @${repoController.version}`);\n // Get the controller from website\n await this.install.downloadPacket(sources, `${controllerName}@${repoController.version}`, {\n stopDb: true\n });\n }\n } else {\n const ioPack = await tools.getJsonAsync(repoController.meta);\n if ((!ioPack || !ioPack.common) && !forceDowngrade) {\n return console.warn(\n `Cannot read version. Write \"${tools.appName} upgrade self --force\" to upgrade controller anyway.`\n );\n }\n let version = ioPack?.common ? ioPack.common.version : '';\n if (version) {\n version = `@${version}`;\n }\n\n if (\n (ioPack?.common && ioPack.common.version === installed.common.version) ||\n (!forceDowngrade && ioPack?.common && tools.upToDate(ioPack.common.version, installed.common.version))\n ) {\n console.log(\n `Host \"${this.hostname}\"${\n this.hostname.length < 15 ? new Array(15 - this.hostname.length).join(' ') : ''\n } is up to date.`\n );\n } else if (controllerRunning) {\n console.warn(`Controller is running. Please stop ioBroker first.`);\n } else {\n const name = ioPack?.common?.name || controllerName;\n console.log(`Update ${name} from @${installed.common.version} to ${version}`);\n // Get the controller from website\n await this.install.downloadPacket(sources, name + version, { stopDb: true });\n }\n }\n }\n}\n"],
4
+ "sourcesContent": ["import Debug from 'debug';\nimport fs from 'fs-extra';\nimport { tools, EXIT_CODES } from '@iobroker/js-controller-common';\nimport semver from 'semver';\nimport { Upload } from '@/lib/setup/setupUpload.js';\nimport { Install } from '@/lib/setup/setupInstall.js';\nimport rl from 'readline-sync';\nimport tty from 'node:tty';\nimport path from 'node:path';\nimport { getRepository, isVersionIgnored } from '@/lib/setup/utils.js';\nimport type { Client as ObjectsInRedisClient } from '@iobroker/db-objects-redis';\nimport type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { ProcessExitCallback } from '@/lib/_Types.js';\nimport { IoBrokerError } from '@/lib/setup/customError.js';\n\nconst debug = Debug('iobroker:cli');\n\ntype IoPackDependencies = string[] | Record<string, any>[] | Record<string, any>;\n\ninterface CLIUpgradeOptions {\n processExit: ProcessExitCallback;\n objects: ObjectsInRedisClient;\n states: StatesInRedisClient;\n params: Record<string, any>;\n}\n\nexport class Upgrade {\n private readonly hostname = tools.getHostName();\n private readonly upload: Upload;\n private readonly install: Install;\n private readonly objects: ObjectsInRedisClient;\n private readonly processExit: ProcessExitCallback;\n\n constructor(options: CLIUpgradeOptions) {\n options = options || {};\n\n if (!options.processExit) {\n throw new Error('Invalid arguments: processExit is missing');\n }\n\n this.processExit = options.processExit;\n this.objects = options.objects;\n\n this.upload = new Upload(options);\n this.install = new Install(options);\n }\n\n /**\n * Sorts the adapters by their dependencies and then upgrades multiple adapters from the given repository url\n *\n * @param repo the repository content\n * @param list list of adapters to upgrade\n * @param forceDowngrade flag to force downgrade\n * @param autoConfirm automatically confirm the tty questions (bypass)\n */\n async upgradeAdapterHelper(\n repo: Record<string, any>,\n list: string[],\n forceDowngrade: boolean,\n autoConfirm: boolean\n ): Promise<void> {\n const relevantAdapters = [];\n // check which adapters are upgradeable and sort them according to their dependencies\n for (const adapter of list) {\n if (repo[adapter].controller) {\n // skip controller\n continue;\n }\n const adapterDir = tools.getAdapterDir(adapter);\n if (adapterDir && fs.existsSync(path.join(adapterDir, 'io-package.json'))) {\n const ioInstalled = fs.readJsonSync(path.join(adapterDir, 'io-package.json'));\n if (!tools.upToDate(repo[adapter].version, ioInstalled.common.version)) {\n // not up to date, we need to put it into account for our dependency check\n relevantAdapters.push(adapter);\n }\n }\n }\n\n if (relevantAdapters.length) {\n const sortedAdapters = [];\n\n while (relevantAdapters.length) {\n let oneAdapterAdded = false;\n // create an ordered list for upgrades\n for (let i = relevantAdapters.length - 1; i >= 0; i--) {\n const relAdapter = relevantAdapters[i];\n // if a new version has no dependencies, we can upgrade\n if (!repo[relAdapter].dependencies && !repo[relAdapter].globalDependencies) {\n // no deps, simply add it\n sortedAdapters.push(relAdapter);\n relevantAdapters.splice(relevantAdapters.indexOf(relAdapter), 1);\n oneAdapterAdded = true;\n } else {\n const allDeps: Record<string, string> = {\n ...tools.parseDependencies(repo[relAdapter].dependencies),\n ...tools.parseDependencies(repo[relAdapter].globalDependencies)\n };\n\n // we have to check if the deps are there\n let conflict = false;\n for (const [depName, version] of Object.entries(allDeps)) {\n debug(`adapter \"${relAdapter}\" has dependency \"${depName}\": \"${version}\"`);\n if (version !== '*') {\n // dependency is important because it affects the version range\n if (relevantAdapters.includes(depName)) {\n // the dependency is also in the upgrade list and not previously added, we should add the dependency first\n debug(`conflict for dependency \"${depName}\" at adapter \"${relAdapter}\"`);\n conflict = true;\n break;\n }\n }\n }\n // we reached here and no conflict, so every dep is satisfied\n if (!conflict) {\n sortedAdapters.push(relAdapter);\n relevantAdapters.splice(relevantAdapters.indexOf(relAdapter), 1);\n oneAdapterAdded = true;\n }\n }\n }\n\n if (!oneAdapterAdded) {\n // no adapter during this loop -> circular dependency\n console.warn(`Circular dependency detected between adapters \"${relevantAdapters.join(', ')}\"`);\n sortedAdapters.concat(relevantAdapters);\n break; // however, break and try to update\n }\n }\n\n debug(`upgrade order is \"${sortedAdapters.join(', ')}\"`);\n\n for (const sortedAdapter of sortedAdapters) {\n if (repo[sortedAdapter]?.controller) {\n continue;\n }\n await this.upgradeAdapter(repo, sortedAdapter, forceDowngrade, autoConfirm, true);\n }\n } else {\n console.log('All adapters are up to date');\n }\n }\n\n /**\n * Checks that local and global deps are fulfilled else rejects promise\n *\n * @param deps local dependencies - required on this host\n * @param globalDeps global dependencies - required on one of the hosts\n */\n private async _checkDependencies(deps: IoPackDependencies, globalDeps: IoPackDependencies): Promise<void> {\n if (!deps && !globalDeps) {\n return Promise.resolve();\n }\n\n deps = tools.parseDependencies(deps);\n globalDeps = tools.parseDependencies(globalDeps);\n // combine both dependencies\n const allDeps = { ...deps, ...globalDeps };\n\n // Get all installed adapters\n let objs;\n try {\n objs = await this.objects.getObjectViewAsync(\n 'system',\n 'instance',\n {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999'\n },\n undefined\n );\n } catch (e) {\n return Promise.reject(e);\n }\n\n if (objs?.rows?.length) {\n for (const dName in allDeps) {\n if (dName === 'js-controller') {\n const version = allDeps[dName];\n // Check only if version not *, else we don't have to read io-pack unnecessarily\n if (version !== '*') {\n const iopkg_ = fs.readJSONSync(`${tools.getControllerDir()}/package.json`);\n try {\n if (!semver.satisfies(iopkg_.version, version, { includePrerelease: true })) {\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${iopkg_.version}\", required \"${version}`\n )\n );\n }\n } catch (e) {\n console.log(`Can not check js-controller dependency requirement: ${e.message}`);\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${iopkg_.version}\", required \"${version}`\n )\n );\n }\n }\n } else {\n let gInstances: ioBroker.GetObjectViewItem<ioBroker.InstanceObject>[] = [];\n let locInstances: ioBroker.GetObjectViewItem<ioBroker.InstanceObject>[] = [];\n // if global dep get all instances of adapter\n if (globalDeps[dName] !== undefined) {\n gInstances = objs.rows.filter(obj => obj.value.common && obj.value.common.name === dName);\n }\n if (deps[dName] !== undefined) {\n // local dependencies: get all instances on the same host\n locInstances = objs.rows.filter(\n obj =>\n obj.value.common &&\n obj.value.common.name === dName &&\n obj.value.common.host === this.hostname\n );\n if (locInstances.length === 0) {\n return Promise.reject(new Error(`Required dependency \"${dName}\" not found on this host.`));\n }\n }\n\n let isFound = false;\n // we check that all instances match - respect different local and global dep versions\n for (const instance of locInstances) {\n const instanceVersion = instance.value.common.version;\n try {\n if (\n !semver.satisfies(instanceVersion, deps[dName], {\n includePrerelease: true\n })\n ) {\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${deps[dName]}`\n )\n );\n }\n } catch (e) {\n console.log(`Can not check dependency requirement: ${e.message}`);\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${deps[dName]}`\n )\n );\n }\n isFound = true;\n }\n\n for (const instance of gInstances) {\n const instanceVersion = instance.value.common.version;\n try {\n if (\n !semver.satisfies(instanceVersion, globalDeps[dName], {\n includePrerelease: true\n })\n ) {\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${globalDeps[dName]}`\n )\n );\n }\n } catch (e) {\n console.log(`Can not check dependency requirement: ${e.message}`);\n return Promise.reject(\n new Error(\n `Invalid version of \"${dName}\". Installed \"${instanceVersion}\", required \"${globalDeps[dName]}`\n )\n );\n }\n isFound = true;\n }\n\n if (isFound === false) {\n return Promise.reject(new Error(`Required dependency \"${dName}\" not found.`));\n }\n }\n }\n }\n }\n\n /**\n * Try to async upgrade adapter from a given source with some checks\n *\n * @param repoUrlOrObject url of the selected repository or parsed repo, if undefined, use current active repository\n * @param adapter name of the adapter (can also include version like web@3.0.0)\n * @param forceDowngrade flag to force downgrade\n * @param autoConfirm automatically confirm the tty questions (bypass)\n * @param upgradeAll if true, this is an upgrade all call, we don't do major upgrades if no tty\n */\n async upgradeAdapter(\n repoUrlOrObject: string | Record<string, any> | undefined,\n adapter: string,\n forceDowngrade: boolean,\n autoConfirm: boolean,\n upgradeAll: boolean\n ): Promise<void> {\n let sources: Record<string, any>;\n if (!repoUrlOrObject || !tools.isObject(repoUrlOrObject)) {\n try {\n sources = await getRepository({ repoName: repoUrlOrObject, objects: this.objects });\n } catch (e) {\n console.error(e.message);\n return this.processExit(e instanceof IoBrokerError ? e.code : e);\n }\n } else {\n sources = repoUrlOrObject;\n }\n\n let version: string;\n if (adapter.includes('@')) {\n const parts = adapter.split('@');\n adapter = parts[0];\n version = parts[1];\n } else {\n version = '';\n }\n if (version) {\n forceDowngrade = true;\n }\n\n /** Repository entry of this adapter */\n const repoAdapter: Record<string, any> = sources[adapter];\n\n // TODO: not really adapter object but close enough\n const finishUpgrade = async (name: string, ioPack?: ioBroker.AdapterObject): Promise<void> => {\n if (!ioPack) {\n const adapterDir = tools.getAdapterDir(name);\n\n if (!adapterDir) {\n console.error(`Cannot find io-package.json in ${adapterDir}`);\n return this.processExit(EXIT_CODES.MISSING_ADAPTER_FILES);\n }\n\n try {\n // close enough to an AdapterObject\n ioPack = fs.readJSONSync(path.join(adapterDir, 'io-package.json')) as ioBroker.AdapterObject;\n } catch {\n console.error(`Cannot find io-package.json in ${adapterDir}`);\n return this.processExit(EXIT_CODES.MISSING_ADAPTER_FILES);\n }\n }\n\n if (ioPack.common.osDependencies) {\n // install linux/osx libraries\n await this.install.installOSPackages(ioPack.common.osDependencies);\n }\n\n // Upload www and admin files of adapter\n await this.upload.uploadAdapter(name, false, true);\n // extend all adapter instance default configs with current config\n // (introduce potentially new attributes while keeping current settings)\n await this.upload.upgradeAdapterObjects(name, ioPack);\n await this.upload.uploadAdapter(name, true, true);\n };\n\n const adapterDir = tools.getAdapterDir(adapter);\n\n // Read the actual description of installed adapter with a version\n if (!adapterDir || (!version && !fs.existsSync(path.join(adapterDir, 'io-package.json')))) {\n return console.log(\n `Adapter \"${adapter}\"${\n adapter.length < 15 ? new Array(15 - adapter.length).join(' ') : ''\n } is not installed.`\n );\n }\n // Get the url of io-package.json or direct the version\n if (!repoAdapter) {\n console.log(`Adapter \"${adapter}\" is not in the repository and cannot be updated.`);\n return this.processExit(EXIT_CODES.ADAPTER_NOT_FOUND);\n }\n if (repoAdapter.controller) {\n return console.log(\n `Cannot update ${adapter} using this command. Please use \"iobroker upgrade self\" instead!`\n );\n }\n\n // TODO: not 100 % true but should be correct enough\n let ioInstalled: Pick<ioBroker.AdapterObject, 'common'>;\n if (adapterDir && fs.existsSync(path.join(adapterDir, 'io-package.json'))) {\n ioInstalled = fs.readJsonSync(`${adapterDir}/io-package.json`);\n } else {\n // @ts-expect-error https://github.com/ioBroker/adapter-core/issues/455\n ioInstalled = { common: { version: '0.0.0' } };\n }\n\n const installedVersion = ioInstalled.common.version;\n\n /**\n * We show changelog (news) and ask user if he really wants to upgrade but only if fd is associated with a tty, returns true if upgrade desired\n *\n * @param installedVersion - installed version of adapter\n * @param targetVersion - target version of adapter\n * @param adapterName - name of the adapter\n */\n const showUpgradeDialog = (installedVersion: string, targetVersion: string, adapterName: string): boolean => {\n // major upgrade or downgrade\n const isMajor = semver.major(installedVersion) !== semver.major(targetVersion);\n\n if (autoConfirm || (!tty.isatty(process.stdout.fd) && (!isMajor || !upgradeAll))) {\n // force flag or script on non-major or single adapter upgrade -> always upgrade\n return true;\n }\n\n if (!tty.isatty(process.stdout.fd) && isMajor && upgradeAll) {\n // no tty and not forced and multiple adapters, do not upgrade\n console.log(`Skip major upgrade of ${adapterName} from ${installedVersion} to ${targetVersion}`);\n return false;\n }\n\n const isUpgrade = semver.gt(targetVersion, installedVersion);\n const isDowngrade = semver.lt(targetVersion, installedVersion);\n\n // if information in repo files -> show news\n if (repoAdapter?.news) {\n const news = repoAdapter.news;\n\n let first = true;\n // check if upgrade or downgrade\n if (isUpgrade) {\n for (const version in news) {\n try {\n if (semver.lte(version, targetVersion) && semver.gt(version, installedVersion)) {\n if (first === true) {\n const noMissingNews = news[targetVersion] && news[installedVersion];\n console.log(\n `\\nThis upgrade of \"${adapter}\" will ${\n noMissingNews ? '' : 'at least '\n }introduce the following changes:`\n );\n console.log(\n '=========================================================================='\n );\n first = false;\n } else if (first === false) {\n console.log();\n }\n console.log(`-> ${version}:`);\n console.log(news[version].en);\n }\n } catch {\n // ignore\n }\n }\n } else if (isDowngrade) {\n for (const version in news) {\n try {\n if (semver.gt(version, targetVersion) && semver.lte(version, installedVersion)) {\n if (first === true) {\n const noMissingNews = news[targetVersion] && news[installedVersion];\n console.log(\n `\\nThis downgrade of \"${adapter}\" will ${\n noMissingNews ? '' : 'at least '\n }remove the following changes:`\n );\n console.log(\n '=========================================================================='\n );\n first = false;\n } else if (first === false) {\n console.log();\n }\n console.log(`-> ${version}`);\n console.log(news[version].en);\n }\n } catch {\n // ignore\n }\n }\n }\n if (first === false) {\n console.log('==========================================================================\\n');\n }\n }\n\n let answer;\n\n // ask user if he really wants to upgrade/downgrade/reinstall - repeat until (y)es or (n)o given\n do {\n if (isUpgrade || isDowngrade) {\n if (isMajor) {\n console.log(\n `BE CAREFUL: THIS IS A MAJOR ${\n isUpgrade ? 'UPGRADE' : 'DOWNGRADE'\n }, WHICH WILL MOST LIKELY INTRODUCE BREAKING CHANGES!`\n );\n }\n answer = rl.question(\n `Would you like to ${\n isUpgrade ? 'upgrade' : 'downgrade'\n } ${adapter} from @${installedVersion} to @${\n version || repoAdapter.version\n } now? [(y)es, (n)o]: `,\n {\n defaultInput: 'n'\n }\n );\n } else {\n answer = rl.question(\n `Would you like to reinstall version ${\n version || repoAdapter.version\n } of ${adapter} now? [(y)es, (n)o]: `,\n {\n defaultInput: 'n'\n }\n );\n }\n\n answer = answer.toLowerCase();\n\n if (answer === 'n' || answer === 'no') {\n return false;\n }\n } while (answer !== 'y' && answer !== 'yes');\n return true;\n };\n\n // If a version is included in the repository\n if (repoAdapter.version) {\n if (!forceDowngrade) {\n try {\n await this._checkDependencies(repoAdapter.dependencies, repoAdapter.globalDependencies);\n } catch (e) {\n return console.error(`Cannot check dependencies: ${e.message}`);\n }\n }\n\n if (\n !forceDowngrade &&\n (repoAdapter.version === installedVersion || tools.upToDate(repoAdapter.version, installedVersion))\n ) {\n return console.log(\n `Adapter \"${adapter}\"${\n adapter.length < 15 ? new Array(15 - adapter.length).join(' ') : ''\n } is up to date.`\n );\n } else {\n const targetVersion = version || repoAdapter.version;\n\n const isIgnored = await isVersionIgnored({\n adapterName: adapter,\n version: targetVersion,\n objects: this.objects\n });\n\n if (isIgnored) {\n console.log(\n `No upgrade of \"${adapter}\" desired, because version \"${targetVersion}\" is configured to be ignored by the user. Run \"${tools.appNameLowerCase} version ${adapter} --recognize\" to allow this upgrade!`\n );\n return;\n }\n\n try {\n if (!showUpgradeDialog(installedVersion, targetVersion, adapter)) {\n console.log(`No upgrade of \"${adapter}\" desired.`);\n return;\n }\n } catch (e) {\n console.log(`Can not check version information to display upgrade infos: ${e.message}`);\n }\n console.log(`Update ${adapter} from @${installedVersion} to @${targetVersion}`);\n const npmPacketName = `${tools.appNameLowerCase}.${adapter}`;\n\n try {\n if (!semver.diff(installedVersion, targetVersion)) {\n console.log(`Uninstall npm packet \"${npmPacketName}\" for a clean re-installation`);\n await tools.uninstallNodeModule(npmPacketName, { debug: process.argv.includes('--debug') });\n }\n } catch (e) {\n console.warn(`Could not uninstall npm packet \"${npmPacketName}\": ${e.message}`);\n }\n\n // Get the adapter from website\n const { packetName, stoppedList } = await this.install.downloadPacket(\n sources,\n `${adapter}@${targetVersion}`\n );\n await finishUpgrade(packetName);\n await this.install.enableInstances(stoppedList, true);\n }\n } else if (repoAdapter.meta) {\n // Read repository from url or file\n const ioPack = (await tools.getJsonAsync(repoAdapter.meta)) as ioBroker.AdapterObject;\n if (!ioPack) {\n console.error(`Cannot parse file${repoAdapter.meta}`);\n return;\n }\n\n if (!forceDowngrade) {\n try {\n // @ts-expect-error https://github.com/ioBroker/adapter-core/issues/455\n await this._checkDependencies(ioPack.common.dependencies, ioPack.common.globalDependencies);\n } catch (e) {\n console.error(`Cannot check dependencies: ${e.message}`);\n return;\n }\n }\n\n if (\n !version &&\n (ioPack.common.version === installedVersion ||\n (!forceDowngrade && tools.upToDate(ioPack.common.version, installedVersion)))\n ) {\n console.log(\n `Adapter \"${adapter}\"${\n adapter.length < 15 ? new Array(15 - adapter.length).join(' ') : ''\n } is up to date.`\n );\n } else {\n // Get the adapter from website\n const targetVersion = version || ioPack.common.version;\n\n const isIgnored = await isVersionIgnored({\n adapterName: adapter,\n version: targetVersion,\n objects: this.objects\n });\n\n if (isIgnored) {\n console.log(\n `No upgrade of \"${adapter}\" desired, because version \"${targetVersion}\" is configured to be ignored by the user. Run \"${tools.appNameLowerCase} version ${adapter} --recognize\" to allow this upgrade!`\n );\n return;\n }\n\n try {\n if (!showUpgradeDialog(installedVersion, targetVersion, adapter)) {\n console.log(`No upgrade of \"${adapter}\" desired.`);\n return;\n }\n } catch (e) {\n console.log(`Can not check version information to display upgrade infos: ${e.message}`);\n }\n console.log(`Update ${adapter} from @${installedVersion} to @${targetVersion}`);\n const { packetName, stoppedList } = await this.install.downloadPacket(\n sources,\n `${adapter}@${targetVersion}`\n );\n await finishUpgrade(packetName, ioPack);\n await this.install.enableInstances(stoppedList, true);\n }\n } else if (forceDowngrade) {\n try {\n if (!showUpgradeDialog(installedVersion, version, adapter)) {\n return console.log(`No upgrade of \"${adapter}\" desired.`);\n }\n } catch (e) {\n console.log(`Can not check version information to display upgrade infos: ${e.message}`);\n }\n console.warn(`Unable to get version for \"${adapter}\". Update anyway.`);\n console.log(`Update ${adapter} from @${installedVersion} to @${version}`);\n // Get the adapter from website\n const { packetName, stoppedList } = await this.install.downloadPacket(sources, `${adapter}@${version}`);\n await finishUpgrade(packetName);\n await this.install.enableInstances(stoppedList, true);\n } else {\n return console.error(`Unable to get version for \"${adapter}\".`);\n }\n }\n\n /**\n * Upgrade the js-controller\n *\n * @param repoUrl the repo or url\n * @param forceDowngrade if downgrades are allowed\n * @param controllerRunning if controller is currently running\n */\n async upgradeController(repoUrl: string, forceDowngrade: boolean, controllerRunning: boolean): Promise<void> {\n let sources: Record<string, any>;\n\n try {\n const result = await getRepository({ repoName: repoUrl, objects: this.objects });\n if (!result) {\n return console.warn(`Cannot get repository under \"${repoUrl}\"`);\n }\n sources = result;\n } catch (e) {\n console.error(e.message);\n return this.processExit(e instanceof IoBrokerError ? e.code : e);\n }\n\n const installed = fs.readJSONSync(`${tools.getControllerDir()}/io-package.json`);\n if (!installed || !installed.common || !installed.common.version) {\n return console.error(\n `Host \"${this.hostname}\"${\n this.hostname.length < 15 ? ''.padStart(15 - this.hostname.length) : ''\n } is not installed.`\n );\n }\n\n const controllerName = installed.common.name;\n /** Repository entry of the controller */\n const repoController = sources[controllerName];\n\n if (!repoController) {\n // no info for controller\n return console.error(`Cannot find this controller \"${controllerName}\" in repository.`);\n }\n\n if (repoController.version) {\n if (\n !forceDowngrade &&\n (repoController.version === installed.common.version ||\n tools.upToDate(repoController.version, installed.common.version))\n ) {\n console.log(\n `Host \"${this.hostname}\"${\n this.hostname.length < 15 ? new Array(15 - this.hostname.length).join(' ') : ''\n } is up to date.`\n );\n } else if (controllerRunning) {\n console.warn(`Controller is running. Please stop ioBroker first.`);\n } else {\n console.log(`Update ${controllerName} from @${installed.common.version} to @${repoController.version}`);\n // Get the controller from website\n await this.install.downloadPacket(sources, `${controllerName}@${repoController.version}`, {\n stopDb: true\n });\n }\n } else {\n const ioPack = await tools.getJsonAsync(repoController.meta);\n if ((!ioPack || !ioPack.common) && !forceDowngrade) {\n return console.warn(\n `Cannot read version. Write \"${tools.appName} upgrade self --force\" to upgrade controller anyway.`\n );\n }\n let version = ioPack?.common ? ioPack.common.version : '';\n if (version) {\n version = `@${version}`;\n }\n\n if (\n (ioPack?.common && ioPack.common.version === installed.common.version) ||\n (!forceDowngrade && ioPack?.common && tools.upToDate(ioPack.common.version, installed.common.version))\n ) {\n console.log(\n `Host \"${this.hostname}\"${\n this.hostname.length < 15 ? new Array(15 - this.hostname.length).join(' ') : ''\n } is up to date.`\n );\n } else if (controllerRunning) {\n console.warn(`Controller is running. Please stop ioBroker first.`);\n } else {\n const name = ioPack?.common?.name || controllerName;\n console.log(`Update ${name} from @${installed.common.version} to ${version}`);\n // Get the controller from website\n await this.install.downloadPacket(sources, name + version, { stopDb: true });\n }\n }\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["Debug", "fs", "path", "semver", "adapterDir", "installedVersion", "tty", "version", "rl"]
7
7
  }
@@ -6,7 +6,7 @@ interface GetRepositoryOptions {
6
6
  repoName?: string;
7
7
  }
8
8
  /**
9
- * Get json of the given repository
9
+ * Get JSON of the given repository
10
10
  *
11
11
  * @param options Repository specific options
12
12
  */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/setup/utils.ts"],
4
- "sourcesContent": ["import { EXIT_CODES } from '@iobroker/js-controller-common';\nimport { tools } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsClient } from '@iobroker/db-objects-redis';\nimport semver from 'semver';\nimport { IoBrokerError } from '@/lib/setup/customError.js';\n\ninterface GetRepositoryOptions {\n /** The objects DB client */\n objects: ObjectsClient;\n /** Name of the repository */\n repoName?: string;\n}\n\n/**\n * Get json of the given repository\n *\n * @param options Repository specific options\n */\nexport async function getRepository(options: GetRepositoryOptions): Promise<Record<string, any>> {\n const { objects } = options;\n const { repoName } = options;\n\n let repoNameOrArray: string | string[] | undefined = repoName;\n if (!repoName || repoName === 'auto') {\n const systemConfig = await objects!.getObjectAsync('system.config');\n repoNameOrArray = systemConfig!.common.activeRepo;\n }\n\n const repoArr = !Array.isArray(repoNameOrArray) ? [repoNameOrArray!] : repoNameOrArray;\n\n const systemRepos = (await objects!.getObjectAsync('system.repositories'))!;\n\n const allSources = {};\n let changed = false;\n let anyFound = false;\n for (const repoUrl of repoArr) {\n const repo = systemRepos.native.repositories[repoUrl];\n if (repo) {\n if (typeof repo === 'string') {\n systemRepos.native.repositories[repo] = {\n link: repo,\n json: null\n };\n changed = true;\n }\n\n // If repo is not yet loaded\n if (!systemRepos.native.repositories[repoUrl].json) {\n console.log(`Update repository \"${repoUrl}\" under \"${systemRepos.native.repositories[repoUrl].link}\"`);\n const data = await tools.getRepositoryFileAsync(systemRepos.native.repositories[repoUrl].link);\n systemRepos.native.repositories[repoUrl].json = data.json;\n systemRepos.native.repositories[repoUrl].hash = data.hash;\n systemRepos.from = `system.host.${tools.getHostName()}.cli`;\n systemRepos.ts = new Date().getTime();\n changed = true;\n }\n\n if (systemRepos.native.repositories[repoUrl].json) {\n Object.assign(allSources, systemRepos.native.repositories[repoUrl].json);\n anyFound = true;\n }\n }\n\n if (changed) {\n await objects.setObjectAsync('system.repositories', systemRepos);\n }\n }\n\n if (!anyFound) {\n let message: string;\n if (repoArr.length) {\n message = `ERROR: No repositories defined matching \"${repoArr.join(\n ' | '\n )}\". Please use one of ${Object.keys(systemRepos.native.repositories)\n .map(repo => `\"${repo}\"`)\n .join(', ')}.`;\n } else {\n message = `ERROR: No repositories defined. Please define one repository as active: \"iob repo set <${Object.keys(\n systemRepos.native.repositories\n ).join(' | ')}>\"`;\n }\n\n throw new IoBrokerError({ message, code: EXIT_CODES.INVALID_REPO });\n } else {\n return allSources;\n }\n}\n\ninterface VersionOptions {\n /** The adapter name to check the version for */\n adapterName: string;\n /** The objects DB instance */\n objects: ObjectsClient;\n}\n\ninterface IgnoreVersionOptions extends VersionOptions {\n /** The version which will be checked */\n version: string;\n}\n\n/**\n * Get info if a specific version should be ignored of this adapter\n *\n * @param options name and target version of the adapter\n */\nexport async function isVersionIgnored(options: IgnoreVersionOptions): Promise<boolean> {\n const { adapterName, version, objects } = options;\n const obj = await objects.getObject(`system.host.${tools.getHostName()}.adapter.${adapterName}`);\n\n if (obj?.common.ignoreVersion === undefined) {\n return false;\n }\n\n return semver.satisfies(version, obj?.common.ignoreVersion);\n}\n\n/**\n * Ignore a specific version of an adapter\n *\n * @param options name and target version of the adapter\n */\nexport async function ignoreVersion(options: IgnoreVersionOptions): Promise<void> {\n const { adapterName, version, objects } = options;\n const id = `system.host.${tools.getHostName()}.adapter.${adapterName}`;\n const obj = await objects.getObject(id);\n\n if (!obj) {\n throw new IoBrokerError({ code: EXIT_CODES.CANNOT_SET_OBJECT, message: `Object \"${id}\" does not exist` });\n }\n\n obj.common.ignoreVersion = version;\n\n await objects.setObject(id, obj);\n}\n\n/**\n * Recognize all updates of adapter again\n *\n * @param options name of the adapter\n */\nexport async function recognizeVersion(options: VersionOptions): Promise<void> {\n const { adapterName, objects } = options;\n const id = `system.host.${tools.getHostName()}.adapter.${adapterName}`;\n const obj = await objects.getObject(id);\n\n if (!obj) {\n throw new IoBrokerError({ code: EXIT_CODES.CANNOT_SET_OBJECT, message: `Object \"${id}\" does not exist` });\n }\n\n delete obj.common.ignoreVersion;\n\n await objects.setObject(id, obj);\n}\n"],
4
+ "sourcesContent": ["import { EXIT_CODES } from '@iobroker/js-controller-common';\nimport { tools } from '@iobroker/js-controller-common';\nimport type { Client as ObjectsClient } from '@iobroker/db-objects-redis';\nimport semver from 'semver';\nimport { IoBrokerError } from '@/lib/setup/customError.js';\n\ninterface GetRepositoryOptions {\n /** The objects DB client */\n objects: ObjectsClient;\n /** Name of the repository */\n repoName?: string;\n}\n\n/**\n * Get JSON of the given repository\n *\n * @param options Repository specific options\n */\nexport async function getRepository(options: GetRepositoryOptions): Promise<Record<string, any>> {\n const { objects } = options;\n const { repoName } = options;\n\n let repoNameOrArray: string | string[] | undefined = repoName;\n if (!repoName || repoName === 'auto') {\n const systemConfig = await objects!.getObjectAsync('system.config');\n repoNameOrArray = systemConfig!.common.activeRepo;\n }\n\n const repoArr = !Array.isArray(repoNameOrArray) ? [repoNameOrArray!] : repoNameOrArray;\n\n const systemRepos = (await objects!.getObjectAsync('system.repositories'))!;\n\n const allSources = {};\n let changed = false;\n let anyFound = false;\n for (const repoUrl of repoArr) {\n const repo = systemRepos.native.repositories[repoUrl];\n if (repo) {\n if (typeof repo === 'string') {\n systemRepos.native.repositories[repo] = {\n link: repo,\n json: null\n };\n changed = true;\n }\n\n // If repo is not yet loaded\n if (!systemRepos.native.repositories[repoUrl].json) {\n console.log(`Update repository \"${repoUrl}\" under \"${systemRepos.native.repositories[repoUrl].link}\"`);\n const data = await tools.getRepositoryFileAsync(systemRepos.native.repositories[repoUrl].link);\n systemRepos.native.repositories[repoUrl].json = data.json;\n systemRepos.native.repositories[repoUrl].hash = data.hash;\n systemRepos.from = `system.host.${tools.getHostName()}.cli`;\n systemRepos.ts = new Date().getTime();\n changed = true;\n }\n\n if (systemRepos.native.repositories[repoUrl].json) {\n Object.assign(allSources, systemRepos.native.repositories[repoUrl].json);\n anyFound = true;\n }\n }\n\n if (changed) {\n await objects.setObjectAsync('system.repositories', systemRepos);\n }\n }\n\n if (!anyFound) {\n let message: string;\n if (repoArr.length) {\n message = `ERROR: No repositories defined matching \"${repoArr.join(\n ' | '\n )}\". Please use one of ${Object.keys(systemRepos.native.repositories)\n .map(repo => `\"${repo}\"`)\n .join(', ')}.`;\n } else {\n message = `ERROR: No repositories defined. Please define one repository as active: \"iob repo set <${Object.keys(\n systemRepos.native.repositories\n ).join(' | ')}>\"`;\n }\n\n throw new IoBrokerError({ message, code: EXIT_CODES.INVALID_REPO });\n } else {\n return allSources;\n }\n}\n\ninterface VersionOptions {\n /** The adapter name to check the version for */\n adapterName: string;\n /** The objects DB instance */\n objects: ObjectsClient;\n}\n\ninterface IgnoreVersionOptions extends VersionOptions {\n /** The version which will be checked */\n version: string;\n}\n\n/**\n * Get info if a specific version should be ignored of this adapter\n *\n * @param options name and target version of the adapter\n */\nexport async function isVersionIgnored(options: IgnoreVersionOptions): Promise<boolean> {\n const { adapterName, version, objects } = options;\n const obj = await objects.getObject(`system.host.${tools.getHostName()}.adapter.${adapterName}`);\n\n if (obj?.common.ignoreVersion === undefined) {\n return false;\n }\n\n return semver.satisfies(version, obj?.common.ignoreVersion);\n}\n\n/**\n * Ignore a specific version of an adapter\n *\n * @param options name and target version of the adapter\n */\nexport async function ignoreVersion(options: IgnoreVersionOptions): Promise<void> {\n const { adapterName, version, objects } = options;\n const id = `system.host.${tools.getHostName()}.adapter.${adapterName}`;\n const obj = await objects.getObject(id);\n\n if (!obj) {\n throw new IoBrokerError({ code: EXIT_CODES.CANNOT_SET_OBJECT, message: `Object \"${id}\" does not exist` });\n }\n\n obj.common.ignoreVersion = version;\n\n await objects.setObject(id, obj);\n}\n\n/**\n * Recognize all updates of adapter again\n *\n * @param options name of the adapter\n */\nexport async function recognizeVersion(options: VersionOptions): Promise<void> {\n const { adapterName, objects } = options;\n const id = `system.host.${tools.getHostName()}.adapter.${adapterName}`;\n const obj = await objects.getObject(id);\n\n if (!obj) {\n throw new IoBrokerError({ code: EXIT_CODES.CANNOT_SET_OBJECT, message: `Object \"${id}\" does not exist` });\n }\n\n delete obj.common.ignoreVersion;\n\n await objects.setObject(id, obj);\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["import_js_controller_common", "semver"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Install adapter
3
3
  *
4
- * Copyright 2013-2023 bluefox <dogafox@gmail.com>
4
+ * Copyright 2013-2024 bluefox <dogafox@gmail.com>
5
5
  *
6
6
  * MIT License
7
7
  *
@@ -188,7 +188,7 @@ export declare class Install {
188
188
  */
189
189
  deleteInstance(adapter: string, instance?: number): Promise<void | EXIT_CODES.CANNOT_DELETE_DEPENDENCY>;
190
190
  /**
191
- * Remove all node modules which has been installed by this instance
191
+ * Remove all node modules that has been installed by this instance
192
192
  *
193
193
  * @param adapter adapter name like hm-rpc
194
194
  * @param instance e.g. 1, if undefined deletes all instances
@@ -212,7 +212,7 @@ export declare class Install {
212
212
  *
213
213
  * @param adapter adapter name
214
214
  * @param instance instance, like 1
215
- * @returns if dependent exists returns adapter name
215
+ * @returns if dependent exists, returns adapter name
216
216
  */
217
217
  private _hasDependentInstances;
218
218
  /**
@@ -221,7 +221,7 @@ export declare class Install {
221
221
  * @param adapter adapter name
222
222
  * @param instancesRows all instances objects view rows
223
223
  * @param scopedHostname hostname which should be assumed as local
224
- * @returns true if an instance is present on other host
224
+ * @returns true if an instance is present on another host
225
225
  */
226
226
  private _checkDependencyFulfilledForeignHosts;
227
227
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Install adapter
3
3
  *
4
- * Copyright 2013-2023 bluefox <dogafox@gmail.com>
4
+ * Copyright 2013-2024 bluefox <dogafox@gmail.com>
5
5
  *
6
6
  * MIT License
7
7
  *
@@ -110,7 +110,7 @@ export class Install {
110
110
  version = parts[1];
111
111
  }
112
112
  else {
113
- // always take version from repository
113
+ // always take a version from repository
114
114
  if (sources[packetName]?.version) {
115
115
  version = sources[packetName].version;
116
116
  }
@@ -178,7 +178,7 @@ export class Install {
178
178
  return { packetName, stoppedList };
179
179
  }
180
180
  }
181
- console.error(`host.${hostname} Unknown packetName ${packetName}. Please install packages from outside the repository using "${tools.appNameLowerCase} url <url-or-package>"!`);
181
+ console.error(`host.${hostname} Unknown packet name ${packetName}. Please install packages from outside the repository using "${tools.appNameLowerCase} url <url-or-package>"!`);
182
182
  throw new IoBrokerError({
183
183
  code: EXIT_CODES.UNKNOWN_PACKET_NAME,
184
184
  message: `Unknown packetName ${packetName}. Please install packages from outside the repository using npm!`
@@ -251,7 +251,7 @@ export class Install {
251
251
  npmUrl = npmUrl.substring(0, npmUrl.indexOf('#'));
252
252
  }
253
253
  if (npmUrl.includes('/') && !npmUrl.startsWith('@')) {
254
- // only scoped packages (e.g. @types/node ) may have a slash in their path
254
+ // only scoped packages (e.g., @types/node) may have a slash in their path
255
255
  npmUrl = npmUrl.substring(npmUrl.lastIndexOf('/') + 1);
256
256
  }
257
257
  if (!npmUrl.startsWith('@')) {
@@ -282,7 +282,7 @@ export class Install {
282
282
  debug: !!debug,
283
283
  unsafePerm: !!options.unsafePerm
284
284
  });
285
- // code 1 is sometimes a real error and sometimes a strange error, where everything is installed but error
285
+ // code 1 is sometimes a real error and sometimes a strange error, where everything is installed but still the error
286
286
  const isSuccess = result.success || (result.exitCode === 1 && !result.stderr.startsWith('npm ERR!'));
287
287
  if (isSuccess) {
288
288
  // Determine where the packet would be installed if npm succeeds
@@ -397,7 +397,7 @@ export class Install {
397
397
  let isFound = false;
398
398
  if (dName === 'js-controller') {
399
399
  const version = allDeps[dName];
400
- // Check only if version not *, else we dont have to read io-pack unnecessarily
400
+ // Check only if version not *, else we don't have to read io-pack unnecessarily
401
401
  if (version !== '*') {
402
402
  const packJson = fs.readJSONSync(`${tools.getControllerDir()}/package.json`);
403
403
  if (!semver.satisfies(packJson.version, version, { includePrerelease: true })) {
@@ -420,7 +420,7 @@ export class Install {
420
420
  gInstances = objs.rows.filter(obj => obj.value.common && obj.value.common.name === dName);
421
421
  }
422
422
  if (deps[dName] !== undefined) {
423
- // local dep get all instances on same host
423
+ // local dependencies: get all instances on the same host
424
424
  locInstances = objs.rows.filter(obj => obj.value.common &&
425
425
  obj.value.common.name === dName &&
426
426
  obj.value.common.host === hostname);
@@ -428,7 +428,7 @@ export class Install {
428
428
  console.error(`host.${hostname} Required dependency "${dName}" not found on this host.`);
429
429
  }
430
430
  }
431
- // we check, that all existing instances match - respect different versions for local and global deps
431
+ // we check that all existing instances match - respect different versions for local and global deps
432
432
  for (const instance of locInstances) {
433
433
  const instanceVersion = instance.value.common.version;
434
434
  if (!semver.satisfies(instanceVersion, deps[dName], {
@@ -540,7 +540,7 @@ export class Install {
540
540
  _installCount++;
541
541
  const { stoppedList } = await this.downloadPacket(repoUrl, fullName);
542
542
  await this.installAdapter(adapter, repoUrl, _installCount);
543
- await this.enableInstances(stoppedList, true); // even if unlikely make sure to reenable disabled instances
543
+ await this.enableInstances(stoppedList, true); // even if unlikely make sure to re-enable disabled instances
544
544
  return adapter;
545
545
  }
546
546
  let adapterConf;
@@ -884,7 +884,7 @@ export class Install {
884
884
  .filter(row => !!row.value._id)
885
885
  // ... that matches the pattern
886
886
  .filter(row => instanceRegex.test(row.value._id))
887
- // if instance given also delete from foreign host else only instance on this host
887
+ // if instance given, also delete it from foreign host else only instance on this host
888
888
  .filter(row => {
889
889
  if (instance !== undefined || !row.value.common?.host || row.value.common?.host === hostname) {
890
890
  return true;
@@ -1201,7 +1201,7 @@ export class Install {
1201
1201
  }
1202
1202
  while (stateIDs.length > 0) {
1203
1203
  if (stateIDs.length % 200 === 0) {
1204
- // write progress report
1204
+ // write a progress report
1205
1205
  console.log(`host.${hostname}: Only ${stateIDs.length} states left to be deleted.`);
1206
1206
  }
1207
1207
  // try to delete the current state
@@ -1209,7 +1209,7 @@ export class Install {
1209
1209
  await this.states.delState(stateIDs.pop());
1210
1210
  }
1211
1211
  catch (e) {
1212
- // yep that works!
1212
+ // yep, that works!
1213
1213
  e !== tools.ERRORS.ERROR_NOT_FOUND &&
1214
1214
  e.message !== tools.ERRORS.ERROR_NOT_FOUND &&
1215
1215
  console.error(`host.${hostname} Cannot delete states: ${e.message}`);
@@ -1235,7 +1235,7 @@ export class Install {
1235
1235
  }
1236
1236
  while (objIDs.length > 0) {
1237
1237
  if (objIDs.length % 200 === 0) {
1238
- // write progress report
1238
+ // write a progress report
1239
1239
  console.log(`host.${hostname}: Only ${objIDs.length} objects left to be deleted.`);
1240
1240
  }
1241
1241
  // try to delete the current object
@@ -1270,7 +1270,7 @@ export class Install {
1270
1270
  const ioPack = await fs.readJSON(ioPackPath);
1271
1271
  if (!ioPack.common || !ioPack.common.nondeletable) {
1272
1272
  await this._npmUninstall(adapterNpm, false);
1273
- // after uninstalling we have to restart the defined adapters
1273
+ // after uninstalling, we have to restart the defined adapters
1274
1274
  if (ioPack.common.restartAdapters) {
1275
1275
  if (!Array.isArray(ioPack.common.restartAdapters)) {
1276
1276
  // it's not an array, now it can only be a single adapter as string
@@ -1325,7 +1325,7 @@ export class Install {
1325
1325
  await _uninstallNpm();
1326
1326
  }
1327
1327
  else {
1328
- // we are not allowed to delete last instance if another instance depends on us
1328
+ // we are not allowed to delete the last instance if another instance depends on us
1329
1329
  const dependentInstance = await this._hasDependentInstances(adapter);
1330
1330
  if (dependentInstance) {
1331
1331
  console.log(`Cannot remove adapter "${adapter}", because instance "${dependentInstance}" depends on it!`);
@@ -1363,7 +1363,7 @@ export class Install {
1363
1363
  async deleteInstance(adapter, instance) {
1364
1364
  const knownObjectIDs = [];
1365
1365
  const knownStateIDs = [];
1366
- // we are not allowed to delete last instance if another instance depends on us
1366
+ // we are not allowed to delete the last instance if another instance depends on us
1367
1367
  const dependentInstance = await this._hasDependentInstances(adapter, instance);
1368
1368
  if (dependentInstance) {
1369
1369
  console.log(`Cannot remove instance "${adapter}.${instance}", because instance "${dependentInstance}" depends on it!`);
@@ -1384,7 +1384,7 @@ export class Install {
1384
1384
  }
1385
1385
  }
1386
1386
  /**
1387
- * Remove all node modules which has been installed by this instance
1387
+ * Remove all node modules that has been installed by this instance
1388
1388
  *
1389
1389
  * @param adapter adapter name like hm-rpc
1390
1390
  * @param instance e.g. 1, if undefined deletes all instances
@@ -1405,7 +1405,7 @@ export class Install {
1405
1405
  * @param ids - id of the adapter/instance to check for
1406
1406
  */
1407
1407
  async _removeCustomFromObjects(ids) {
1408
- // get all objects which have a custom attribute
1408
+ // get all objects that have a custom attribute
1409
1409
  const res = await this.objects.getObjectViewAsync('system', 'custom', {
1410
1410
  startkey: '',
1411
1411
  endkey: '\u9999'
@@ -1437,7 +1437,7 @@ export class Install {
1437
1437
  * @param name package name
1438
1438
  */
1439
1439
  async installAdapterFromUrl(url, name) {
1440
- // If the user provided an URL, try to parse it into known ways to represent a Github URL
1440
+ // If the user provided a URL, try to parse it into known ways to represent a GitHub URL
1441
1441
  let parsedUrl;
1442
1442
  try {
1443
1443
  parsedUrl = new URL(url);
@@ -1459,7 +1459,7 @@ export class Install {
1459
1459
  const result = await axios(`http://api.github.com/repos/${user}/${repo}/commits`, {
1460
1460
  headers: {
1461
1461
  'User-Agent': 'ioBroker Adapter install',
1462
- // @ts-expect-error should be okay..
1462
+ // @ts-expect-error should be okay...
1463
1463
  validateStatus: status => status === 200
1464
1464
  }
1465
1465
  });
@@ -1485,7 +1485,7 @@ export class Install {
1485
1485
  console.log(`install ${url}`);
1486
1486
  // Try to extract name from URL
1487
1487
  if (!name) {
1488
- const reNpmPacket = new RegExp('^' + tools.appName + '\\.([-_\\w\\d]+)(@.*)?$', 'i');
1488
+ const reNpmPacket = new RegExp(`^${tools.appName}\\.([-_\\w\\d]+)(@.*)?$`, 'i');
1489
1489
  const match = reNpmPacket.exec(url); // we have iobroker.adaptername@1.2.3
1490
1490
  if (match) {
1491
1491
  name = match[1];
@@ -1493,7 +1493,7 @@ export class Install {
1493
1493
  else if (url.match(/\.(tgz|gz|zip|tar\.gz)$/)) {
1494
1494
  const parts = url.split('/');
1495
1495
  const last = parts.pop();
1496
- const mm = last.match(/\.([-_\w\d]+)-[.\d]+/);
1496
+ const mm = last.match(/\.([-_\w]+)-[.\d]+/);
1497
1497
  if (mm) {
1498
1498
  name = mm[1];
1499
1499
  }
@@ -1509,7 +1509,7 @@ export class Install {
1509
1509
  name = url;
1510
1510
  }
1511
1511
  // Remove the leading `iobroker.` from the name
1512
- const reG = new RegExp(tools.appName + '\\.([-_\\w\\d]+)$', 'i');
1512
+ const reG = new RegExp(`${tools.appName}\\.([-_\\w\\d]+)$`, 'i');
1513
1513
  const match = reG.exec(name);
1514
1514
  if (match) {
1515
1515
  name = match[1];
@@ -1570,7 +1570,7 @@ export class Install {
1570
1570
  *
1571
1571
  * @param adapter adapter name
1572
1572
  * @param instance instance, like 1
1573
- * @returns if dependent exists returns adapter name
1573
+ * @returns if dependent exists, returns adapter name
1574
1574
  */
1575
1575
  async _hasDependentInstances(adapter, instance) {
1576
1576
  try {
@@ -1590,7 +1590,7 @@ export class Install {
1590
1590
  scopedHostname = scopedHostname || hostname;
1591
1591
  for (const row of doc.rows) {
1592
1592
  if (!row.value?.common) {
1593
- // this object seems to be corrupted so it will not need our adapter
1593
+ // this object seems to be corrupted, so it will not need our adapter
1594
1594
  continue;
1595
1595
  }
1596
1596
  const localDeps = tools.parseDependencies(row.value.common.dependencies);
@@ -1601,7 +1601,7 @@ export class Install {
1601
1601
  return `${row.value.common.name}.${row.id.split('.').pop()}`;
1602
1602
  }
1603
1603
  else {
1604
- // check if other instance of us exists on this host
1604
+ // check if another instance of us exists on this host
1605
1605
  if (this._checkDependencyFulfilledThisHost(adapter, instance, doc.rows, scopedHostname)) {
1606
1606
  // there are other instances of our adapter - ok
1607
1607
  break;
@@ -1616,7 +1616,7 @@ export class Install {
1616
1616
  for (const globalDep of Object.keys(globalDeps)) {
1617
1617
  if (globalDep === adapter) {
1618
1618
  if (instance === undefined) {
1619
- // all instances on this host should be removed so check if there are some on other hosts
1619
+ // all instances on this host should be removed, so check if there are some on other hosts
1620
1620
  if (this._checkDependencyFulfilledForeignHosts(adapter, doc.rows, scopedHostname)) {
1621
1621
  break;
1622
1622
  }
@@ -1646,7 +1646,7 @@ export class Install {
1646
1646
  * @param adapter adapter name
1647
1647
  * @param instancesRows all instances objects view rows
1648
1648
  * @param scopedHostname hostname which should be assumed as local
1649
- * @returns true if an instance is present on other host
1649
+ * @returns true if an instance is present on another host
1650
1650
  */
1651
1651
  _checkDependencyFulfilledForeignHosts(adapter, instancesRows, scopedHostname) {
1652
1652
  for (const row of instancesRows) {