diff --git a/lib/install.mjs b/lib/install.mjs index 1037ba9..ce20063 100755 --- a/lib/install.mjs +++ b/lib/install.mjs @@ -1,4 +1,5 @@ -import { createWriteStream, existsSync, rmSync, renameSync } from 'node:fs'; +import { createWriteStream, existsSync} from 'node:fs'; +import { rename, rm } from 'node:fs/promises'; import { get } from 'node:https'; import { dirname, resolve } from 'node:path'; import { arch, env, platform, exit } from 'node:process'; @@ -8,7 +9,7 @@ import compressing from 'compressing'; import progress from 'cli-progress'; import semver from 'semver'; -import nodeManifest from "../package.json" assert { type: 'json' }; +import nodeManifest from '../package.json' assert { type: 'json' }; /** * NW.js build flavor @@ -17,8 +18,16 @@ import nodeManifest from "../package.json" assert { type: 'json' }; */ let buildType = env.npm_config_nwjs_build_type || env.NWJS_BUILD_TYPE || 'normal'; -// Parse Node manifest version. +/** + * Parsed string version to Semver version object + */ let parsedVersion = semver.parse(nodeManifest.version); + +/** + * Version string of the format `X.Y.Z-pre`. + * The prerelease segment `pre` is used to specify build flavor, or other tags. + * @type {string} + */ let versionString = [ parsedVersion.major, parsedVersion.minor, @@ -31,10 +40,10 @@ if (typeof parsedVersion?.prerelease?.[0] === 'string') { if (prerelease.length > 1) { prerelease = prerelease.slice(0, -1); } - versionString = [ versionString, prerelease ].join('-'); + versionString = [versionString, prerelease].join('-'); } -// Check build flavor +// Check build flavor and slice that off the `versionString`. if (versionString.slice(-4) === '-sdk') { versionString = versionString.slice(0, -4); buildType = 'sdk'; @@ -43,39 +52,85 @@ if (versionString.slice(-4) === '-sdk') { buildType = 'sdk'; } +/** + * URL to download or get binaries. + */ let url = ''; -let hostArch = env.npm_config_nwjs_process_arch || arch; -let urlBase = env.npm_config_nwjs_urlbase || env.NWJS_URLBASE || 'https://dl.nwjs.io/v'; -let buildTypeSuffix = buildType === 'normal' ? '' : `-${buildType}`; + +/** + * Host operating system + * + * @type {NodeJS.Platform | 'osx' | 'win'} + */ let hostOs = env.npm_config_nwjs_platform || env.NWJS_PLATFORM || platform; -// Determine download url -switch (hostOs) { - case 'win32': - url = `${urlBase}${versionString}/nwjs${buildTypeSuffix}-v${versionString}-win-${hostArch}.zip`; - break; - case 'darwin': - url = `${urlBase}${versionString}/nwjs${buildTypeSuffix}-v${versionString}-osx-${hostArch}.zip`; - break; - case 'linux': - url = `${urlBase}${versionString}/nwjs${buildTypeSuffix}-v${versionString}-linux-${hostArch}.tar.gz`; - break; -} +/** + * Host architecture + * + * @type {NodeJS.Architecture} + */ +let hostArch = env.npm_config_nwjs_process_arch || arch; + +/** + * URL base prepended to `url`. + * @type {string} + */ +let urlBase = env.npm_config_nwjs_urlbase || env.NWJS_URLBASE || 'https://dl.nwjs.io/v'; -if (url === '') { - console.error('[ERROR] Could not find a compatible version of nw.js to download for your platform.'); +const PLATFORM_KV = { + darwin: 'osx', + linux: 'linux', + win32: 'win', +}; + +const ARCH_KV = { + x64: 'x64', + ia32: 'ia32', + arm64: 'arm64', +}; + +url = [ + urlBase, + versionString, + '/nwjs', + buildType === 'normal' ? '' : `-${buildType}`, + '-v', + versionString, + '-', + PLATFORM_KV[hostOs], + '-', + ARCH_KV[hostArch], + PLATFORM_KV[hostOs] === 'linux' ? '.tar.gz' : '.zip' +].join(); + +if (PLATFORM_KV[hostOs] === undefined || ARCH_KV[hostArch] === undefined) { + console.error('[ ERROR ] Could not find a compatible version of nw.js to download for your platform.'); exit(1); } const __dirname = dirname(fileURLToPath(import.meta.url)); -let dest = resolve(__dirname, '..', 'nwjs'); +/** + * The folder where NW.js binaries are placed. + * + * @type {string} + */ +let nwDir = resolve(__dirname, '..', 'nwjs'); -if (existsSync(dest) === true) { +if (existsSync(nwDir) === true) { exit(0); } let parsedUrl = new URL(url); + +/** + * Path to the compressed binary. + * + * @type {string} + */ let filePath = ''; + +// If the url is linking to the file system, +// then it is assumed that a compressed binary exists in that location. if (parsedUrl.protocol === 'file:') { filePath = resolve( decodeURIComponent( @@ -84,14 +139,36 @@ if (parsedUrl.protocol === 'file:') { ); if (existsSync(filePath) === false) { - console.error('[ERROR] Could not find ' + filePath); + console.error('[ ERROR ] Could not find ' + filePath); + } + + // If the compressed file is of ZIP format: + if (filePath.slice(-3) === '.zip') { + compressing.zip.uncompress(filePath, '.') + .then(async () => { + await rm(filePath, { + recursive: true, + force: true, + }); + await rename(`nwjs-v${versionString}-${PLATFORM_KV[hostOs]}-${ARCH_KV[hostArch]}`, 'nwjs'); + }); + // If the compressed file is of TGZ format: + } else if (filePath.slice(-7) === '.tar.gz') { + compressing.tgz.uncompress(filePath, '.') + .then(async () => { + await rm(filePath, { + recursive: true, + force: true, + }); + await rename(`nwjs-v${versionString}-${PLATFORM_KV[hostOs]}-${ARCH_KV[hostArch]}`, 'nwjs'); + }); } } else { const bar = new progress.SingleBar({}, progress.Presets.rect); - const stream = createWriteStream(dest); + const stream = createWriteStream(nwDir); get(url, (response) => { @@ -103,31 +180,31 @@ if (parsedUrl.protocol === 'file:') { bar.update(chunks); }); - response.on('error', () => { - rmSync(dest, { + response.on('error', async () => { + await rm(nwDir, { recursive: true, force: true, }); }); response.on('end', () => { - if (platform === 'linux') { - compressing.tgz.uncompress(dest, '.') - .then(() => rmSync(dest, { - recursive: true, - force: true, - })) - .then(() => { - renameSync(`nwjs-v${versionString}-${platform}-${arch}`, 'nwjs'); + if (PLATFORM_KV[hostOs] === 'linux') { + compressing.tgz.uncompress(nwDir, '.') + .then(async () => { + await rm(nwDir, { + recursive: true, + force: true, + }); + await rename(`nwjs-v${versionString}-${PLATFORM_KV[hostOs]}-${ARCH_KV[hostArch]}`, 'nwjs'); }); } else { - compressing.zip.uncompress(dest, '.') - .then(() => rmSync(dest, { - recursive: true, - force: true, - })) - .then(() => { - renameSync(`nwjs-v${versionString}-${platform}-${arch}`, 'nwjs'); + compressing.zip.uncompress(nwDir, '.') + .then(async () => { + await rm(nwDir, { + recursive: true, + force: true, + }); + await rename(`nwjs-v${versionString}-${PLATFORM_KV[hostOs]}-${ARCH_KV[hostArch]}`, 'nwjs'); }); } });