UNPKG

@electron-forge/cli

Version:

A complete tool for building modern Electron applications

143 lines • 10.9 kB
import { exec } from 'node:child_process'; import os from 'node:os'; import path from 'node:path'; import { PACKAGE_MANAGERS, pathExists, resolvePackageManager, spawnPackageManager, } from '@electron-forge/core-utils'; import debug from 'debug'; import semver from 'semver'; const d = debug('electron-forge:check-system'); async function getGitVersion() { return new Promise((resolve) => { exec('git --version', (err, output) => err ? resolve(null) : resolve(output.toString().trim().split(' ').reverse()[0])); }); } /** * Packaging an app with Electron Forge requires `node_modules` to be on disk. * With `pnpm`, this can be done in a few different ways. * * `node-linker=hoisted` replicates the behaviour of npm and Yarn Classic, while * users may choose to set `public-hoist-pattern` or `hoist-pattern` for advanced * configuration purposes. */ async function checkPnpmConfig() { const { pnpm } = PACKAGE_MANAGERS; const hoistPattern = await spawnPackageManager(pnpm, [ 'config', 'get', 'hoist-pattern', ]); const publicHoistPattern = await spawnPackageManager(pnpm, [ 'config', 'get', 'public-hoist-pattern', ]); if (hoistPattern !== 'undefined' || publicHoistPattern !== 'undefined') { d(`Custom hoist pattern detected ${JSON.stringify({ hoistPattern, publicHoistPattern, })}, assuming that the user has configured pnpm to package dependencies.`); return; } const nodeLinker = await spawnPackageManager(pnpm, [ 'config', 'get', 'node-linker', ]); if (nodeLinker !== 'hoisted') { throw new Error('When using pnpm, `node-linker` must be set to "hoisted" (or a custom `hoist-pattern` or `public-hoist-pattern` must be defined). Run `pnpm config set node-linker hoisted` to set this config value, or add it to your project\'s `.npmrc` file.'); } } async function checkYarnConfig() { const { yarn } = PACKAGE_MANAGERS; const yarnVersion = await spawnPackageManager(yarn, ['--version']); const nodeLinker = await spawnPackageManager(yarn, [ 'config', 'get', 'nodeLinker', ]); if (yarnVersion && semver.gte(yarnVersion, '2.0.0') && nodeLinker !== 'node-modules') { throw new Error('When using Yarn 2+, `nodeLinker` must be set to "node-modules". Run `yarn config set nodeLinker node-modules` to set this config value, or add it to your project\'s `.yarnrc.yml` file.'); } } const ALLOWLISTED_VERSIONS = { npm: { all: '>= 10.9.0', }, yarn: { all: '>= 1.0.0', }, pnpm: { all: '>= 8.0.0', }, }; export async function checkPackageManager() { const pm = await resolvePackageManager(); const version = pm.version ?? (await spawnPackageManager(pm, ['--version'])); const versionString = version.toString().trim(); const range = ALLOWLISTED_VERSIONS[pm.executable][process.platform] ?? ALLOWLISTED_VERSIONS[pm.executable].all; if (!semver.valid(version)) { d(`Invalid semver-string while checking version: ${version}`); throw new Error(`Could not check ${pm.executable} version "${version}", assuming incompatible`); } if (!semver.satisfies(version, range, { includePrerelease: true })) { throw new Error(`Incompatible version of ${pm.executable} detected: "${version}" must be in range ${range}`); } if (pm.executable === 'pnpm') { await checkPnpmConfig(); } else if (pm.executable === 'yarn') { await checkYarnConfig(); } return `${pm.executable}@${versionString}`; } /** * Some people know their system is OK and don't appreciate the 800ms lag in * start up that these checks (in particular the package manager check) costs. * * Simply creating this flag file in your home directory will skip these checks * and shave ~800ms off your forge start time. * * This is specifically not documented or everyone would make it. */ const SKIP_SYSTEM_CHECK = path.resolve(os.homedir(), '.skip-forge-system-check'); export async function checkSystem(callerTask) { if (!(await pathExists(SKIP_SYSTEM_CHECK))) { d('checking system, create ~/.skip-forge-system-check to stop doing this'); return callerTask.newListr([ { title: 'Checking git exists', // We only call the `initGit` helper in the `init` and `import` commands enabled: (ctx) => (ctx.command === 'init' || ctx.command === 'import') && ctx.git, task: async (_, task) => { const gitVersion = await getGitVersion(); if (gitVersion) { task.title = `Found git@${gitVersion}`; } else { throw new Error('Could not find git in environment'); } }, }, { title: 'Checking package manager version', task: async (_, task) => { const packageManager = await checkPackageManager(); task.title = `Found ${packageManager}`; }, }, ], { concurrent: true, exitOnError: true, rendererOptions: { collapseSubtasks: true, }, }); } d('skipping system check'); return true; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2stc3lzdGVtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWwvY2hlY2stc3lzdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBRTdCLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsVUFBVSxFQUNWLHFCQUFxQixFQUNyQixtQkFBbUIsR0FFcEIsTUFBTSw0QkFBNEIsQ0FBQztBQUVwQyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRTVCLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBRS9DLEtBQUssVUFBVSxhQUFhO0lBQzFCLE9BQU8sSUFBSSxPQUFPLENBQWdCLENBQUMsT0FBTyxFQUFFLEVBQUU7UUFDNUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUNwQyxHQUFHO1lBQ0QsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDZixDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDOUQsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxLQUFLLFVBQVUsZUFBZTtJQUM1QixNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsZ0JBQWdCLENBQUM7SUFDbEMsTUFBTSxZQUFZLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxJQUFJLEVBQUU7UUFDbkQsUUFBUTtRQUNSLEtBQUs7UUFDTCxlQUFlO0tBQ2hCLENBQUMsQ0FBQztJQUNILE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxJQUFJLEVBQUU7UUFDekQsUUFBUTtRQUNSLEtBQUs7UUFDTCxzQkFBc0I7S0FDdkIsQ0FBQyxDQUFDO0lBRUgsSUFBSSxZQUFZLEtBQUssV0FBVyxJQUFJLGtCQUFrQixLQUFLLFdBQVcsRUFBRSxDQUFDO1FBQ3ZFLENBQUMsQ0FDQyxpQ0FBaUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUM5QyxZQUFZO1lBQ1osa0JBQWtCO1NBQ25CLENBQUMsdUVBQXVFLENBQzFFLENBQUM7UUFDRixPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sVUFBVSxHQUFHLE1BQU0sbUJBQW1CLENBQUMsSUFBSSxFQUFFO1FBQ2pELFFBQVE7UUFDUixLQUFLO1FBQ0wsYUFBYTtLQUNkLENBQUMsQ0FBQztJQUNILElBQUksVUFBVSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzdCLE1BQU0sSUFBSSxLQUFLLENBQ2Isa1BBQWtQLENBQ25QLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxlQUFlO0lBQzVCLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQztJQUNsQyxNQUFNLFdBQVcsR0FBRyxNQUFNLG1CQUFtQixDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDbkUsTUFBTSxVQUFVLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxJQUFJLEVBQUU7UUFDakQsUUFBUTtRQUNSLEtBQUs7UUFDTCxZQUFZO0tBQ2IsQ0FBQyxDQUFDO0lBQ0gsSUFDRSxXQUFXO1FBQ1gsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDO1FBQ2hDLFVBQVUsS0FBSyxjQUFjLEVBQzdCLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLDBMQUEwTCxDQUMzTCxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFRCxNQUFNLG9CQUFvQixHQUd0QjtJQUNGLEdBQUcsRUFBRTtRQUNILEdBQUcsRUFBRSxXQUFXO0tBQ2pCO0lBQ0QsSUFBSSxFQUFFO1FBQ0osR0FBRyxFQUFFLFVBQVU7S0FDaEI7SUFDRCxJQUFJLEVBQUU7UUFDSixHQUFHLEVBQUUsVUFBVTtLQUNoQjtDQUNGLENBQUM7QUFFRixNQUFNLENBQUMsS0FBSyxVQUFVLG1CQUFtQjtJQUN2QyxNQUFNLEVBQUUsR0FBRyxNQUFNLHFCQUFxQixFQUFFLENBQUM7SUFDekMsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLE9BQU8sSUFBSSxDQUFDLE1BQU0sbUJBQW1CLENBQUMsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdFLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUVoRCxNQUFNLEtBQUssR0FDVCxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNyRCxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDO0lBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDM0IsQ0FBQyxDQUFDLGlEQUFpRCxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzlELE1BQU0sSUFBSSxLQUFLLENBQ2IsbUJBQW1CLEVBQUUsQ0FBQyxVQUFVLGFBQWEsT0FBTywwQkFBMEIsQ0FDL0UsQ0FBQztJQUNKLENBQUM7SUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ25FLE1BQU0sSUFBSSxLQUFLLENBQ2IsMkJBQTJCLEVBQUUsQ0FBQyxVQUFVLGVBQWUsT0FBTyxzQkFBc0IsS0FBSyxFQUFFLENBQzVGLENBQUM7SUFDSixDQUFDO0lBRUQsSUFBSSxFQUFFLENBQUMsVUFBVSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQzdCLE1BQU0sZUFBZSxFQUFFLENBQUM7SUFDMUIsQ0FBQztTQUFNLElBQUksRUFBRSxDQUFDLFVBQVUsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUNwQyxNQUFNLGVBQWUsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxPQUFPLEdBQUcsRUFBRSxDQUFDLFVBQVUsSUFBSSxhQUFhLEVBQUUsQ0FBQztBQUM3QyxDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQ3BDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFDWiwwQkFBMEIsQ0FDM0IsQ0FBQztBQVNGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUMvQixVQUE4QztJQUU5QyxJQUFJLENBQUMsQ0FBQyxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMzQyxDQUFDLENBQUMsdUVBQXVFLENBQUMsQ0FBQztRQUMzRSxPQUFPLFVBQVUsQ0FBQyxRQUFRLENBQ3hCO1lBQ0U7Z0JBQ0UsS0FBSyxFQUFFLHFCQUFxQjtnQkFDNUIsd0VBQXdFO2dCQUN4RSxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQVcsRUFBRSxDQUN4QixDQUFDLEdBQUcsQ0FBQyxPQUFPLEtBQUssTUFBTSxJQUFJLEdBQUcsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLElBQUksR0FBRyxDQUFDLEdBQUc7Z0JBQ2pFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFO29CQUN0QixNQUFNLFVBQVUsR0FBRyxNQUFNLGFBQWEsRUFBRSxDQUFDO29CQUN6QyxJQUFJLFVBQVUsRUFBRSxDQUFDO3dCQUNmLElBQUksQ0FBQyxLQUFLLEdBQUcsYUFBYSxVQUFVLEVBQUUsQ0FBQztvQkFDekMsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztvQkFDdkQsQ0FBQztnQkFDSCxDQUFDO2FBQ0Y7WUFDRDtnQkFDRSxLQUFLLEVBQUUsa0NBQWtDO2dCQUN6QyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRTtvQkFDdEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxtQkFBbUIsRUFBRSxDQUFDO29CQUNuRCxJQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsY0FBYyxFQUFFLENBQUM7Z0JBQ3pDLENBQUM7YUFDRjtTQUNGLEVBQ0Q7WUFDRSxVQUFVLEVBQUUsSUFBSTtZQUNoQixXQUFXLEVBQUUsSUFBSTtZQUNqQixlQUFlLEVBQUU7Z0JBQ2YsZ0JBQWdCLEVBQUUsSUFBSTthQUN2QjtTQUNGLENBQ0YsQ0FBQztJQUNKLENBQUM7SUFDRCxDQUFDLENBQUMsdUJBQXVCLENBQUMsQ0FBQztJQUMzQixPQUFPLElBQUksQ0FBQztBQUNkLENBQUMifQ==