@iobroker/js-controller-cli 7.2.2 → 7.2.3-alpha.1-20260621-61726ea22
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/lib/_Types.d.ts +7 -0
- package/build/cjs/lib/cli/cliCert.d.ts +5 -2
- package/build/cjs/lib/cli/cliCert.js +5 -2
- package/build/cjs/lib/cli/cliCert.js.map +2 -2
- package/build/cjs/lib/cli/cliCommand.d.ts +32 -1
- package/build/cjs/lib/cli/cliCommand.js +4 -1
- package/build/cjs/lib/cli/cliCommand.js.map +2 -2
- package/build/cjs/lib/cli/cliCompact.d.ts +4 -1
- package/build/cjs/lib/cli/cliCompact.js +4 -1
- package/build/cjs/lib/cli/cliCompact.js.map +2 -2
- package/build/cjs/lib/cli/cliDebug.d.ts +4 -1
- package/build/cjs/lib/cli/cliDebug.js +4 -1
- package/build/cjs/lib/cli/cliDebug.js.map +2 -2
- package/build/cjs/lib/cli/cliHost.d.ts +8 -5
- package/build/cjs/lib/cli/cliHost.js +8 -5
- package/build/cjs/lib/cli/cliHost.js.map +2 -2
- package/build/cjs/lib/cli/cliLogs.d.ts +4 -1
- package/build/cjs/lib/cli/cliLogs.js +4 -1
- package/build/cjs/lib/cli/cliLogs.js.map +2 -2
- package/build/cjs/lib/cli/cliMessage.d.ts +1 -0
- package/build/cjs/lib/cli/cliMessage.js.map +2 -2
- package/build/cjs/lib/cli/cliObjects.d.ts +12 -9
- package/build/cjs/lib/cli/cliObjects.js +12 -9
- package/build/cjs/lib/cli/cliObjects.js.map +2 -2
- package/build/cjs/lib/cli/cliPlugin.js.map +1 -1
- package/build/cjs/lib/cli/cliProcess.d.ts +4 -0
- package/build/cjs/lib/cli/cliProcess.js +3 -0
- package/build/cjs/lib/cli/cliProcess.js.map +2 -2
- package/build/cjs/lib/cli/cliStates.d.ts +3 -0
- package/build/cjs/lib/cli/cliStates.js +3 -0
- package/build/cjs/lib/cli/cliStates.js.map +2 -2
- package/build/cjs/lib/setup/customError.d.ts +4 -0
- package/build/cjs/lib/setup/customError.js +3 -0
- package/build/cjs/lib/setup/customError.js.map +2 -2
- package/build/cjs/lib/setup/formatters.d.ts +4 -4
- package/build/cjs/lib/setup/formatters.js.map +1 -1
- package/build/cjs/lib/setup/pluginInfos.d.ts +5 -0
- package/build/cjs/lib/setup/pluginInfos.js.map +2 -2
- package/build/cjs/lib/setup/setupBackup.d.ts +34 -0
- package/build/cjs/lib/setup/setupBackup.js +22 -0
- package/build/cjs/lib/setup/setupBackup.js.map +2 -2
- package/build/cjs/lib/setup/setupInstall.d.ts +37 -14
- package/build/cjs/lib/setup/setupInstall.js +28 -14
- package/build/cjs/lib/setup/setupInstall.js.map +2 -2
- package/build/cjs/lib/setup/setupLicense.d.ts +8 -0
- package/build/cjs/lib/setup/setupLicense.js +3 -0
- package/build/cjs/lib/setup/setupLicense.js.map +2 -2
- package/build/cjs/lib/setup/setupList.d.ts +54 -0
- package/build/cjs/lib/setup/setupList.js +51 -0
- package/build/cjs/lib/setup/setupList.js.map +2 -2
- package/build/cjs/lib/setup/setupPacketManager.d.ts +10 -0
- package/build/cjs/lib/setup/setupPacketManager.js +6 -0
- package/build/cjs/lib/setup/setupPacketManager.js.map +2 -2
- package/build/cjs/lib/setup/setupRepo.d.ts +6 -0
- package/build/cjs/lib/setup/setupRepo.js +3 -0
- package/build/cjs/lib/setup/setupRepo.js.map +2 -2
- package/build/cjs/lib/setup/setupSetup.d.ts +27 -0
- package/build/cjs/lib/setup/setupSetup.js +18 -0
- package/build/cjs/lib/setup/setupSetup.js.map +2 -2
- package/build/cjs/lib/setup/setupUpgrade.d.ts +6 -0
- package/build/cjs/lib/setup/setupUpgrade.js +3 -0
- package/build/cjs/lib/setup/setupUpgrade.js.map +2 -2
- package/build/cjs/lib/setup/setupUpload.d.ts +71 -0
- package/build/cjs/lib/setup/setupUpload.js +65 -1
- package/build/cjs/lib/setup/setupUpload.js.map +2 -2
- package/build/cjs/lib/setup/setupUsers.d.ts +23 -14
- package/build/cjs/lib/setup/setupUsers.js +17 -14
- package/build/cjs/lib/setup/setupUsers.js.map +2 -2
- package/build/cjs/lib/setup/setupVendor.d.ts +9 -1
- package/build/cjs/lib/setup/setupVendor.js +4 -1
- package/build/cjs/lib/setup/setupVendor.js.map +2 -2
- package/build/cjs/lib/setup/setupVisDebug.d.ts +9 -0
- package/build/cjs/lib/setup/setupVisDebug.js +3 -0
- package/build/cjs/lib/setup/setupVisDebug.js.map +2 -2
- package/build/esm/lib/_Types.d.ts +7 -0
- package/build/esm/lib/_Types.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCert.d.ts +5 -2
- package/build/esm/lib/cli/cliCert.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCert.js +5 -2
- package/build/esm/lib/cli/cliCert.js.map +1 -1
- package/build/esm/lib/cli/cliCommand.d.ts +32 -1
- 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 +4 -1
- package/build/esm/lib/cli/cliCompact.d.ts.map +1 -1
- package/build/esm/lib/cli/cliCompact.js +4 -1
- package/build/esm/lib/cli/cliCompact.js.map +1 -1
- package/build/esm/lib/cli/cliDebug.d.ts +4 -1
- 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 +8 -5
- 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 +4 -1
- package/build/esm/lib/cli/cliLogs.d.ts.map +1 -1
- package/build/esm/lib/cli/cliLogs.js +4 -1
- package/build/esm/lib/cli/cliLogs.js.map +1 -1
- package/build/esm/lib/cli/cliMessage.d.ts +1 -0
- 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 +12 -9
- package/build/esm/lib/cli/cliObjects.d.ts.map +1 -1
- package/build/esm/lib/cli/cliObjects.js +17 -14
- package/build/esm/lib/cli/cliObjects.js.map +1 -1
- package/build/esm/lib/cli/cliPlugin.js +1 -1
- package/build/esm/lib/cli/cliProcess.d.ts +4 -0
- package/build/esm/lib/cli/cliProcess.d.ts.map +1 -1
- package/build/esm/lib/cli/cliProcess.js +5 -1
- package/build/esm/lib/cli/cliProcess.js.map +1 -1
- package/build/esm/lib/cli/cliStates.d.ts +3 -0
- package/build/esm/lib/cli/cliStates.d.ts.map +1 -1
- package/build/esm/lib/cli/cliStates.js +3 -0
- package/build/esm/lib/cli/cliStates.js.map +1 -1
- 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/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 +34 -0
- package/build/esm/lib/setup/setupBackup.d.ts.map +1 -1
- package/build/esm/lib/setup/setupBackup.js +25 -0
- package/build/esm/lib/setup/setupBackup.js.map +1 -1
- package/build/esm/lib/setup/setupInstall.d.ts +37 -14
- package/build/esm/lib/setup/setupInstall.d.ts.map +1 -1
- package/build/esm/lib/setup/setupInstall.js +31 -14
- package/build/esm/lib/setup/setupInstall.js.map +1 -1
- package/build/esm/lib/setup/setupLicense.d.ts +8 -0
- package/build/esm/lib/setup/setupLicense.d.ts.map +1 -1
- package/build/esm/lib/setup/setupLicense.js +6 -0
- package/build/esm/lib/setup/setupLicense.js.map +1 -1
- package/build/esm/lib/setup/setupList.d.ts +54 -0
- package/build/esm/lib/setup/setupList.d.ts.map +1 -1
- package/build/esm/lib/setup/setupList.js +54 -0
- package/build/esm/lib/setup/setupList.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 +6 -0
- package/build/esm/lib/setup/setupRepo.d.ts.map +1 -1
- package/build/esm/lib/setup/setupRepo.js +6 -0
- package/build/esm/lib/setup/setupRepo.js.map +1 -1
- package/build/esm/lib/setup/setupSetup.d.ts +27 -0
- package/build/esm/lib/setup/setupSetup.d.ts.map +1 -1
- package/build/esm/lib/setup/setupSetup.js +21 -0
- package/build/esm/lib/setup/setupSetup.js.map +1 -1
- package/build/esm/lib/setup/setupUpgrade.d.ts +6 -0
- package/build/esm/lib/setup/setupUpgrade.d.ts.map +1 -1
- package/build/esm/lib/setup/setupUpgrade.js +6 -0
- package/build/esm/lib/setup/setupUpgrade.js.map +1 -1
- package/build/esm/lib/setup/setupUpload.d.ts +71 -0
- package/build/esm/lib/setup/setupUpload.d.ts.map +1 -1
- package/build/esm/lib/setup/setupUpload.js +68 -1
- package/build/esm/lib/setup/setupUpload.js.map +1 -1
- package/build/esm/lib/setup/setupUsers.d.ts +23 -14
- package/build/esm/lib/setup/setupUsers.d.ts.map +1 -1
- package/build/esm/lib/setup/setupUsers.js +20 -14
- package/build/esm/lib/setup/setupUsers.js.map +1 -1
- package/build/esm/lib/setup/setupVendor.d.ts +9 -1
- package/build/esm/lib/setup/setupVendor.d.ts.map +1 -1
- package/build/esm/lib/setup/setupVendor.js +7 -1
- package/build/esm/lib/setup/setupVendor.js.map +1 -1
- package/build/esm/lib/setup/setupVisDebug.d.ts +9 -0
- package/build/esm/lib/setup/setupVisDebug.d.ts.map +1 -1
- package/build/esm/lib/setup/setupVisDebug.js +6 -0
- package/build/esm/lib/setup/setupVisDebug.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/setup/setupBackup.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'fs-extra';\nimport path from 'node:path';\nimport { EXIT_CODES, tools } from '@iobroker/js-controller-common';\nimport { exec as execAsync } from 'promisify-child-process';\nimport * as tar from 'tar';\nimport type { Client as StatesRedisClient } from '@iobroker/db-states-redis';\nimport type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';\nimport { Upload } from './setupUpload.js';\nimport type { CleanDatabaseHandler, ProcessExitCallback, RestartController } from '../_Types.js';\nimport { dbConnectAsync, resetDbConnect } from './dbConnection.js';\nimport { IoBrokerError } from './customError.js';\nimport { CLIProcess } from '@/lib/cli/cliProcess.js';\nimport { open, writeFile } from 'node:fs/promises';\n\nexport interface CLIBackupRestoreOptions {\n dbMigration?: boolean;\n states: StatesRedisClient;\n objects: ObjectsRedisClient;\n processExit: ProcessExitCallback;\n cleanDatabase: CleanDatabaseHandler;\n restartController: RestartController;\n}\n\ntype BackupObject = Omit<ioBroker.GetObjectListItem<ioBroker.Object>, 'doc'>;\n\nexport interface RestoreBackupReturnValue {\n /** Exit code of the process */\n exitCode: EXIT_CODES;\n /** The new states db connection after restore */\n states: StatesRedisClient;\n /** The new objects db connection after restore */\n objects: ObjectsRedisClient;\n}\n\ninterface RestoreAfterStopOptions {\n /** restart controller after restore */\n restartOnFinish: boolean;\n /** skip the controller version check */\n force: boolean;\n /** skip adapter deletion, e.g. for setup custom db migration */\n dontDeleteAdapters: boolean;\n}\n\ninterface Backup {\n config?: null | ioBroker.IoBrokerJson;\n objects: null | BackupObject[];\n states: Record<string, ioBroker.State>;\n}\n\ninterface PreprocessObjectOptions {\n /** The hostname */\n hostname: string;\n /** The object to preprocess */\n object: ioBroker.Object;\n /** If the host has a custom hostname */\n isCustomHostname: boolean;\n /** String to check if it is a sub object or state of this host (will not match the host object directly) */\n thisHostNameStartsWith: string;\n}\n\nexport interface RestoreBackupOptions {\n /** backup name, absolute path or index */\n name: string | number;\n /** if force flag is set, js-controller is allowed to have a different version */\n force: boolean;\n /** skip adapter deletion, e.g. for setup custom db migration */\n dontDeleteAdapters: boolean;\n}\n\nconst controllerDir = tools.getControllerDir();\n\nexport class BackupRestore {\n private readonly hostname = tools.getHostName();\n private readonly tmpDir = path.normalize(path.join(controllerDir, 'tmp'));\n private readonly bkpDir = path.normalize(path.join(controllerDir, 'backups'));\n private objects: ObjectsRedisClient;\n private states: StatesRedisClient;\n private readonly processExit: CLIBackupRestoreOptions['processExit'];\n private readonly restartController: CLIBackupRestoreOptions['restartController'];\n private readonly cleanDatabase: CLIBackupRestoreOptions['cleanDatabase'];\n private readonly dbMigration: boolean;\n /** these adapters will be reinstalled during restore, while others will be installed after next controller start */\n private readonly PRESERVE_ADAPTERS = ['admin', 'backitup'] as const;\n private upload: Upload;\n private configParts: string[];\n private readonly configDir: string;\n /** Placeholder inserted during backup creation if no custom hostname defined */\n private readonly HOSTNAME_PLACEHOLDER = '$$__hostname__$$';\n /** Same as HOSTNAME_PLACEHOLDER but used in replace method */\n private readonly HOSTNAME_PLACEHOLDER_REPLACE = '$$$$__hostname__$$$$';\n /** Regex to replace all occurrences of the HOSTNAME_PLACEHOLDER */\n private readonly HOSTNAME_PLACEHOLDER_REGEX = /\\$\\$__hostname__\\$\\$/g;\n /** Postfix for backup name */\n private readonly BACKUP_POSTFIX = `_backup${tools.appNameLowerCase}`;\n\n constructor(options: CLIBackupRestoreOptions) {\n options = options || {};\n\n if (!options.states) {\n throw new Error('Invalid arguments: states is missing');\n }\n if (!options.objects) {\n throw new Error('Invalid arguments: objects is missing');\n }\n if (!options.processExit) {\n throw new Error('Invalid arguments: processExit is missing');\n }\n if (!options.cleanDatabase) {\n throw new Error('Invalid arguments: cleanDatabase is missing');\n }\n if (!options.restartController) {\n throw new Error('Invalid arguments: restartController is missing');\n }\n\n this.objects = options.objects;\n this.states = options.states;\n this.processExit = options.processExit;\n this.cleanDatabase = options.cleanDatabase;\n this.restartController = options.restartController;\n this.dbMigration = options.dbMigration || false;\n\n this.upload = new Upload(options);\n\n this.configParts = tools.getConfigFileName().split('/');\n this.configParts.pop(); // remove *.json\n this.configDir = this.configParts.join('/'); // => name-data\n }\n\n // --------------------------------------- BACKUP ---------------------------------------------------\n private async _copyFile(id: string, srcPath: string, destPath: string): Promise<void> {\n try {\n const data = await this.objects.readFile(id, srcPath);\n if (data) {\n fs.writeFileSync(destPath, data.file);\n }\n } catch (err) {\n console.log(`Can not copy File ${id}${srcPath} to ${destPath}: ${err.message}`);\n }\n }\n\n async copyDir(id: string, srcPath: string, destPath: string): Promise<void> {\n fs.ensureDirSync(destPath);\n\n try {\n const res = await this.objects.readDirAsync(id, srcPath);\n if (res) {\n for (const entry of res) {\n if (entry.isDir) {\n await this.copyDir(id, `${srcPath}/${entry.file}`, `${destPath}/${entry.file}`);\n } else {\n fs.ensureDirSync(destPath);\n await this._copyFile(id, `${srcPath}/${entry.file}`, `${destPath}/${entry.file}`);\n }\n }\n }\n } catch (err) {\n if (!err.message.includes('Not exists')) {\n console.warn(`Directory ${id}/${srcPath} cannot be copied: ${err}`);\n }\n }\n }\n\n /**\n * Get the directory where backups should be stored\n */\n static getBackupDir(): string {\n return path.join(tools.getRootDir(), 'backups/');\n }\n\n copyFileSync(source: string, target: string): void {\n let targetFile = target;\n\n try {\n // if target is a directory a new file with the same name will be created\n if (fs.existsSync(target)) {\n if (fs.statSync(target).isDirectory()) {\n targetFile = path.join(target, path.basename(source));\n }\n }\n\n fs.writeFileSync(targetFile, fs.readFileSync(source));\n } catch (e) {\n console.error(`Could not copy ${targetFile} to ${source}: ${e.message}`);\n }\n }\n\n copyFolderRecursiveSync(source: string, target: string): void {\n let files = [];\n\n if (!fs.existsSync(target)) {\n fs.mkdirSync(target);\n }\n\n // check if folder needs to be created or integrated\n const targetFolder = path.join(target, path.basename(source));\n if (!fs.existsSync(targetFolder)) {\n fs.mkdirSync(targetFolder);\n }\n\n // copy\n if (fs.existsSync(source) && fs.statSync(source).isDirectory()) {\n files = fs.readdirSync(source);\n files.forEach(file => {\n const curSource = path.join(source, file);\n if (!fs.existsSync(curSource)) {\n return;\n }\n if (fs.statSync(curSource).isDirectory()) {\n this.copyFolderRecursiveSync(curSource, targetFolder);\n } else {\n this.copyFileSync(curSource, targetFolder);\n }\n });\n }\n }\n\n /**\n * Removes the temporary backup directory, never throws\n */\n private removeTempBackupDir(): void {\n try {\n fs.rmSync(path.join(this.tmpDir, 'backup'), { recursive: true, force: true });\n } catch (e) {\n console.error(`host.${this.hostname} Cannot clear temporary backup directory: ${e.message}`);\n }\n }\n\n /**\n * Pack and compress the backup\n *\n * @param name - backup name\n */\n private _packBackup(name: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const f = fs.createWriteStream(name);\n f.on('finish', () => {\n this.removeTempBackupDir();\n resolve(path.normalize(name));\n });\n\n f.on('error', e => {\n console.error(`host.${this.hostname} Cannot pack directory ${this.tmpDir}/backup: ${e.message}`);\n reject(new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_GZIP_DIRECTORY }));\n });\n\n try {\n tar.create({ gzip: true, cwd: `${this.tmpDir}/` }, ['backup']).pipe(f);\n } catch (e) {\n console.error(`host.${this.hostname} Cannot pack directory ${this.tmpDir}/backup: ${e.message}`);\n reject(new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_GZIP_DIRECTORY }));\n }\n });\n }\n\n /**\n * Creates backup and stores with given name\n *\n * @param name - name of the backup\n * @param noConfig - do not store configs (used by setup custom migration)\n */\n async createBackup(name: string, noConfig = false): Promise<string> {\n if (!name) {\n const d = new Date();\n name = `${d.getFullYear()}_${`0${d.getMonth() + 1}`.slice(-2)}_${`0${d.getDate()}`.slice(-2)}-${`0${d.getHours()}`.slice(\n -2,\n )}_${`0${d.getMinutes()}`.slice(-2)}_${`0${d.getSeconds()}`.slice(-2)}${this.BACKUP_POSTFIX}`;\n } else if (!name.endsWith(this.BACKUP_POSTFIX) && !name.endsWith(`${this.BACKUP_POSTFIX}.tar.gz`)) {\n name += this.BACKUP_POSTFIX;\n }\n\n name = name.toString().replace(/\\\\/g, '/');\n if (!name.includes('/')) {\n const backupPath = BackupRestore.getBackupDir();\n\n // create directory if not exists\n fs.ensureDirSync(backupPath);\n\n if (!name.includes('.tar.gz')) {\n name = `${backupPath + name}.tar.gz`;\n } else {\n name = backupPath + name;\n }\n }\n\n const hostname = tools.getHostName();\n // String to check if it is a sub object or state of this host (will not match the host object directly)\n const thisHostNameStartsWith = `system.host.${hostname}.`;\n\n fs.ensureDirSync(this.bkpDir);\n fs.ensureDirSync(this.tmpDir);\n\n this.removeTempBackupDir();\n\n const backupBasePath = path.join(this.tmpDir, 'backup');\n fs.ensureDirSync(backupBasePath);\n fs.ensureDirSync(path.join(backupBasePath, 'files'));\n\n let isCustomHostname = false;\n let config: ioBroker.IoBrokerJson | undefined;\n\n // read iobroker.json\n try {\n config = (await fs.readJSON(tools.getConfigFileName())) as ioBroker.IoBrokerJson;\n // if a hostname is configured\n isCustomHostname = !!config.system.hostname;\n } catch (e) {\n console.error(`host.${hostname} Cannot read config file: ${e.message}`);\n }\n\n if (!noConfig && config) {\n await writeFile(path.join(backupBasePath, 'config.json'), JSON.stringify(config), { encoding: 'utf-8' });\n }\n\n const objectsFd = await open(path.join(backupBasePath, 'objects.jsonl'), 'a');\n\n try {\n const res = await this.objects.getObjectListAsync({ include_docs: true });\n for (const row of res.rows) {\n const preprocessedValue = await this._preprocessObject({\n object: row.value,\n isCustomHostname,\n hostname,\n thisHostNameStartsWith,\n });\n await objectsFd.write(`${JSON.stringify(preprocessedValue)}\\n`);\n }\n\n console.log(`host.${hostname} ${res.rows.length || 'no'} objects saved`);\n } catch (e) {\n console.error(`host.${hostname} Cannot get objects: ${e.message}`);\n }\n\n await objectsFd.close();\n\n const statesFd = await open(path.join(backupBasePath, 'states.jsonl'), 'a');\n\n try {\n const keys = await this.states.getKeys('*');\n const objs = await this.states.getStates(keys!);\n\n if (keys) {\n for (let i = 0; i < keys.length; i++) {\n const obj = objs[i];\n\n if (!obj) {\n continue;\n }\n\n if (!isCustomHostname) {\n // if it's a default hostname, we will have a new default after restore and need to replace\n if (obj.from === `system.host.${hostname}`) {\n obj.from.replace(\n `system.host.${hostname}`,\n `system.host.${this.HOSTNAME_PLACEHOLDER_REPLACE}`,\n );\n }\n if (keys[i].startsWith(thisHostNameStartsWith)) {\n keys[i] = keys[i].replace(hostname, this.HOSTNAME_PLACEHOLDER_REPLACE);\n }\n }\n\n await statesFd.write(`${JSON.stringify({ id: keys[i], state: obj })}\\n`);\n }\n\n await statesFd.close();\n console.log(`host.${hostname} ${keys.length} states saved`);\n }\n } catch (e) {\n console.error(`host.${hostname} Cannot get states: ${e.message}`);\n }\n\n console.log(`host.${hostname} Validating backup ...`);\n try {\n await this._validateTempDirectory(noConfig);\n console.log(`host.${hostname} The backup is valid!`);\n\n return await this._packBackup(name);\n } catch (e) {\n console.error(`host.${hostname} Backup not created: ${e.message}`);\n this.removeTempBackupDir();\n\n if (e instanceof IoBrokerError) {\n throw e;\n }\n\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP });\n }\n }\n\n //--------------------------------------- RESTORE ---------------------------------------------------\n /**\n * Helper to restore raw state\n *\n * @param stateId - state ID\n * @param stateObject - the corresponding state object\n */\n private async _setStateHelper(stateId: string, stateObject: ioBroker.State): Promise<void> {\n try {\n await this.states.setRawState(stateId, stateObject);\n } catch (e) {\n console.log(`host.${this.hostname} Could not set value for state ${stateId}: ${e.message}`);\n }\n }\n\n /**\n * Sets all objects to the db and disables all adapters\n *\n * @param object - object to be set\n */\n private async _setObjHelper(object: ioBroker.Object): Promise<void> {\n // Disable all adapters.\n if (\n !this.dbMigration &&\n object._id &&\n /^system\\.adapter\\..+\\.\\d$/.test(object._id) &&\n !object._id.startsWith('system.adapter.admin.') &&\n !object._id.startsWith('system.adapter.backitup.')\n ) {\n if (object.common?.enabled) {\n object.common.enabled = false;\n }\n }\n\n try {\n await this.objects.setObject(object._id, object);\n } catch (e) {\n console.warn(`host.${this.hostname} Cannot restore ${object._id}: ${e.message}`);\n }\n }\n\n /**\n * Creates all provided object if non-existing\n *\n * @param objectList - list of objects to be created\n */\n private async _reloadAdapterObject(objectList: ioBroker.Object[]): Promise<void> {\n if (!Array.isArray(objectList)) {\n return;\n }\n\n for (const object of objectList) {\n let obj;\n try {\n obj = await this.objects.getObject(object._id);\n } catch {\n // ignore\n }\n\n if (!obj) {\n // object not existing -> create it\n try {\n await this.objects.setObject(object._id, object);\n console.log(`host.${this.hostname} object ${object._id} created`);\n } catch {\n // ignore\n }\n }\n }\n }\n\n private async _reloadAdaptersObjects(): Promise<void> {\n const dirs: string[] = [];\n let _modules;\n let p = path.join(controllerDir, 'node_modules');\n\n if (p.includes('js-controller')) {\n p = path.join(controllerDir, '..', 'node_modules');\n }\n\n if (fs.existsSync(p)) {\n _modules = fs.readdirSync(p).filter(dir => fs.existsSync(`${p}/${dir}/io-package.json`));\n if (_modules) {\n const regEx = new RegExp(`^${tools.appName}\\\\.`, 'i');\n for (const module of _modules) {\n if (regEx.test(module) && !dirs.includes(module.substring(tools.appName.length + 1))) {\n dirs.push(module);\n }\n }\n }\n }\n\n // if installed as npm\n if (\n fs.existsSync(\n path.join(controllerDir, '..', '..', 'node_modules', `${tools.appName.toLowerCase()}.js-controller`),\n )\n ) {\n const p = path.join(controllerDir, '..');\n _modules = fs.readdirSync(p).filter(dir => fs.existsSync(`${p}/${dir}/io-package.json`));\n const regEx_ = new RegExp(`^${tools.appName}\\\\.`, 'i');\n for (const module of _modules) {\n // if starting from application name + '.'\n if (\n regEx_.test(module) &&\n // If not js-controller\n module.substring(tools.appName.length + 1) !== 'js-controller' &&\n !dirs.includes(module.substring(tools.appName.length + 1))\n ) {\n dirs.push(module);\n }\n }\n }\n\n for (const dir of dirs) {\n const adapterName = dir.replace(/^iobroker\\./i, '');\n await this.upload.uploadAdapter(adapterName, false, true);\n await this.upload.uploadAdapter(adapterName, true, true);\n\n let pkg;\n\n if (!dir) {\n console.error('Wrong');\n }\n const adapterDir = tools.getAdapterDir(adapterName);\n if (fs.existsSync(`${adapterDir}/io-package.json`)) {\n pkg = fs.readJSONSync(`${adapterDir}/io-package.json`);\n }\n\n if (pkg?.objects?.length) {\n console.log(`host.${this.hostname} Setup \"${dir}\" adapter`);\n await this._reloadAdapterObject(pkg.objects);\n }\n }\n }\n\n private async _uploadUserFiles(root: string, uploadPath?: string): Promise<void> {\n uploadPath = uploadPath || '';\n if (!fs.existsSync(root)) {\n return;\n }\n const files = fs.readdirSync(root + uploadPath);\n for (const file of files) {\n const fName = path.join(root, uploadPath, file);\n if (!fs.existsSync(fName)) {\n continue;\n }\n const stat = fs.statSync(fName);\n if (stat.isDirectory()) {\n try {\n await this._uploadUserFiles(root, `${uploadPath}/${file}`);\n } catch (err) {\n console.error(`Error: ${err}`);\n }\n } else {\n const parts = uploadPath.split('/');\n const adapter = parts.splice(0, 2)[1];\n const _path = `${parts.join('/')}/${file}`;\n console.log(`host.${this.hostname} Upload user file \"${adapter}/${_path}`);\n try {\n await this.objects.writeFileAsync(adapter, _path, fs.readFileSync(`${root + uploadPath}/${file}`));\n } catch (err) {\n console.error(`Error: ${err.message}`);\n }\n }\n }\n }\n\n /**\n * Preprocess object before storing it in the backup file\n *\n * @param options object and host information\n */\n private async _preprocessObject(options: PreprocessObjectOptions): Promise<ioBroker.Object> {\n const { object, isCustomHostname, hostname, thisHostNameStartsWith } = options;\n\n if (!object || !object._id || !object.common) {\n return object;\n }\n\n if (!isCustomHostname) {\n if (object._id.match(/^system\\.adapter\\.([\\w\\d_-]+).(\\d+)$/) && object.common.host === hostname) {\n object.common.host = this.HOSTNAME_PLACEHOLDER;\n object.common.host = this.HOSTNAME_PLACEHOLDER;\n } else if (object._id.startsWith(thisHostNameStartsWith)) {\n object._id = object._id.replace(hostname, this.HOSTNAME_PLACEHOLDER_REPLACE);\n } else if (object._id === `system.host.${hostname}`) {\n object._id = `system.host.${this.HOSTNAME_PLACEHOLDER}`;\n object.common.name = object._id;\n object.common.hostname = this.HOSTNAME_PLACEHOLDER;\n if (object.native && object.native.os) {\n object.native.os.hostname = this.HOSTNAME_PLACEHOLDER;\n }\n\n object.common.name = object._id;\n object.common.hostname = this.HOSTNAME_PLACEHOLDER;\n if (object.native?.os) {\n object.native.os.hostname = this.HOSTNAME_PLACEHOLDER;\n }\n }\n }\n\n // Read all files\n if (object.type === 'meta' && object.common?.type === 'meta.user') {\n // do not process \"xxx.0. \" and \"xxx.0.\"\n if (object._id.trim() === object._id && object._id[object._id.length - 1] !== '.') {\n await this.copyDir(object._id, '', `${this.tmpDir}/backup/files/${object._id}`);\n }\n }\n\n // Read all files\n if (object.type === 'instance' && object.common?.dataFolder) {\n let dataFolderPath = object.common.dataFolder;\n\n if (dataFolderPath[0] !== '/' && !dataFolderPath.match(/^\\w:/)) {\n dataFolderPath = path.join(this.configDir, dataFolderPath);\n }\n\n if (fs.existsSync(dataFolderPath)) {\n try {\n this.copyFolderRecursiveSync(dataFolderPath, `${this.tmpDir}/backup`);\n } catch (e) {\n console.error(`host.${hostname} Could not backup \"${dataFolderPath}\" directory: ${e.message}`);\n this.removeTempBackupDir();\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_COPY_DIR });\n }\n }\n }\n\n return object;\n }\n\n private _copyBackupedFiles(backupDir: string): void {\n try {\n if (!fs.existsSync(backupDir)) {\n console.log('No additional files to restore');\n return;\n }\n const dirs = fs.readdirSync(backupDir);\n\n dirs.forEach(dir => {\n if (dir === 'files') {\n return;\n }\n const backupPath = path.join(backupDir, dir);\n let stat;\n try {\n if (!fs.existsSync(backupPath)) {\n return;\n }\n stat = fs.statSync(backupPath);\n } catch (e) {\n console.error(`Ignoring ${backupPath} because can not get file type: ${e.message}`);\n return;\n }\n if (stat.isDirectory()) {\n this.copyFolderRecursiveSync(backupPath, this.configDir);\n }\n });\n } catch (e) {\n console.error(`Ignoring ${backupDir} because can not read directory: ${e.message}`);\n }\n }\n\n /**\n * Restore JSONL backup after controller has been stopped\n *\n * @param options The restore options\n */\n private async _restoreJsonlBackup(options: RestoreAfterStopOptions): Promise<EXIT_CODES> {\n const { force, dontDeleteAdapters } = options;\n const hostname = tools.getHostName();\n\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n\n let backupHostName = hostname;\n // Note: on backups created during migration no config exists\n let config: ioBroker.IoBrokerJson | undefined;\n\n if (await fs.pathExists(path.join(backupBaseDir, 'config.json'))) {\n config = (await fs.readJSON(path.join(backupBaseDir, 'config.json'))) as ioBroker.IoBrokerJson;\n backupHostName = config.system?.hostname || hostname;\n }\n\n // we need to find the host obj for the compatibility check\n const objFd = await open(path.join(backupBaseDir, 'objects.jsonl'));\n const rlObj = objFd.readLines();\n\n const hostObjArr: BackupObject[] = [];\n\n for await (let line of rlObj) {\n line = line.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n const obj: ioBroker.Object = JSON.parse(line);\n if (obj._id === `system.host.${backupHostName}`) {\n hostObjArr.push({ id: obj._id, value: obj });\n break;\n }\n }\n\n await objFd.close();\n\n // check that the same controller version is installed as it is contained in backup\n const exitCode = this._ensureCompatibility(controllerDir, backupHostName, hostObjArr, force);\n\n if (exitCode) {\n // we had an error\n return exitCode;\n }\n\n if (!dontDeleteAdapters) {\n // prevent having wrong versions of adapters\n await this._removeAllAdapters();\n }\n\n // restore ioBroker.json\n if (config) {\n fs.writeFileSync(tools.getConfigFileName(), JSON.stringify(config, null, 2));\n await this.connectToNewDatabase(config);\n }\n\n console.log(`host.${hostname} Clear all objects and states...`);\n await this.cleanDatabase(false);\n console.log(`host.${hostname} done.`);\n\n const objectsFd = await open(path.join(backupBaseDir, 'objects.jsonl'));\n const rlObjects = objectsFd.readLines();\n\n let count = 0;\n\n for await (let line of rlObjects) {\n line = line.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n const obj: ioBroker.Object = JSON.parse(line);\n await this._setObjHelper(obj);\n count++;\n }\n\n console.log(`${count} objects restored.`);\n\n await objectsFd.close();\n\n const statesFd = await open(path.join(backupBaseDir, 'states.jsonl'));\n const rlStates = statesFd.readLines();\n\n count = 0;\n\n for await (let line of rlStates) {\n line = line.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n const state: {\n id: string;\n state: ioBroker.State;\n } = JSON.parse(line);\n await this._setStateHelper(state.id, state.state);\n count++;\n }\n\n console.log(`${count} states restored.`);\n\n await statesFd.close();\n\n return EXIT_CODES.NO_ERROR;\n }\n\n /**\n * Restore after controller has been stopped\n *\n * @param options The restore options\n */\n private async _restoreAfterStop(options: RestoreAfterStopOptions): Promise<EXIT_CODES> {\n const { force, restartOnFinish, dontDeleteAdapters } = options;\n\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n const isJsonl = await fs.pathExists(path.join(backupBaseDir, 'objects.jsonl'));\n\n if (isJsonl) {\n const exitCode = await this._restoreJsonlBackup(options);\n if (exitCode !== EXIT_CODES.NO_ERROR) {\n return exitCode;\n }\n } else {\n const hostname = tools.getHostName();\n console.log(`host.${hostname} Restore legacy backup.`);\n\n // Open file\n let data = fs.readFileSync(path.join(backupBaseDir, 'backup.json'), 'utf8');\n // replace all hostnames of instances etc with the new host\n data = data.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n fs.writeFileSync(path.join(backupBaseDir, 'backup_.json'), data);\n let restore: Backup;\n try {\n restore = JSON.parse(data);\n } catch (e) {\n console.error(`Cannot parse \"${path.join(backupBaseDir, 'backup_.json')}\": ${e.message}`);\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n\n if (!restore.objects) {\n console.error('The backup does not contain any objects.');\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n\n // check that the same controller version is installed as it is contained in backup\n const exitCode = this._ensureCompatibility(\n controllerDir,\n restore.config?.system?.hostname || hostname,\n restore.objects,\n force,\n );\n\n if (exitCode) {\n // we had an error\n return exitCode;\n }\n\n if (!dontDeleteAdapters) {\n // prevent having wrong versions of adapters\n await this._removeAllAdapters();\n }\n\n // restore ioBroker.json\n if (restore.config) {\n fs.writeFileSync(tools.getConfigFileName(), JSON.stringify(restore.config, null, 2));\n await this.connectToNewDatabase(restore.config);\n }\n\n console.log(`host.${hostname} Clear all objects and states...`);\n await this.cleanDatabase(false);\n console.log(`host.${hostname} done.`);\n\n const sList = Object.keys(restore.states);\n\n for (let i = 0; i < restore.objects.length; i++) {\n await this._setObjHelper(restore.objects[i].value);\n if (i % 200 === 0) {\n console.log(`host.${this.hostname} Processed ${i}/${restore.objects.length} objects`);\n }\n }\n\n console.log(`${restore.objects.length} objects restored.`);\n for (let i = 0; i < sList.length; i++) {\n const id = sList[i];\n await this._setStateHelper(id, restore.states[id]);\n if (i % 200 === 0) {\n console.log(`host.${this.hostname} Processed ${i}/${sList.length} states`);\n }\n }\n\n console.log(`${sList.length} states restored.`);\n }\n\n // Load user files into DB\n await this._uploadUserFiles(path.join(backupBaseDir, 'files'));\n // reload objects of adapters (if some couldn't be removed - normally this shouldn't be necessary anymore)\n await this._reloadAdaptersObjects();\n // Reload host objects\n const packageIO = fs.readJSONSync(path.join(controllerDir, 'io-package.json'));\n await this._reloadAdapterObject(packageIO ? packageIO.objects : null);\n // copy all files into iob-data\n this._copyBackupedFiles(backupBaseDir);\n // reinstall preserve adapters\n await this._restorePreservedAdapters();\n\n if (force) {\n // js-controller version has changed (setup never called for this version)\n console.log('Forced restore - executing setup ...');\n try {\n await execAsync(\n `\"${process.execPath}\" \"${path.join(controllerDir, `${tools.appName.toLowerCase()}.js`)}\" setup`,\n );\n } catch (e) {\n console.error(\n `Could not execute \"setup\" command, please ensure \"setup\" is called before starting ioBroker: ${e.message}`,\n );\n }\n }\n\n if (restartOnFinish) {\n console.log('restart');\n this.restartController();\n }\n\n return EXIT_CODES.NO_ERROR;\n }\n\n /**\n * Connects to the database which is configured in `iobroker.json`\n * Meant to be used after the configuration file has been overwritten\n *\n * @param config The new config, needed for logging purposes\n */\n private async connectToNewDatabase(config: ioBroker.IoBrokerJson): Promise<void> {\n console.log(\n `host.${this.hostname} Connecting to new DB \"${config.states.type}/${config.objects.type}\" (can take up to 20s) ...`,\n );\n await resetDbConnect();\n const { objects, states } = await dbConnectAsync(false);\n console.log(`host.${this.hostname} Successfully connected to new DB`);\n\n this.upload = new Upload({ states, objects });\n\n this.objects = objects;\n this.states = states;\n }\n\n /**\n * Removes all adapters\n */\n private async _removeAllAdapters(): Promise<void> {\n const nodeModulePath = path.join(controllerDir, '..');\n const nodeModuleDirs = fs.readdirSync(nodeModulePath, { withFileTypes: true });\n // we need to uninstall current adapters to get exact the same system as before backup\n for (const dir of nodeModuleDirs) {\n if (\n dir.isDirectory() &&\n dir.name.startsWith(`${tools.appName.toLowerCase()}.`) &&\n dir.name !== `${tools.appName.toLowerCase()}.js-controller`\n ) {\n try {\n const packJson = fs.readJsonSync(path.join(nodeModulePath, dir.name, 'package.json'));\n console.log(`Removing current installation of ${packJson.name}`);\n await tools.uninstallNodeModule(packJson.name);\n } catch {\n // ignore\n }\n }\n }\n }\n\n /**\n * Ensure that installed controller version matches version in backup\n *\n * @param controllerDir - directory of js-controller\n * @param backupHostname - hostname in backup file\n * @param backupObjects - the objects contained in the backup\n * @param force - if force is true, only log\n */\n private _ensureCompatibility(\n controllerDir: string,\n backupHostname: string,\n backupObjects: BackupObject[],\n force: boolean,\n ): void | number {\n try {\n const ioPackJson = fs.readJsonSync(path.join(controllerDir, 'io-package.json'));\n const hostObj = backupObjects.find(obj => obj.id === `system.host.${backupHostname}`);\n\n if (!hostObj) {\n console.error('No host object found, your backup seems to be corrupted!');\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n\n if (hostObj.value.common.installedVersion !== ioPackJson.common.version) {\n if (!force) {\n console.warn('The current version of js-controller differs from the version in the backup.');\n console.warn('The js-controller version of the backup can not be restored automatically.');\n console.warn(\n `To restore the js-controller version of the backup, execute \"npm i iobroker.js-controller@${hostObj.value.common.installedVersion} --omit=dev\" inside your ioBroker directory`,\n );\n console.warn(\n 'If you really want to restore the backup with the current installed js-controller, execute the restore command with the --force flag',\n );\n\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n console.info('The current version of js-controller differs from the version in the backup.');\n console.info('The js-controller version of the backup can not be restored automatically.');\n console.info('Note, that your backup might differ in behavior due to this version change!');\n }\n } catch {\n // ignore\n }\n }\n\n /**\n * Returns all backups as array\n */\n listBackups(): string[] {\n const dir = BackupRestore.getBackupDir();\n const result: string[] = [];\n if (fs.existsSync(dir)) {\n const files = fs.readdirSync(dir);\n for (const file of files) {\n if (file.match(/\\.tar\\.gz$/i)) {\n result.push(file);\n }\n }\n return result;\n }\n return result;\n }\n\n /**\n * Validates a JSONL-style backup and all json files inside the backup (in temporary directory)\n *\n * @param noConfig if the backup does not contain a `config.json` (used by setup custom migration)\n */\n private async _validateTempDirectory(noConfig = false): Promise<void> {\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n\n if (!noConfig) {\n await fs.readJSON(path.join(backupBaseDir, 'config.json'));\n console.log(`host.${this.hostname} \"config.json\" is valid`);\n }\n\n if (!(await fs.pathExists(path.join(backupBaseDir, 'objects.jsonl')))) {\n throw new Error('Backup does not contain valid objects');\n }\n\n console.log(`host.${this.hostname} \"objects.jsonl\" exists`);\n\n if (!(await fs.pathExists(path.join(backupBaseDir, 'states.jsonl')))) {\n throw new Error('Backup does not contain valid states');\n }\n\n console.log(`host.${this.hostname} \"states.jsonl\" exists`);\n\n await this._validateDatabaseFiles();\n\n console.log(`host.${this.hostname} JSONL lines are valid`);\n\n // we check all other json files, we assume them as optional, because user created files may be no valid json\n try {\n this._checkDirectory(path.join(backupBaseDir, 'files'));\n } catch (e) {\n console.warn(`host.${this.hostname} One or more optional files are corrupted: ${e.message}`);\n console.warn(`host.${this.hostname} Please ensure that self-created JSON files are valid`);\n }\n }\n\n /**\n * Validate that the created JSONL files in the temporary directories are parseable\n */\n private async _validateDatabaseFiles(): Promise<void> {\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n\n const objectsFd = await open(path.join(backupBaseDir, 'objects.jsonl'));\n const rlObjects = objectsFd.readLines();\n\n for await (const line of rlObjects) {\n try {\n JSON.parse(line);\n } catch (e) {\n throw new Error(`The \"objects.jsonl\" file is corrupted: ${e.message}`);\n }\n }\n\n await objectsFd.close();\n\n const statesFd = await open(path.join(backupBaseDir, 'states.jsonl'));\n const rlStates = statesFd.readLines();\n\n for await (const line of rlStates) {\n try {\n JSON.parse(line);\n } catch (e) {\n throw new Error(`The \"states.jsonl\" file is corrupted: ${e.message}`);\n }\n }\n\n await statesFd.close();\n }\n\n /**\n * Validates the given backup.json and all json files in the backup, calls processExit afterwards\n *\n * @param _name - index or name of the backup\n */\n async validateBackup(_name: string | number): Promise<void> {\n let backups;\n let name = typeof _name === 'number' ? _name.toString() : _name;\n\n if (!name) {\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n if (backups.length) {\n // List all available backups\n console.log('Please specify one of the backup names:');\n\n for (const t in backups) {\n console.log(`${backups[t]} or ${backups[t].replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${t}`);\n }\n } else {\n console.warn(`No backups found. Create a backup, using \"${tools.appName} backup\" first`);\n }\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n // If number\n if (parseInt(name, 10).toString() === name.toString()) {\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n name = backups[parseInt(name, 10)];\n if (!name) {\n console.log('No matching backup found');\n if (backups.length) {\n console.log('Please specify one of the backup names:');\n for (const t in backups) {\n console.log(\n `${backups[t]} or ${backups[t].replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${t}`,\n );\n }\n } else {\n console.log(`No existing backups. Create a backup, using \"${tools.appName} backup\" first`);\n }\n\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n console.log(`host.${this.hostname} Using backup file ${name}`);\n }\n\n name = name.toString().replace(/\\\\/g, '/');\n if (!name.includes('/')) {\n name = BackupRestore.getBackupDir() + name;\n const regEx = new RegExp(this.BACKUP_POSTFIX, 'i');\n if (!regEx.test(name)) {\n name += this.BACKUP_POSTFIX;\n }\n if (!name.match(/\\.tar\\.gz$/i)) {\n name += '.tar.gz';\n }\n }\n if (!fs.existsSync(name)) {\n console.error(`host.${this.hostname} Cannot find ${name}`);\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n\n if (fs.existsSync(`${this.tmpDir}/backup/backup.json`)) {\n fs.unlinkSync(`${this.tmpDir}/backup/backup.json`);\n }\n\n try {\n await tar.extract({\n file: name,\n cwd: this.tmpDir,\n });\n } catch (e) {\n const errMessage = `Cannot extract from file \"${name}\": ${e.message}`;\n console.error(`host.${this.hostname} ${errMessage}`);\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n\n try {\n if (fs.existsSync(path.join(this.tmpDir, 'backup', 'backup.json'))) {\n this._validateLegacyTempDir();\n } else {\n await this._validateTempDirectory();\n }\n } catch (e) {\n console.error(`host.${this.hostname} ${e.message}`);\n\n try {\n this.removeTempBackupDir();\n } catch (e) {\n console.error(`host.${this.hostname} Cannot clear temporary backup directory: ${e.message}`);\n }\n\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP });\n }\n\n try {\n this.removeTempBackupDir();\n } catch (e) {\n console.error(`host.${this.hostname} Cannot clear temporary backup directory: ${e.message}`);\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP });\n }\n }\n\n /**\n * Validate an unpacked legacy backup in the temporary directory\n */\n private _validateLegacyTempDir(): void {\n console.log(`host.${this.hostname} Starting validation ...`);\n let backupJSON;\n try {\n backupJSON = fs.readJSONSync(`${this.tmpDir}/backup/backup.json`);\n } catch (e) {\n throw new Error(`Backup corrupted. Backup does not contain a valid backup.json file: ${e.message}`);\n }\n\n if (!backupJSON || !backupJSON.objects || !backupJSON.objects.length) {\n throw new Error(`host.${this.hostname} Backup corrupted. Backup does not contain valid objects`);\n }\n\n console.log(`host.${this.hostname} backup.json OK`);\n\n try {\n this._checkDirectory(`${this.tmpDir}/backup/files`, true);\n } catch (e) {\n throw new Error(`Backup corrupted: ${e.message}`);\n }\n }\n\n /**\n * Checks a directory for json files and validates them, steps down recursive in subdirectories\n *\n * @param path - path to the directory\n * @param verbose - if logging should be verbose\n */\n private _checkDirectory(path: string, verbose = false): void {\n if (fs.existsSync(path)) {\n const files = fs.readdirSync(path);\n if (!files.length) {\n return;\n }\n for (const file of files) {\n const filePath = `${path}/${file}`;\n if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {\n // if directory then check it\n this._checkDirectory(filePath, verbose);\n } else if (file.endsWith('.json')) {\n try {\n fs.readJSONSync(filePath);\n if (verbose) {\n console.log(`host.${this.hostname} ${file} OK`);\n }\n } catch {\n throw new Error(`host.${this.hostname} ${filePath} is not a valid json file`);\n }\n }\n }\n }\n }\n\n /**\n * Restores a backup\n *\n * @param options Restore options\n */\n async restoreBackup(options: RestoreBackupOptions): Promise<RestoreBackupReturnValue> {\n const { name: _name, dontDeleteAdapters, force } = options;\n\n let backups;\n let name = typeof _name === 'number' ? _name.toString() : _name;\n\n if (!name) {\n // List all available backups\n console.log('Please specify one of the backup names:');\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n if (backups.length) {\n backups.forEach((backup, i) =>\n console.log(`${backup} or ${backup.replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${i}`),\n );\n } else {\n console.warn('No backups found');\n }\n return { exitCode: EXIT_CODES.INVALID_ARGUMENTS, objects: this.objects, states: this.states };\n }\n\n if (!this.cleanDatabase) {\n throw new Error('Invalid arguments: cleanDatabase is missing');\n }\n if (!this.restartController) {\n throw new Error('Invalid arguments: restartController is missing');\n }\n\n // If number\n if (parseInt(name, 10).toString() === name.toString()) {\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n name = backups[parseInt(name, 10)];\n if (!name) {\n console.log('No matching backup found');\n if (backups.length) {\n console.log('Please specify one of the backup names:');\n backups.forEach((backup, i) =>\n console.log(`${backup} or ${backup.replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${i}`),\n );\n }\n return { exitCode: EXIT_CODES.INVALID_ARGUMENTS, objects: this.objects, states: this.states };\n }\n console.log(`host.${this.hostname} Using backup file ${name}`);\n }\n\n name = name.toString().replace(/\\\\/g, '/');\n if (!name.includes('/')) {\n name = BackupRestore.getBackupDir() + name;\n const regEx = new RegExp(this.BACKUP_POSTFIX, 'i');\n if (!regEx.test(name)) {\n name += this.BACKUP_POSTFIX;\n }\n if (!name.match(/\\.tar\\.gz$/i)) {\n name += '.tar.gz';\n }\n }\n if (!fs.existsSync(name)) {\n console.error(`host.${this.hostname} Cannot find ${name}`);\n return { exitCode: EXIT_CODES.INVALID_ARGUMENTS, objects: this.objects, states: this.states };\n }\n\n const backupBasePath = path.join(this.tmpDir, 'backup');\n\n // delete /backup/backup.json\n if (fs.existsSync(path.join(backupBasePath, 'backup.json'))) {\n fs.unlinkSync(path.join(backupBasePath, 'backup.json'));\n }\n\n try {\n await tar.extract({\n file: name,\n cwd: this.tmpDir,\n });\n } catch (e) {\n console.error(`host.${this.hostname} Cannot extract from file \"${name}\": ${e.message}`);\n return { exitCode: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP, objects: this.objects, states: this.states };\n }\n\n if (\n !(await fs.pathExists(path.join(backupBasePath, 'backup.json'))) &&\n !(await fs.pathExists(path.join(backupBasePath, 'objects.jsonl')))\n ) {\n console.error(\n `host.${this.hostname} Cannot find extracted file \"${path.join(backupBasePath, 'backup.json')}\" or \"${path.join(backupBasePath, 'objects.jsonl')}\"`,\n );\n return { exitCode: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP, objects: this.objects, states: this.states };\n }\n\n await CLIProcess.stopJSController();\n const exitCode = await this._restoreAfterStop({\n restartOnFinish: false,\n force,\n dontDeleteAdapters,\n });\n\n this.removeTempBackupDir();\n\n return { exitCode, objects: this.objects, states: this.states };\n }\n\n /**\n * This method checks if adapter of PRESERVE_ADAPTERS exists, and re-installs them if this is the case\n */\n private async _restorePreservedAdapters(): Promise<void> {\n for (const adapterName of this.PRESERVE_ADAPTERS) {\n try {\n const adapterObj = await this.objects.getObject(`system.adapter.${adapterName}`);\n if (adapterObj?.common?.version) {\n let installSource;\n if (adapterObj.common.installedFrom) {\n installSource = adapterObj.common.installedFrom;\n } else {\n installSource = `${tools.appName.toLowerCase()}.${adapterName}@${adapterObj.common.version}`;\n }\n\n console.log(`Reinstalling adapter \"${adapterName}\" from \"${installSource}\"`);\n const res = await tools.installNodeModule(installSource);\n\n if (!res.success) {\n console.error(`Could not install adapter \"${adapterName}\" (${res.exitCode}): ${res.stderr}`);\n }\n }\n } catch (e) {\n console.error(`Could not ensure existence of adapter \"${adapterName}\": ${e.message}`);\n }\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import fs from 'fs-extra';\nimport path from 'node:path';\nimport { EXIT_CODES, tools } from '@iobroker/js-controller-common';\nimport { exec as execAsync } from 'promisify-child-process';\nimport * as tar from 'tar';\nimport type { Client as StatesRedisClient } from '@iobroker/db-states-redis';\nimport type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';\nimport { Upload } from './setupUpload.js';\nimport type { CleanDatabaseHandler, ProcessExitCallback, RestartController } from '../_Types.js';\nimport { dbConnectAsync, resetDbConnect } from './dbConnection.js';\nimport { IoBrokerError } from './customError.js';\nimport { CLIProcess } from '@/lib/cli/cliProcess.js';\nimport { open, writeFile } from 'node:fs/promises';\n\n/** Options for the backup/restore command */\nexport interface CLIBackupRestoreOptions {\n /** Whether this is part of a database migration */\n dbMigration?: boolean;\n /** The states database client */\n states: StatesRedisClient;\n /** The objects database client */\n objects: ObjectsRedisClient;\n /** Callback to exit the process with an exit code */\n processExit: ProcessExitCallback;\n /** Handler to clean the database */\n cleanDatabase: CleanDatabaseHandler;\n /** Handler to restart the controller */\n restartController: RestartController;\n}\n\ntype BackupObject = Omit<ioBroker.GetObjectListItem<ioBroker.Object>, 'doc'>;\n\n/** Result returned after restoring a backup */\nexport interface RestoreBackupReturnValue {\n /** Exit code of the process */\n exitCode: EXIT_CODES;\n /** The new states db connection after restore */\n states: StatesRedisClient;\n /** The new objects db connection after restore */\n objects: ObjectsRedisClient;\n}\n\ninterface RestoreAfterStopOptions {\n /** restart controller after restore */\n restartOnFinish: boolean;\n /** skip the controller version check */\n force: boolean;\n /** skip adapter deletion, e.g. for setup custom db migration */\n dontDeleteAdapters: boolean;\n}\n\ninterface Backup {\n config?: null | ioBroker.IoBrokerJson;\n objects: null | BackupObject[];\n states: Record<string, ioBroker.State>;\n}\n\ninterface PreprocessObjectOptions {\n /** The hostname */\n hostname: string;\n /** The object to preprocess */\n object: ioBroker.Object;\n /** If the host has a custom hostname */\n isCustomHostname: boolean;\n /** String to check if it is a sub object or state of this host (will not match the host object directly) */\n thisHostNameStartsWith: string;\n}\n\n/** Options for restoring a backup */\nexport interface RestoreBackupOptions {\n /** backup name, absolute path or index */\n name: string | number;\n /** if force flag is set, js-controller is allowed to have a different version */\n force: boolean;\n /** skip adapter deletion, e.g. for setup custom db migration */\n dontDeleteAdapters: boolean;\n}\n\nconst controllerDir = tools.getControllerDir();\n\n/**\n * CLI command to create and restore ioBroker backups\n */\nexport class BackupRestore {\n private readonly hostname = tools.getHostName();\n private readonly tmpDir = path.normalize(path.join(controllerDir, 'tmp'));\n private readonly bkpDir = path.normalize(path.join(controllerDir, 'backups'));\n private objects: ObjectsRedisClient;\n private states: StatesRedisClient;\n private readonly processExit: CLIBackupRestoreOptions['processExit'];\n private readonly restartController: CLIBackupRestoreOptions['restartController'];\n private readonly cleanDatabase: CLIBackupRestoreOptions['cleanDatabase'];\n private readonly dbMigration: boolean;\n /** these adapters will be reinstalled during restore, while others will be installed after next controller start */\n private readonly PRESERVE_ADAPTERS = ['admin', 'backitup'] as const;\n private upload: Upload;\n private configParts: string[];\n private readonly configDir: string;\n /** Placeholder inserted during backup creation if no custom hostname defined */\n private readonly HOSTNAME_PLACEHOLDER = '$$__hostname__$$';\n /** Same as HOSTNAME_PLACEHOLDER but used in replace method */\n private readonly HOSTNAME_PLACEHOLDER_REPLACE = '$$$$__hostname__$$$$';\n /** Regex to replace all occurrences of the HOSTNAME_PLACEHOLDER */\n private readonly HOSTNAME_PLACEHOLDER_REGEX = /\\$\\$__hostname__\\$\\$/g;\n /** Postfix for backup name */\n private readonly BACKUP_POSTFIX = `_backup${tools.appNameLowerCase}`;\n\n /**\n * @param options The states/objects clients and the exit, clean and restart handlers\n */\n constructor(options: CLIBackupRestoreOptions) {\n options = options || {};\n\n if (!options.states) {\n throw new Error('Invalid arguments: states is missing');\n }\n if (!options.objects) {\n throw new Error('Invalid arguments: objects is missing');\n }\n if (!options.processExit) {\n throw new Error('Invalid arguments: processExit is missing');\n }\n if (!options.cleanDatabase) {\n throw new Error('Invalid arguments: cleanDatabase is missing');\n }\n if (!options.restartController) {\n throw new Error('Invalid arguments: restartController is missing');\n }\n\n this.objects = options.objects;\n this.states = options.states;\n this.processExit = options.processExit;\n this.cleanDatabase = options.cleanDatabase;\n this.restartController = options.restartController;\n this.dbMigration = options.dbMigration || false;\n\n this.upload = new Upload(options);\n\n this.configParts = tools.getConfigFileName().split('/');\n this.configParts.pop(); // remove *.json\n this.configDir = this.configParts.join('/'); // => name-data\n }\n\n // --------------------------------------- BACKUP ---------------------------------------------------\n private async _copyFile(id: string, srcPath: string, destPath: string): Promise<void> {\n try {\n const data = await this.objects.readFile(id, srcPath);\n if (data) {\n fs.writeFileSync(destPath, data.file);\n }\n } catch (err) {\n console.log(`Can not copy File ${id}${srcPath} to ${destPath}: ${err.message}`);\n }\n }\n\n /**\n * Recursively copy a directory from the object's file storage to disk\n *\n * @param id The object id owning the files\n * @param srcPath The source directory in the object's file storage\n * @param destPath The destination directory on disk\n */\n async copyDir(id: string, srcPath: string, destPath: string): Promise<void> {\n fs.ensureDirSync(destPath);\n\n try {\n const res = await this.objects.readDirAsync(id, srcPath);\n if (res) {\n for (const entry of res) {\n if (entry.isDir) {\n await this.copyDir(id, `${srcPath}/${entry.file}`, `${destPath}/${entry.file}`);\n } else {\n fs.ensureDirSync(destPath);\n await this._copyFile(id, `${srcPath}/${entry.file}`, `${destPath}/${entry.file}`);\n }\n }\n }\n } catch (err) {\n if (!err.message.includes('Not exists')) {\n console.warn(`Directory ${id}/${srcPath} cannot be copied: ${err}`);\n }\n }\n }\n\n /**\n * Get the directory where backups should be stored\n */\n static getBackupDir(): string {\n return path.join(tools.getRootDir(), 'backups/');\n }\n\n /**\n * Copy a single file synchronously\n *\n * @param source The source file path\n * @param target The target file or directory path\n */\n copyFileSync(source: string, target: string): void {\n let targetFile = target;\n\n try {\n // if target is a directory a new file with the same name will be created\n if (fs.existsSync(target)) {\n if (fs.statSync(target).isDirectory()) {\n targetFile = path.join(target, path.basename(source));\n }\n }\n\n fs.writeFileSync(targetFile, fs.readFileSync(source));\n } catch (e) {\n console.error(`Could not copy ${targetFile} to ${source}: ${e.message}`);\n }\n }\n\n /**\n * Recursively copy a folder synchronously\n *\n * @param source The source folder path\n * @param target The target folder path\n */\n copyFolderRecursiveSync(source: string, target: string): void {\n let files = [];\n\n if (!fs.existsSync(target)) {\n fs.mkdirSync(target);\n }\n\n // check if folder needs to be created or integrated\n const targetFolder = path.join(target, path.basename(source));\n if (!fs.existsSync(targetFolder)) {\n fs.mkdirSync(targetFolder);\n }\n\n // copy\n if (fs.existsSync(source) && fs.statSync(source).isDirectory()) {\n files = fs.readdirSync(source);\n files.forEach(file => {\n const curSource = path.join(source, file);\n if (!fs.existsSync(curSource)) {\n return;\n }\n if (fs.statSync(curSource).isDirectory()) {\n this.copyFolderRecursiveSync(curSource, targetFolder);\n } else {\n this.copyFileSync(curSource, targetFolder);\n }\n });\n }\n }\n\n /**\n * Removes the temporary backup directory, never throws\n */\n private removeTempBackupDir(): void {\n try {\n fs.rmSync(path.join(this.tmpDir, 'backup'), { recursive: true, force: true });\n } catch (e) {\n console.error(`host.${this.hostname} Cannot clear temporary backup directory: ${e.message}`);\n }\n }\n\n /**\n * Pack and compress the backup\n *\n * @param name - backup name\n */\n private _packBackup(name: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const f = fs.createWriteStream(name);\n f.on('finish', () => {\n this.removeTempBackupDir();\n resolve(path.normalize(name));\n });\n\n f.on('error', e => {\n console.error(`host.${this.hostname} Cannot pack directory ${this.tmpDir}/backup: ${e.message}`);\n reject(new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_GZIP_DIRECTORY }));\n });\n\n try {\n tar.create({ gzip: true, cwd: `${this.tmpDir}/` }, ['backup']).pipe(f);\n } catch (e) {\n console.error(`host.${this.hostname} Cannot pack directory ${this.tmpDir}/backup: ${e.message}`);\n reject(new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_GZIP_DIRECTORY }));\n }\n });\n }\n\n /**\n * Creates backup and stores with given name\n *\n * @param name - name of the backup\n * @param noConfig - do not store configs (used by setup custom migration)\n */\n async createBackup(name: string, noConfig = false): Promise<string> {\n if (!name) {\n const d = new Date();\n name = `${d.getFullYear()}_${`0${d.getMonth() + 1}`.slice(-2)}_${`0${d.getDate()}`.slice(-2)}-${`0${d.getHours()}`.slice(\n -2,\n )}_${`0${d.getMinutes()}`.slice(-2)}_${`0${d.getSeconds()}`.slice(-2)}${this.BACKUP_POSTFIX}`;\n } else if (!name.endsWith(this.BACKUP_POSTFIX) && !name.endsWith(`${this.BACKUP_POSTFIX}.tar.gz`)) {\n name += this.BACKUP_POSTFIX;\n }\n\n name = name.toString().replace(/\\\\/g, '/');\n if (!name.includes('/')) {\n const backupPath = BackupRestore.getBackupDir();\n\n // create directory if not exists\n fs.ensureDirSync(backupPath);\n\n if (!name.includes('.tar.gz')) {\n name = `${backupPath + name}.tar.gz`;\n } else {\n name = backupPath + name;\n }\n }\n\n const hostname = tools.getHostName();\n // String to check if it is a sub object or state of this host (will not match the host object directly)\n const thisHostNameStartsWith = `system.host.${hostname}.`;\n\n fs.ensureDirSync(this.bkpDir);\n fs.ensureDirSync(this.tmpDir);\n\n this.removeTempBackupDir();\n\n const backupBasePath = path.join(this.tmpDir, 'backup');\n fs.ensureDirSync(backupBasePath);\n fs.ensureDirSync(path.join(backupBasePath, 'files'));\n\n let isCustomHostname = false;\n let config: ioBroker.IoBrokerJson | undefined;\n\n // read iobroker.json\n try {\n config = (await fs.readJSON(tools.getConfigFileName())) as ioBroker.IoBrokerJson;\n // if a hostname is configured\n isCustomHostname = !!config.system.hostname;\n } catch (e) {\n console.error(`host.${hostname} Cannot read config file: ${e.message}`);\n }\n\n if (!noConfig && config) {\n await writeFile(path.join(backupBasePath, 'config.json'), JSON.stringify(config), { encoding: 'utf-8' });\n }\n\n const objectsFd = await open(path.join(backupBasePath, 'objects.jsonl'), 'a');\n\n try {\n const res = await this.objects.getObjectListAsync({ include_docs: true });\n for (const row of res.rows) {\n const preprocessedValue = await this._preprocessObject({\n object: row.value,\n isCustomHostname,\n hostname,\n thisHostNameStartsWith,\n });\n await objectsFd.write(`${JSON.stringify(preprocessedValue)}\\n`);\n }\n\n console.log(`host.${hostname} ${res.rows.length || 'no'} objects saved`);\n } catch (e) {\n console.error(`host.${hostname} Cannot get objects: ${e.message}`);\n }\n\n await objectsFd.close();\n\n const statesFd = await open(path.join(backupBasePath, 'states.jsonl'), 'a');\n\n try {\n const keys = await this.states.getKeys('*');\n const objs = await this.states.getStates(keys!);\n\n if (keys) {\n for (let i = 0; i < keys.length; i++) {\n const obj = objs[i];\n\n if (!obj) {\n continue;\n }\n\n if (!isCustomHostname) {\n // if it's a default hostname, we will have a new default after restore and need to replace\n if (obj.from === `system.host.${hostname}`) {\n obj.from.replace(\n `system.host.${hostname}`,\n `system.host.${this.HOSTNAME_PLACEHOLDER_REPLACE}`,\n );\n }\n if (keys[i].startsWith(thisHostNameStartsWith)) {\n keys[i] = keys[i].replace(hostname, this.HOSTNAME_PLACEHOLDER_REPLACE);\n }\n }\n\n await statesFd.write(`${JSON.stringify({ id: keys[i], state: obj })}\\n`);\n }\n\n await statesFd.close();\n console.log(`host.${hostname} ${keys.length} states saved`);\n }\n } catch (e) {\n console.error(`host.${hostname} Cannot get states: ${e.message}`);\n }\n\n console.log(`host.${hostname} Validating backup ...`);\n try {\n await this._validateTempDirectory(noConfig);\n console.log(`host.${hostname} The backup is valid!`);\n\n return await this._packBackup(name);\n } catch (e) {\n console.error(`host.${hostname} Backup not created: ${e.message}`);\n this.removeTempBackupDir();\n\n if (e instanceof IoBrokerError) {\n throw e;\n }\n\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP });\n }\n }\n\n //--------------------------------------- RESTORE ---------------------------------------------------\n /**\n * Helper to restore raw state\n *\n * @param stateId - state ID\n * @param stateObject - the corresponding state object\n */\n private async _setStateHelper(stateId: string, stateObject: ioBroker.State): Promise<void> {\n try {\n await this.states.setRawState(stateId, stateObject);\n } catch (e) {\n console.log(`host.${this.hostname} Could not set value for state ${stateId}: ${e.message}`);\n }\n }\n\n /**\n * Sets all objects to the db and disables all adapters\n *\n * @param object - object to be set\n */\n private async _setObjHelper(object: ioBroker.Object): Promise<void> {\n // Disable all adapters.\n if (\n !this.dbMigration &&\n object._id &&\n /^system\\.adapter\\..+\\.\\d$/.test(object._id) &&\n !object._id.startsWith('system.adapter.admin.') &&\n !object._id.startsWith('system.adapter.backitup.')\n ) {\n if (object.common?.enabled) {\n object.common.enabled = false;\n }\n }\n\n try {\n await this.objects.setObject(object._id, object);\n } catch (e) {\n console.warn(`host.${this.hostname} Cannot restore ${object._id}: ${e.message}`);\n }\n }\n\n /**\n * Creates all provided object if non-existing\n *\n * @param objectList - list of objects to be created\n */\n private async _reloadAdapterObject(objectList: ioBroker.Object[]): Promise<void> {\n if (!Array.isArray(objectList)) {\n return;\n }\n\n for (const object of objectList) {\n let obj;\n try {\n obj = await this.objects.getObject(object._id);\n } catch {\n // ignore\n }\n\n if (!obj) {\n // object not existing -> create it\n try {\n await this.objects.setObject(object._id, object);\n console.log(`host.${this.hostname} object ${object._id} created`);\n } catch {\n // ignore\n }\n }\n }\n }\n\n private async _reloadAdaptersObjects(): Promise<void> {\n const dirs: string[] = [];\n let _modules;\n let p = path.join(controllerDir, 'node_modules');\n\n if (p.includes('js-controller')) {\n p = path.join(controllerDir, '..', 'node_modules');\n }\n\n if (fs.existsSync(p)) {\n _modules = fs.readdirSync(p).filter(dir => fs.existsSync(`${p}/${dir}/io-package.json`));\n if (_modules) {\n const regEx = new RegExp(`^${tools.appName}\\\\.`, 'i');\n for (const module of _modules) {\n if (regEx.test(module) && !dirs.includes(module.substring(tools.appName.length + 1))) {\n dirs.push(module);\n }\n }\n }\n }\n\n // if installed as npm\n if (\n fs.existsSync(\n path.join(controllerDir, '..', '..', 'node_modules', `${tools.appName.toLowerCase()}.js-controller`),\n )\n ) {\n const p = path.join(controllerDir, '..');\n _modules = fs.readdirSync(p).filter(dir => fs.existsSync(`${p}/${dir}/io-package.json`));\n const regEx_ = new RegExp(`^${tools.appName}\\\\.`, 'i');\n for (const module of _modules) {\n // if starting from application name + '.'\n if (\n regEx_.test(module) &&\n // If not js-controller\n module.substring(tools.appName.length + 1) !== 'js-controller' &&\n !dirs.includes(module.substring(tools.appName.length + 1))\n ) {\n dirs.push(module);\n }\n }\n }\n\n for (const dir of dirs) {\n const adapterName = dir.replace(/^iobroker\\./i, '');\n await this.upload.uploadAdapter(adapterName, false, true);\n await this.upload.uploadAdapter(adapterName, true, true);\n\n let pkg;\n\n if (!dir) {\n console.error('Wrong');\n }\n const adapterDir = tools.getAdapterDir(adapterName);\n if (fs.existsSync(`${adapterDir}/io-package.json`)) {\n pkg = fs.readJSONSync(`${adapterDir}/io-package.json`);\n }\n\n if (pkg?.objects?.length) {\n console.log(`host.${this.hostname} Setup \"${dir}\" adapter`);\n await this._reloadAdapterObject(pkg.objects);\n }\n }\n }\n\n private async _uploadUserFiles(root: string, uploadPath?: string): Promise<void> {\n uploadPath = uploadPath || '';\n if (!fs.existsSync(root)) {\n return;\n }\n const files = fs.readdirSync(root + uploadPath);\n for (const file of files) {\n const fName = path.join(root, uploadPath, file);\n if (!fs.existsSync(fName)) {\n continue;\n }\n const stat = fs.statSync(fName);\n if (stat.isDirectory()) {\n try {\n await this._uploadUserFiles(root, `${uploadPath}/${file}`);\n } catch (err) {\n console.error(`Error: ${err}`);\n }\n } else {\n const parts = uploadPath.split('/');\n const adapter = parts.splice(0, 2)[1];\n const _path = `${parts.join('/')}/${file}`;\n console.log(`host.${this.hostname} Upload user file \"${adapter}/${_path}`);\n try {\n await this.objects.writeFileAsync(adapter, _path, fs.readFileSync(`${root + uploadPath}/${file}`));\n } catch (err) {\n console.error(`Error: ${err.message}`);\n }\n }\n }\n }\n\n /**\n * Preprocess object before storing it in the backup file\n *\n * @param options object and host information\n */\n private async _preprocessObject(options: PreprocessObjectOptions): Promise<ioBroker.Object> {\n const { object, isCustomHostname, hostname, thisHostNameStartsWith } = options;\n\n if (!object || !object._id || !object.common) {\n return object;\n }\n\n if (!isCustomHostname) {\n if (object._id.match(/^system\\.adapter\\.([\\w\\d_-]+).(\\d+)$/) && object.common.host === hostname) {\n object.common.host = this.HOSTNAME_PLACEHOLDER;\n object.common.host = this.HOSTNAME_PLACEHOLDER;\n } else if (object._id.startsWith(thisHostNameStartsWith)) {\n object._id = object._id.replace(hostname, this.HOSTNAME_PLACEHOLDER_REPLACE);\n } else if (object._id === `system.host.${hostname}`) {\n object._id = `system.host.${this.HOSTNAME_PLACEHOLDER}`;\n object.common.name = object._id;\n object.common.hostname = this.HOSTNAME_PLACEHOLDER;\n if (object.native && object.native.os) {\n object.native.os.hostname = this.HOSTNAME_PLACEHOLDER;\n }\n\n object.common.name = object._id;\n object.common.hostname = this.HOSTNAME_PLACEHOLDER;\n if (object.native?.os) {\n object.native.os.hostname = this.HOSTNAME_PLACEHOLDER;\n }\n }\n }\n\n // Read all files\n if (object.type === 'meta' && object.common?.type === 'meta.user') {\n // do not process \"xxx.0. \" and \"xxx.0.\"\n if (object._id.trim() === object._id && object._id[object._id.length - 1] !== '.') {\n await this.copyDir(object._id, '', `${this.tmpDir}/backup/files/${object._id}`);\n }\n }\n\n // Read all files\n if (object.type === 'instance' && object.common?.dataFolder) {\n let dataFolderPath = object.common.dataFolder;\n\n if (dataFolderPath[0] !== '/' && !dataFolderPath.match(/^\\w:/)) {\n dataFolderPath = path.join(this.configDir, dataFolderPath);\n }\n\n if (fs.existsSync(dataFolderPath)) {\n try {\n this.copyFolderRecursiveSync(dataFolderPath, `${this.tmpDir}/backup`);\n } catch (e) {\n console.error(`host.${hostname} Could not backup \"${dataFolderPath}\" directory: ${e.message}`);\n this.removeTempBackupDir();\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_COPY_DIR });\n }\n }\n }\n\n return object;\n }\n\n private _copyBackupedFiles(backupDir: string): void {\n try {\n if (!fs.existsSync(backupDir)) {\n console.log('No additional files to restore');\n return;\n }\n const dirs = fs.readdirSync(backupDir);\n\n dirs.forEach(dir => {\n if (dir === 'files') {\n return;\n }\n const backupPath = path.join(backupDir, dir);\n let stat;\n try {\n if (!fs.existsSync(backupPath)) {\n return;\n }\n stat = fs.statSync(backupPath);\n } catch (e) {\n console.error(`Ignoring ${backupPath} because can not get file type: ${e.message}`);\n return;\n }\n if (stat.isDirectory()) {\n this.copyFolderRecursiveSync(backupPath, this.configDir);\n }\n });\n } catch (e) {\n console.error(`Ignoring ${backupDir} because can not read directory: ${e.message}`);\n }\n }\n\n /**\n * Restore JSONL backup after controller has been stopped\n *\n * @param options The restore options\n */\n private async _restoreJsonlBackup(options: RestoreAfterStopOptions): Promise<EXIT_CODES> {\n const { force, dontDeleteAdapters } = options;\n const hostname = tools.getHostName();\n\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n\n let backupHostName = hostname;\n // Note: on backups created during migration no config exists\n let config: ioBroker.IoBrokerJson | undefined;\n\n if (await fs.pathExists(path.join(backupBaseDir, 'config.json'))) {\n config = (await fs.readJSON(path.join(backupBaseDir, 'config.json'))) as ioBroker.IoBrokerJson;\n backupHostName = config.system?.hostname || hostname;\n }\n\n // we need to find the host obj for the compatibility check\n const objFd = await open(path.join(backupBaseDir, 'objects.jsonl'));\n const rlObj = objFd.readLines();\n\n const hostObjArr: BackupObject[] = [];\n\n for await (let line of rlObj) {\n line = line.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n const obj: ioBroker.Object = JSON.parse(line);\n if (obj._id === `system.host.${backupHostName}`) {\n hostObjArr.push({ id: obj._id, value: obj });\n break;\n }\n }\n\n await objFd.close();\n\n // check that the same controller version is installed as it is contained in backup\n const exitCode = this._ensureCompatibility(controllerDir, backupHostName, hostObjArr, force);\n\n if (exitCode) {\n // we had an error\n return exitCode;\n }\n\n if (!dontDeleteAdapters) {\n // prevent having wrong versions of adapters\n await this._removeAllAdapters();\n }\n\n // restore ioBroker.json\n if (config) {\n fs.writeFileSync(tools.getConfigFileName(), JSON.stringify(config, null, 2));\n await this.connectToNewDatabase(config);\n }\n\n console.log(`host.${hostname} Clear all objects and states...`);\n await this.cleanDatabase(false);\n console.log(`host.${hostname} done.`);\n\n const objectsFd = await open(path.join(backupBaseDir, 'objects.jsonl'));\n const rlObjects = objectsFd.readLines();\n\n let count = 0;\n\n for await (let line of rlObjects) {\n line = line.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n const obj: ioBroker.Object = JSON.parse(line);\n await this._setObjHelper(obj);\n count++;\n }\n\n console.log(`${count} objects restored.`);\n\n await objectsFd.close();\n\n const statesFd = await open(path.join(backupBaseDir, 'states.jsonl'));\n const rlStates = statesFd.readLines();\n\n count = 0;\n\n for await (let line of rlStates) {\n line = line.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n const state: {\n /** The id of the state */\n id: string;\n /** The state value */\n state: ioBroker.State;\n } = JSON.parse(line);\n await this._setStateHelper(state.id, state.state);\n count++;\n }\n\n console.log(`${count} states restored.`);\n\n await statesFd.close();\n\n return EXIT_CODES.NO_ERROR;\n }\n\n /**\n * Restore after controller has been stopped\n *\n * @param options The restore options\n */\n private async _restoreAfterStop(options: RestoreAfterStopOptions): Promise<EXIT_CODES> {\n const { force, restartOnFinish, dontDeleteAdapters } = options;\n\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n const isJsonl = await fs.pathExists(path.join(backupBaseDir, 'objects.jsonl'));\n\n if (isJsonl) {\n const exitCode = await this._restoreJsonlBackup(options);\n if (exitCode !== EXIT_CODES.NO_ERROR) {\n return exitCode;\n }\n } else {\n const hostname = tools.getHostName();\n console.log(`host.${hostname} Restore legacy backup.`);\n\n // Open file\n let data = fs.readFileSync(path.join(backupBaseDir, 'backup.json'), 'utf8');\n // replace all hostnames of instances etc with the new host\n data = data.replace(this.HOSTNAME_PLACEHOLDER_REGEX, hostname);\n fs.writeFileSync(path.join(backupBaseDir, 'backup_.json'), data);\n let restore: Backup;\n try {\n restore = JSON.parse(data);\n } catch (e) {\n console.error(`Cannot parse \"${path.join(backupBaseDir, 'backup_.json')}\": ${e.message}`);\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n\n if (!restore.objects) {\n console.error('The backup does not contain any objects.');\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n\n // check that the same controller version is installed as it is contained in backup\n const exitCode = this._ensureCompatibility(\n controllerDir,\n restore.config?.system?.hostname || hostname,\n restore.objects,\n force,\n );\n\n if (exitCode) {\n // we had an error\n return exitCode;\n }\n\n if (!dontDeleteAdapters) {\n // prevent having wrong versions of adapters\n await this._removeAllAdapters();\n }\n\n // restore ioBroker.json\n if (restore.config) {\n fs.writeFileSync(tools.getConfigFileName(), JSON.stringify(restore.config, null, 2));\n await this.connectToNewDatabase(restore.config);\n }\n\n console.log(`host.${hostname} Clear all objects and states...`);\n await this.cleanDatabase(false);\n console.log(`host.${hostname} done.`);\n\n const sList = Object.keys(restore.states);\n\n for (let i = 0; i < restore.objects.length; i++) {\n await this._setObjHelper(restore.objects[i].value);\n if (i % 200 === 0) {\n console.log(`host.${this.hostname} Processed ${i}/${restore.objects.length} objects`);\n }\n }\n\n console.log(`${restore.objects.length} objects restored.`);\n for (let i = 0; i < sList.length; i++) {\n const id = sList[i];\n await this._setStateHelper(id, restore.states[id]);\n if (i % 200 === 0) {\n console.log(`host.${this.hostname} Processed ${i}/${sList.length} states`);\n }\n }\n\n console.log(`${sList.length} states restored.`);\n }\n\n // Load user files into DB\n await this._uploadUserFiles(path.join(backupBaseDir, 'files'));\n // reload objects of adapters (if some couldn't be removed - normally this shouldn't be necessary anymore)\n await this._reloadAdaptersObjects();\n // Reload host objects\n const packageIO = fs.readJSONSync(path.join(controllerDir, 'io-package.json'));\n await this._reloadAdapterObject(packageIO ? packageIO.objects : null);\n // copy all files into iob-data\n this._copyBackupedFiles(backupBaseDir);\n // reinstall preserve adapters\n await this._restorePreservedAdapters();\n\n if (force) {\n // js-controller version has changed (setup never called for this version)\n console.log('Forced restore - executing setup ...');\n try {\n await execAsync(\n `\"${process.execPath}\" \"${path.join(controllerDir, `${tools.appName.toLowerCase()}.js`)}\" setup`,\n );\n } catch (e) {\n console.error(\n `Could not execute \"setup\" command, please ensure \"setup\" is called before starting ioBroker: ${e.message}`,\n );\n }\n }\n\n if (restartOnFinish) {\n console.log('restart');\n this.restartController();\n }\n\n return EXIT_CODES.NO_ERROR;\n }\n\n /**\n * Connects to the database which is configured in `iobroker.json`\n * Meant to be used after the configuration file has been overwritten\n *\n * @param config The new config, needed for logging purposes\n */\n private async connectToNewDatabase(config: ioBroker.IoBrokerJson): Promise<void> {\n console.log(\n `host.${this.hostname} Connecting to new DB \"${config.states.type}/${config.objects.type}\" (can take up to 20s) ...`,\n );\n await resetDbConnect();\n const { objects, states } = await dbConnectAsync(false);\n console.log(`host.${this.hostname} Successfully connected to new DB`);\n\n this.upload = new Upload({ states, objects });\n\n this.objects = objects;\n this.states = states;\n }\n\n /**\n * Removes all adapters\n */\n private async _removeAllAdapters(): Promise<void> {\n const nodeModulePath = path.join(controllerDir, '..');\n const nodeModuleDirs = fs.readdirSync(nodeModulePath, { withFileTypes: true });\n // we need to uninstall current adapters to get exact the same system as before backup\n for (const dir of nodeModuleDirs) {\n if (\n dir.isDirectory() &&\n dir.name.startsWith(`${tools.appName.toLowerCase()}.`) &&\n dir.name !== `${tools.appName.toLowerCase()}.js-controller`\n ) {\n try {\n const packJson = fs.readJsonSync(path.join(nodeModulePath, dir.name, 'package.json'));\n console.log(`Removing current installation of ${packJson.name}`);\n await tools.uninstallNodeModule(packJson.name);\n } catch {\n // ignore\n }\n }\n }\n }\n\n /**\n * Ensure that installed controller version matches version in backup\n *\n * @param controllerDir - directory of js-controller\n * @param backupHostname - hostname in backup file\n * @param backupObjects - the objects contained in the backup\n * @param force - if force is true, only log\n */\n private _ensureCompatibility(\n controllerDir: string,\n backupHostname: string,\n backupObjects: BackupObject[],\n force: boolean,\n ): void | number {\n try {\n const ioPackJson = fs.readJsonSync(path.join(controllerDir, 'io-package.json'));\n const hostObj = backupObjects.find(obj => obj.id === `system.host.${backupHostname}`);\n\n if (!hostObj) {\n console.error('No host object found, your backup seems to be corrupted!');\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n\n if (hostObj.value.common.installedVersion !== ioPackJson.common.version) {\n if (!force) {\n console.warn('The current version of js-controller differs from the version in the backup.');\n console.warn('The js-controller version of the backup can not be restored automatically.');\n console.warn(\n `To restore the js-controller version of the backup, execute \"npm i iobroker.js-controller@${hostObj.value.common.installedVersion} --omit=dev\" inside your ioBroker directory`,\n );\n console.warn(\n 'If you really want to restore the backup with the current installed js-controller, execute the restore command with the --force flag',\n );\n\n return EXIT_CODES.CANNOT_RESTORE_BACKUP;\n }\n console.info('The current version of js-controller differs from the version in the backup.');\n console.info('The js-controller version of the backup can not be restored automatically.');\n console.info('Note, that your backup might differ in behavior due to this version change!');\n }\n } catch {\n // ignore\n }\n }\n\n /**\n * Returns all backups as array\n */\n listBackups(): string[] {\n const dir = BackupRestore.getBackupDir();\n const result: string[] = [];\n if (fs.existsSync(dir)) {\n const files = fs.readdirSync(dir);\n for (const file of files) {\n if (file.match(/\\.tar\\.gz$/i)) {\n result.push(file);\n }\n }\n return result;\n }\n return result;\n }\n\n /**\n * Validates a JSONL-style backup and all json files inside the backup (in temporary directory)\n *\n * @param noConfig if the backup does not contain a `config.json` (used by setup custom migration)\n */\n private async _validateTempDirectory(noConfig = false): Promise<void> {\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n\n if (!noConfig) {\n await fs.readJSON(path.join(backupBaseDir, 'config.json'));\n console.log(`host.${this.hostname} \"config.json\" is valid`);\n }\n\n if (!(await fs.pathExists(path.join(backupBaseDir, 'objects.jsonl')))) {\n throw new Error('Backup does not contain valid objects');\n }\n\n console.log(`host.${this.hostname} \"objects.jsonl\" exists`);\n\n if (!(await fs.pathExists(path.join(backupBaseDir, 'states.jsonl')))) {\n throw new Error('Backup does not contain valid states');\n }\n\n console.log(`host.${this.hostname} \"states.jsonl\" exists`);\n\n await this._validateDatabaseFiles();\n\n console.log(`host.${this.hostname} JSONL lines are valid`);\n\n // we check all other json files, we assume them as optional, because user created files may be no valid json\n try {\n this._checkDirectory(path.join(backupBaseDir, 'files'));\n } catch (e) {\n console.warn(`host.${this.hostname} One or more optional files are corrupted: ${e.message}`);\n console.warn(`host.${this.hostname} Please ensure that self-created JSON files are valid`);\n }\n }\n\n /**\n * Validate that the created JSONL files in the temporary directories are parseable\n */\n private async _validateDatabaseFiles(): Promise<void> {\n const backupBaseDir = path.join(this.tmpDir, 'backup');\n\n const objectsFd = await open(path.join(backupBaseDir, 'objects.jsonl'));\n const rlObjects = objectsFd.readLines();\n\n for await (const line of rlObjects) {\n try {\n JSON.parse(line);\n } catch (e) {\n throw new Error(`The \"objects.jsonl\" file is corrupted: ${e.message}`);\n }\n }\n\n await objectsFd.close();\n\n const statesFd = await open(path.join(backupBaseDir, 'states.jsonl'));\n const rlStates = statesFd.readLines();\n\n for await (const line of rlStates) {\n try {\n JSON.parse(line);\n } catch (e) {\n throw new Error(`The \"states.jsonl\" file is corrupted: ${e.message}`);\n }\n }\n\n await statesFd.close();\n }\n\n /**\n * Validates the given backup.json and all json files in the backup, calls processExit afterwards\n *\n * @param _name - index or name of the backup\n */\n async validateBackup(_name: string | number): Promise<void> {\n let backups;\n let name = typeof _name === 'number' ? _name.toString() : _name;\n\n if (!name) {\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n if (backups.length) {\n // List all available backups\n console.log('Please specify one of the backup names:');\n\n for (const t in backups) {\n console.log(`${backups[t]} or ${backups[t].replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${t}`);\n }\n } else {\n console.warn(`No backups found. Create a backup, using \"${tools.appName} backup\" first`);\n }\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n // If number\n if (parseInt(name, 10).toString() === name.toString()) {\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n name = backups[parseInt(name, 10)];\n if (!name) {\n console.log('No matching backup found');\n if (backups.length) {\n console.log('Please specify one of the backup names:');\n for (const t in backups) {\n console.log(\n `${backups[t]} or ${backups[t].replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${t}`,\n );\n }\n } else {\n console.log(`No existing backups. Create a backup, using \"${tools.appName} backup\" first`);\n }\n\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n console.log(`host.${this.hostname} Using backup file ${name}`);\n }\n\n name = name.toString().replace(/\\\\/g, '/');\n if (!name.includes('/')) {\n name = BackupRestore.getBackupDir() + name;\n const regEx = new RegExp(this.BACKUP_POSTFIX, 'i');\n if (!regEx.test(name)) {\n name += this.BACKUP_POSTFIX;\n }\n if (!name.match(/\\.tar\\.gz$/i)) {\n name += '.tar.gz';\n }\n }\n if (!fs.existsSync(name)) {\n console.error(`host.${this.hostname} Cannot find ${name}`);\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n\n if (fs.existsSync(`${this.tmpDir}/backup/backup.json`)) {\n fs.unlinkSync(`${this.tmpDir}/backup/backup.json`);\n }\n\n try {\n await tar.extract({\n file: name,\n cwd: this.tmpDir,\n });\n } catch (e) {\n const errMessage = `Cannot extract from file \"${name}\": ${e.message}`;\n console.error(`host.${this.hostname} ${errMessage}`);\n throw new IoBrokerError({ message: 'Backup not found', code: EXIT_CODES.INVALID_ARGUMENTS });\n }\n\n try {\n if (fs.existsSync(path.join(this.tmpDir, 'backup', 'backup.json'))) {\n this._validateLegacyTempDir();\n } else {\n await this._validateTempDirectory();\n }\n } catch (e) {\n console.error(`host.${this.hostname} ${e.message}`);\n\n try {\n this.removeTempBackupDir();\n } catch (e) {\n console.error(`host.${this.hostname} Cannot clear temporary backup directory: ${e.message}`);\n }\n\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP });\n }\n\n try {\n this.removeTempBackupDir();\n } catch (e) {\n console.error(`host.${this.hostname} Cannot clear temporary backup directory: ${e.message}`);\n throw new IoBrokerError({ message: e.message, code: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP });\n }\n }\n\n /**\n * Validate an unpacked legacy backup in the temporary directory\n */\n private _validateLegacyTempDir(): void {\n console.log(`host.${this.hostname} Starting validation ...`);\n let backupJSON;\n try {\n backupJSON = fs.readJSONSync(`${this.tmpDir}/backup/backup.json`);\n } catch (e) {\n throw new Error(`Backup corrupted. Backup does not contain a valid backup.json file: ${e.message}`);\n }\n\n if (!backupJSON || !backupJSON.objects || !backupJSON.objects.length) {\n throw new Error(`host.${this.hostname} Backup corrupted. Backup does not contain valid objects`);\n }\n\n console.log(`host.${this.hostname} backup.json OK`);\n\n try {\n this._checkDirectory(`${this.tmpDir}/backup/files`, true);\n } catch (e) {\n throw new Error(`Backup corrupted: ${e.message}`);\n }\n }\n\n /**\n * Checks a directory for json files and validates them, steps down recursive in subdirectories\n *\n * @param path - path to the directory\n * @param verbose - if logging should be verbose\n */\n private _checkDirectory(path: string, verbose = false): void {\n if (fs.existsSync(path)) {\n const files = fs.readdirSync(path);\n if (!files.length) {\n return;\n }\n for (const file of files) {\n const filePath = `${path}/${file}`;\n if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {\n // if directory then check it\n this._checkDirectory(filePath, verbose);\n } else if (file.endsWith('.json')) {\n try {\n fs.readJSONSync(filePath);\n if (verbose) {\n console.log(`host.${this.hostname} ${file} OK`);\n }\n } catch {\n throw new Error(`host.${this.hostname} ${filePath} is not a valid json file`);\n }\n }\n }\n }\n }\n\n /**\n * Restores a backup\n *\n * @param options Restore options\n */\n async restoreBackup(options: RestoreBackupOptions): Promise<RestoreBackupReturnValue> {\n const { name: _name, dontDeleteAdapters, force } = options;\n\n let backups;\n let name = typeof _name === 'number' ? _name.toString() : _name;\n\n if (!name) {\n // List all available backups\n console.log('Please specify one of the backup names:');\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n if (backups.length) {\n backups.forEach((backup, i) =>\n console.log(`${backup} or ${backup.replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${i}`),\n );\n } else {\n console.warn('No backups found');\n }\n return { exitCode: EXIT_CODES.INVALID_ARGUMENTS, objects: this.objects, states: this.states };\n }\n\n if (!this.cleanDatabase) {\n throw new Error('Invalid arguments: cleanDatabase is missing');\n }\n if (!this.restartController) {\n throw new Error('Invalid arguments: restartController is missing');\n }\n\n // If number\n if (parseInt(name, 10).toString() === name.toString()) {\n backups = this.listBackups();\n backups.sort((a, b) => (b > a ? 1 : b === a ? 0 : -1));\n name = backups[parseInt(name, 10)];\n if (!name) {\n console.log('No matching backup found');\n if (backups.length) {\n console.log('Please specify one of the backup names:');\n backups.forEach((backup, i) =>\n console.log(`${backup} or ${backup.replace(`${this.BACKUP_POSTFIX}.tar.gz`, '')} or ${i}`),\n );\n }\n return { exitCode: EXIT_CODES.INVALID_ARGUMENTS, objects: this.objects, states: this.states };\n }\n console.log(`host.${this.hostname} Using backup file ${name}`);\n }\n\n name = name.toString().replace(/\\\\/g, '/');\n if (!name.includes('/')) {\n name = BackupRestore.getBackupDir() + name;\n const regEx = new RegExp(this.BACKUP_POSTFIX, 'i');\n if (!regEx.test(name)) {\n name += this.BACKUP_POSTFIX;\n }\n if (!name.match(/\\.tar\\.gz$/i)) {\n name += '.tar.gz';\n }\n }\n if (!fs.existsSync(name)) {\n console.error(`host.${this.hostname} Cannot find ${name}`);\n return { exitCode: EXIT_CODES.INVALID_ARGUMENTS, objects: this.objects, states: this.states };\n }\n\n const backupBasePath = path.join(this.tmpDir, 'backup');\n\n // delete /backup/backup.json\n if (fs.existsSync(path.join(backupBasePath, 'backup.json'))) {\n fs.unlinkSync(path.join(backupBasePath, 'backup.json'));\n }\n\n try {\n await tar.extract({\n file: name,\n cwd: this.tmpDir,\n });\n } catch (e) {\n console.error(`host.${this.hostname} Cannot extract from file \"${name}\": ${e.message}`);\n return { exitCode: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP, objects: this.objects, states: this.states };\n }\n\n if (\n !(await fs.pathExists(path.join(backupBasePath, 'backup.json'))) &&\n !(await fs.pathExists(path.join(backupBasePath, 'objects.jsonl')))\n ) {\n console.error(\n `host.${this.hostname} Cannot find extracted file \"${path.join(backupBasePath, 'backup.json')}\" or \"${path.join(backupBasePath, 'objects.jsonl')}\"`,\n );\n return { exitCode: EXIT_CODES.CANNOT_EXTRACT_FROM_ZIP, objects: this.objects, states: this.states };\n }\n\n await CLIProcess.stopJSController();\n const exitCode = await this._restoreAfterStop({\n restartOnFinish: false,\n force,\n dontDeleteAdapters,\n });\n\n this.removeTempBackupDir();\n\n return { exitCode, objects: this.objects, states: this.states };\n }\n\n /**\n * This method checks if adapter of PRESERVE_ADAPTERS exists, and re-installs them if this is the case\n */\n private async _restorePreservedAdapters(): Promise<void> {\n for (const adapterName of this.PRESERVE_ADAPTERS) {\n try {\n const adapterObj = await this.objects.getObject(`system.adapter.${adapterName}`);\n if (adapterObj?.common?.version) {\n let installSource;\n if (adapterObj.common.installedFrom) {\n installSource = adapterObj.common.installedFrom;\n } else {\n installSource = `${tools.appName.toLowerCase()}.${adapterName}@${adapterObj.common.version}`;\n }\n\n console.log(`Reinstalling adapter \"${adapterName}\" from \"${installSource}\"`);\n const res = await tools.installNodeModule(installSource);\n\n if (!res.success) {\n console.error(`Could not install adapter \"${adapterName}\" (${res.exitCode}): ${res.stderr}`);\n }\n }\n } catch (e) {\n console.error(`Could not ensure existence of adapter \"${adapterName}\": ${e.message}`);\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["path", "fs", "module", "p", "execAsync", "controllerDir", "e"]
|
|
7
7
|
}
|
|
@@ -10,16 +10,22 @@ import { EXIT_CODES } from '@iobroker/js-controller-common';
|
|
|
10
10
|
import type { Client as StatesRedisClient } from '@iobroker/db-states-redis';
|
|
11
11
|
import type { Client as ObjectsRedisClient } from '@iobroker/db-objects-redis';
|
|
12
12
|
import type { ProcessExitCallback } from '../../lib/_Types.js';
|
|
13
|
+
/** Options for the install command */
|
|
13
14
|
export interface CLIInstallOptions {
|
|
15
|
+
/** Parsed CLI parameters */
|
|
14
16
|
params: Record<string, any>;
|
|
17
|
+
/** The states database client */
|
|
15
18
|
states: StatesRedisClient;
|
|
19
|
+
/** The objects database client */
|
|
16
20
|
objects: ObjectsRedisClient;
|
|
21
|
+
/** Callback to exit the process with an exit code */
|
|
17
22
|
processExit: ProcessExitCallback;
|
|
18
23
|
}
|
|
19
24
|
interface DownloadPacketReturnObject {
|
|
20
25
|
stoppedList: ioBroker.InstanceObject[];
|
|
21
26
|
packetName: string;
|
|
22
27
|
}
|
|
28
|
+
/** Options for downloading an adapter packet */
|
|
23
29
|
export interface CLIDownloadPacketOptions {
|
|
24
30
|
/** will stop the db before upgrade ONLY use it for controller upgrade */
|
|
25
31
|
stopDb?: boolean;
|
|
@@ -35,6 +41,9 @@ interface CreateInstanceOptions {
|
|
|
35
41
|
host?: string;
|
|
36
42
|
port?: number;
|
|
37
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* CLI command to install and download adapters and create their instances
|
|
46
|
+
*/
|
|
38
47
|
export declare class Install {
|
|
39
48
|
private readonly isRootOnUnix;
|
|
40
49
|
private readonly objects;
|
|
@@ -44,6 +53,9 @@ export declare class Install {
|
|
|
44
53
|
private readonly tarballRegex;
|
|
45
54
|
private upload;
|
|
46
55
|
private packetManager?;
|
|
56
|
+
/**
|
|
57
|
+
* @param options The states/objects clients, CLI parameters and the process-exit callback
|
|
58
|
+
*/
|
|
47
59
|
constructor(options: CLIInstallOptions);
|
|
48
60
|
/**
|
|
49
61
|
* Enables or disables given instances
|
|
@@ -94,11 +106,22 @@ export declare class Install {
|
|
|
94
106
|
* Installs given adapter
|
|
95
107
|
*
|
|
96
108
|
* @param adapter The adapter name
|
|
97
|
-
* @param repoUrl
|
|
98
|
-
* @param _installCount
|
|
109
|
+
* @param repoUrl Optional repository URL to install the adapter from
|
|
110
|
+
* @param _installCount Internal recursion counter limiting the number of dependency installs
|
|
99
111
|
*/
|
|
100
112
|
installAdapter(adapter: string, repoUrl?: string, _installCount?: number): Promise<string | void>;
|
|
113
|
+
/**
|
|
114
|
+
* Install the OS packages required by an adapter
|
|
115
|
+
*
|
|
116
|
+
* @param osDependencies The OS dependencies declared by the adapter, keyed by platform
|
|
117
|
+
*/
|
|
101
118
|
installOSPackages(osDependencies: NonNullable<ioBroker.AdapterCommon['osDependencies']>): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Run the custom install script of an adapter if it defines one
|
|
121
|
+
*
|
|
122
|
+
* @param adapter The adapter name
|
|
123
|
+
* @param config The adapter object containing the install configuration
|
|
124
|
+
*/
|
|
102
125
|
callInstallOfAdapter(adapter: string, config: ioBroker.AdapterObject): Promise<string | void>;
|
|
103
126
|
/**
|
|
104
127
|
* Create adapter instance
|
|
@@ -110,18 +133,18 @@ export declare class Install {
|
|
|
110
133
|
/**
|
|
111
134
|
* Enumerate all instances of an adapter
|
|
112
135
|
*
|
|
113
|
-
* @param knownObjIDs
|
|
114
|
-
* @param notDeleted
|
|
115
|
-
* @param adapter
|
|
116
|
-
* @param instance
|
|
136
|
+
* @param knownObjIDs Accumulator of object IDs found so far
|
|
137
|
+
* @param notDeleted Accumulator of object IDs that must not be deleted
|
|
138
|
+
* @param adapter The adapter name
|
|
139
|
+
* @param instance Optional instance number to restrict the search to
|
|
117
140
|
*/
|
|
118
141
|
private _enumerateAdapterInstances;
|
|
119
142
|
/**
|
|
120
143
|
* Enumerate all meta objects of an adapter
|
|
121
144
|
*
|
|
122
|
-
* @param knownObjIDs
|
|
123
|
-
* @param adapter
|
|
124
|
-
* @param metaFilesToDelete
|
|
145
|
+
* @param knownObjIDs Accumulator of object IDs found so far
|
|
146
|
+
* @param adapter The adapter name
|
|
147
|
+
* @param metaFilesToDelete Accumulator of meta files that should be deleted
|
|
125
148
|
*/
|
|
126
149
|
_enumerateAdapterMeta(knownObjIDs: string[], adapter: string, metaFilesToDelete: string[]): Promise<void>;
|
|
127
150
|
private _enumerateAdapters;
|
|
@@ -160,16 +183,16 @@ export declare class Install {
|
|
|
160
183
|
/**
|
|
161
184
|
* Enumerate all state IDs of an adapter (or instance)
|
|
162
185
|
*
|
|
163
|
-
* @param knownStateIDs
|
|
164
|
-
* @param adapter
|
|
165
|
-
* @param instance
|
|
186
|
+
* @param knownStateIDs Accumulator of state IDs found so far
|
|
187
|
+
* @param adapter The adapter name
|
|
188
|
+
* @param instance Optional instance number to restrict the search to
|
|
166
189
|
*/
|
|
167
190
|
_enumerateAdapterStates(knownStateIDs: string[], adapter: string, instance?: number): Promise<void>;
|
|
168
191
|
/**
|
|
169
192
|
* delete WWW pages, objects and meta files
|
|
170
193
|
*
|
|
171
|
-
* @param adapter
|
|
172
|
-
* @param metaFilesToDelete
|
|
194
|
+
* @param adapter The adapter name
|
|
195
|
+
* @param metaFilesToDelete The meta files that should be deleted
|
|
173
196
|
*/
|
|
174
197
|
private _deleteAdapterFiles;
|
|
175
198
|
private _deleteAdapterStates;
|
|
@@ -58,6 +58,9 @@ class Install {
|
|
|
58
58
|
tarballRegex;
|
|
59
59
|
upload;
|
|
60
60
|
packetManager;
|
|
61
|
+
/**
|
|
62
|
+
* @param options The states/objects clients, CLI parameters and the process-exit callback
|
|
63
|
+
*/
|
|
61
64
|
constructor(options) {
|
|
62
65
|
this.isRootOnUnix = typeof process.getuid === "function" && process.getuid() === 0;
|
|
63
66
|
options = options || {};
|
|
@@ -445,8 +448,8 @@ class Install {
|
|
|
445
448
|
* Installs given adapter
|
|
446
449
|
*
|
|
447
450
|
* @param adapter The adapter name
|
|
448
|
-
* @param repoUrl
|
|
449
|
-
* @param _installCount
|
|
451
|
+
* @param repoUrl Optional repository URL to install the adapter from
|
|
452
|
+
* @param _installCount Internal recursion counter limiting the number of dependency installs
|
|
450
453
|
*/
|
|
451
454
|
async installAdapter(adapter, repoUrl, _installCount) {
|
|
452
455
|
_installCount = _installCount || 0;
|
|
@@ -506,6 +509,11 @@ class Install {
|
|
|
506
509
|
await this.upload.upgradeAdapterObjects(adapter);
|
|
507
510
|
return adapter;
|
|
508
511
|
}
|
|
512
|
+
/**
|
|
513
|
+
* Install the OS packages required by an adapter
|
|
514
|
+
*
|
|
515
|
+
* @param osDependencies The OS dependencies declared by the adapter, keyed by platform
|
|
516
|
+
*/
|
|
509
517
|
async installOSPackages(osDependencies) {
|
|
510
518
|
if (osPlatform in osDependencies) {
|
|
511
519
|
try {
|
|
@@ -517,6 +525,12 @@ class Install {
|
|
|
517
525
|
}
|
|
518
526
|
}
|
|
519
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Run the custom install script of an adapter if it defines one
|
|
530
|
+
*
|
|
531
|
+
* @param adapter The adapter name
|
|
532
|
+
* @param config The adapter object containing the install configuration
|
|
533
|
+
*/
|
|
520
534
|
async callInstallOfAdapter(adapter, config) {
|
|
521
535
|
if (config.common.install) {
|
|
522
536
|
let cmd = "node ";
|
|
@@ -740,10 +754,10 @@ class Install {
|
|
|
740
754
|
/**
|
|
741
755
|
* Enumerate all instances of an adapter
|
|
742
756
|
*
|
|
743
|
-
* @param knownObjIDs
|
|
744
|
-
* @param notDeleted
|
|
745
|
-
* @param adapter
|
|
746
|
-
* @param instance
|
|
757
|
+
* @param knownObjIDs Accumulator of object IDs found so far
|
|
758
|
+
* @param notDeleted Accumulator of object IDs that must not be deleted
|
|
759
|
+
* @param adapter The adapter name
|
|
760
|
+
* @param instance Optional instance number to restrict the search to
|
|
747
761
|
*/
|
|
748
762
|
async _enumerateAdapterInstances(knownObjIDs, notDeleted, adapter, instance) {
|
|
749
763
|
if (!notDeleted) {
|
|
@@ -775,9 +789,9 @@ class Install {
|
|
|
775
789
|
/**
|
|
776
790
|
* Enumerate all meta objects of an adapter
|
|
777
791
|
*
|
|
778
|
-
* @param knownObjIDs
|
|
779
|
-
* @param adapter
|
|
780
|
-
* @param metaFilesToDelete
|
|
792
|
+
* @param knownObjIDs Accumulator of object IDs found so far
|
|
793
|
+
* @param adapter The adapter name
|
|
794
|
+
* @param metaFilesToDelete Accumulator of meta files that should be deleted
|
|
781
795
|
*/
|
|
782
796
|
async _enumerateAdapterMeta(knownObjIDs, adapter, metaFilesToDelete) {
|
|
783
797
|
try {
|
|
@@ -934,9 +948,9 @@ class Install {
|
|
|
934
948
|
/**
|
|
935
949
|
* Enumerate all state IDs of an adapter (or instance)
|
|
936
950
|
*
|
|
937
|
-
* @param knownStateIDs
|
|
938
|
-
* @param adapter
|
|
939
|
-
* @param instance
|
|
951
|
+
* @param knownStateIDs Accumulator of state IDs found so far
|
|
952
|
+
* @param adapter The adapter name
|
|
953
|
+
* @param instance Optional instance number to restrict the search to
|
|
940
954
|
*/
|
|
941
955
|
async _enumerateAdapterStates(knownStateIDs, adapter, instance) {
|
|
942
956
|
for (const pattern of [
|
|
@@ -963,8 +977,8 @@ class Install {
|
|
|
963
977
|
/**
|
|
964
978
|
* delete WWW pages, objects and meta files
|
|
965
979
|
*
|
|
966
|
-
* @param adapter
|
|
967
|
-
* @param metaFilesToDelete
|
|
980
|
+
* @param adapter The adapter name
|
|
981
|
+
* @param metaFilesToDelete The meta files that should be deleted
|
|
968
982
|
*/
|
|
969
983
|
async _deleteAdapterFiles(adapter, metaFilesToDelete) {
|
|
970
984
|
const filesToDelete = [
|