UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

90 lines 4.13 kB
import { untar } from "@andrewbranch/untar.js"; import { ZWaveError, ZWaveErrorCodes, gunzipSync } from "@zwave-js/core"; import { getErrorMessage, writeTextFile, } from "@zwave-js/shared"; import { isObject } from "alcalzone-shared/typeguards"; import path from "pathe"; import semverInc from "semver/functions/inc.js"; import semverValid from "semver/functions/valid.js"; import semverMaxSatisfying from "semver/ranges/max-satisfying.js"; /** * Checks whether there is a compatible update for the currently installed config package. * Returns the new version if there is an update, `undefined` otherwise. * Throws if the update check failed. */ export async function checkForConfigUpdates(currentVersion) { const { default: ky } = await import("ky"); let registry; try { registry = await ky .get("https://registry.npmjs.org/@zwave-js/config") .json(); } catch { throw new ZWaveError(`Could not check for config updates: Failed to download package information!`, ZWaveErrorCodes.Config_Update_RegistryError); } if (!isObject(registry) || !isObject(registry.versions)) { throw new ZWaveError(`Could not check for config updates: Downloaded package information does not contain version information!`, ZWaveErrorCodes.Config_Update_RegistryError); } // Find the highest possible prepatch update (e.g. 7.2.4 -> 7.2.5-20200424) const allVersions = Object.keys(registry.versions) .filter((v) => !!semverValid(v)) .filter((v) => /-\d{8}$/.test(v)); const updateRange = `>${currentVersion} <${semverInc(currentVersion, "patch")}`; const updateVersion = semverMaxSatisfying(allVersions, updateRange, { includePrerelease: true, }); if (updateVersion) return updateVersion; } /** * Downloads and installs the given configuration update. * This only works if an external configuation directory is used. */ export async function installConfigUpdate(fs, newVersion, external) { const { default: ky } = await import("ky"); let registryInfo; try { registryInfo = await ky .get(`https://registry.npmjs.org/@zwave-js/config/${newVersion}`) .json(); } catch { throw new ZWaveError(`Config update failed: Could not fetch package info from npm registry!`, ZWaveErrorCodes.Config_Update_InstallFailed); } const url = registryInfo?.dist?.tarball; if (typeof url !== "string") { throw new ZWaveError(`Config update failed: Could not fetch package tarball URL from npm registry!`, ZWaveErrorCodes.Config_Update_InstallFailed); } let tarballData; try { tarballData = new Uint8Array(await ky.get(url).arrayBuffer()); } catch (e) { throw new ZWaveError(`Config update failed: Could not download tarball. Reason: ${getErrorMessage(e)}`, ZWaveErrorCodes.Config_Update_InstallFailed); } try { // Extract json files from the tarball's config directory // and overwrite the external config directory with them const tarFiles = untar(gunzipSync(tarballData).buffer); await fs.deleteDir(external.configDir); await fs.ensureDir(external.configDir); const prefix = "package/config/"; for (const file of tarFiles) { if (!file.filename.startsWith(prefix) || !file.filename.endsWith(".json")) { continue; } const filename = file.filename.slice(prefix.length); const targetFileName = path.join(external.configDir, filename); const targetDirName = path.dirname(targetFileName); await fs.ensureDir(targetDirName); await fs.writeFile(targetFileName, new Uint8Array(file.fileData)); } const externalVersionFilename = path.join(external.configDir, "version"); await writeTextFile(fs, externalVersionFilename, newVersion); } catch { throw new ZWaveError(`Config update failed: Could not extract tarball`, ZWaveErrorCodes.Config_Update_InstallFailed); } } //# sourceMappingURL=UpdateConfig.js.map