Skip to content

Commit

Permalink
refactor(core): replace yarn-or-npm with detect-package-manager (#…
Browse files Browse the repository at this point in the history
…3813)

* refactor(core): replace `yarn-or-npm` with `detect-package-manager`

* `hasYarn` is async too

* await test
  • Loading branch information
erickzhao authored Jan 21, 2025
1 parent b7788c1 commit bf75aa1
Show file tree
Hide file tree
Showing 15 changed files with 37 additions and 42 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"cross-spawn": "^7.0.3",
"cross-zip": "^4.0.0",
"debug": "^4.3.1",
"detect-package-manager": "^3.0.2",
"express": "^4.17.1",
"express-ws": "^5.0.2",
"fast-glob": "^3.2.7",
Expand Down Expand Up @@ -78,8 +79,7 @@
"which": "^2.0.2",
"xterm": "^4.9.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.8.0",
"yarn-or-npm": "^3.0.1"
"xterm-addon-search": "^0.8.0"
},
"devDependencies": {
"@electron/fuses": ">=1.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/api/cli/src/util/check-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function warnIfPackageManagerIsntAKnownGoodVersion(packageManager: string, versi
async function checkPackageManagerVersion() {
const version = await forgeUtils.yarnOrNpmSpawn(['--version']);
const versionString = version.toString().trim();
if (forgeUtils.hasYarn()) {
if (await forgeUtils.hasYarn()) {
warnIfPackageManagerIsntAKnownGoodVersion('Yarn', versionString, YARN_ALLOWLISTED_VERSIONS);
return `yarn@${versionString}`;
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/api/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@malept/cross-spawn-promise": "^2.0.0",
"chalk": "^4.0.0",
"debug": "^4.3.1",
"detect-package-manager": "^3.0.2",
"fast-glob": "^3.2.7",
"filenamify": "^4.1.0",
"find-up": "^5.0.0",
Expand All @@ -59,8 +60,7 @@
"semver": "^7.2.1",
"source-map-support": "^0.5.13",
"sudo-prompt": "^9.1.1",
"username": "^5.1.0",
"yarn-or-npm": "^3.0.1"
"username": "^5.1.0"
},
"engines": {
"node": ">= 16.4.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('installDependencies', () => {
{ pm: 'yarn', install: 'add', flags: { exact: '--exact', dev: '--dev' } },
])('$pm', ({ pm, install, flags }) => {
beforeEach(() => {
vi.mocked(hasYarn).mockReturnValue(pm === 'yarn');
vi.mocked(hasYarn).mockResolvedValue(pm === 'yarn');
});

it('should install deps', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export default autoTrace(
{
title: 'Installing dependencies',
task: async (_, task) => {
const packageManager = safeYarnOrNpm();
const packageManager = await safeYarnOrNpm();
await writeChanges();

d('deleting old dependencies forcefully');
Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/init-scripts/init-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export async function initLink<T>(dir: string, task?: ForgeListrTask<T>) {
if (shouldLink) {
d('Linking forge dependencies');
const packageJson = await readRawPackageJson(dir);
const packageManager = safeYarnOrNpm();
const packageManager = await safeYarnOrNpm();
const linkFolder = path.resolve(__dirname, '..', '..', '..', '..', '..', '..', '.links');
for (const packageName of Object.keys(packageJson.devDependencies)) {
if (packageName.startsWith('@electron-forge/')) {
Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/init-scripts/init-npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const exactDevDeps = ['electron'];

export const initNPM = async <T>(dir: string, task: ForgeListrTask<T>): Promise<void> => {
d('installing dependencies');
const packageManager = safeYarnOrNpm();
const packageManager = await safeYarnOrNpm();
task.output = `${packageManager} install ${deps.join(' ')}`;
await installDepList(dir, deps);

Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async function validateTemplate(template: string, templateModule: ForgeTemplate)
export default async ({ dir = process.cwd(), interactive = false, copyCIFiles = false, force = false, template = 'base' }: InitOptions): Promise<void> => {
d(`Initializing in: ${dir}`);

const packageManager = safeYarnOrNpm();
const packageManager = await safeYarnOrNpm();

const runner = new Listr<{
templateModule: ForgeTemplate;
Expand Down
4 changes: 2 additions & 2 deletions packages/api/core/src/util/install-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ export enum DepVersionRestriction {
}

export default async (dir: string, deps: string[], depType = DepType.PROD, versionRestriction = DepVersionRestriction.RANGE): Promise<void> => {
d('installing', JSON.stringify(deps), 'in:', dir, `depType=${depType},versionRestriction=${versionRestriction},withYarn=${hasYarn()}`);
d('installing', JSON.stringify(deps), 'in:', dir, `depType=${depType},versionRestriction=${versionRestriction},withYarn=${await hasYarn()}`);
if (deps.length === 0) {
d('nothing to install, stopping immediately');
return Promise.resolve();
}
let cmd = ['install'].concat(deps);
if (hasYarn()) {
if (await hasYarn()) {
cmd = ['add'].concat(deps);
if (depType === DepType.DEV) cmd.push('--dev');
if (versionRestriction === DepVersionRestriction.EXACT) cmd.push('--exact');
Expand Down
4 changes: 2 additions & 2 deletions packages/utils/core-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"@malept/cross-spawn-promise": "^2.0.0",
"chalk": "^4.0.0",
"debug": "^4.3.1",
"detect-package-manager": "^3.0.2",
"find-up": "^5.0.0",
"fs-extra": "^10.0.0",
"log-symbols": "^4.0.0",
"semver": "^7.2.1",
"yarn-or-npm": "^3.0.1"
"semver": "^7.2.1"
},
"engines": {
"node": ">= 16.4.0"
Expand Down
16 changes: 9 additions & 7 deletions packages/utils/core-utils/spec/yarn-or-npm.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { detect } from 'detect-package-manager';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import systemYarnOrNpm from 'yarn-or-npm';

import { safeYarnOrNpm } from '../src/yarn-or-npm';

Expand All @@ -19,24 +19,26 @@ describe('yarn-or-npm', () => {
}
});

it('should by default equal the system yarn-or-npm value', () => {
expect(safeYarnOrNpm()).toEqual(systemYarnOrNpm());
it('should by default equal the system yarn-or-npm value', async () => {
const pm = await detect();
expect(safeYarnOrNpm()).resolves.toEqual(pm);
});

it('should return yarn if NODE_INSTALLER=yarn', () => {
process.env.NODE_INSTALLER = 'yarn';
expect(safeYarnOrNpm()).toEqual('yarn');
expect(safeYarnOrNpm()).resolves.toEqual('yarn');
});

it('should return npm if NODE_INSTALLER=npm', () => {
process.env.NODE_INSTALLER = 'npm';
expect(safeYarnOrNpm()).toEqual('npm');
expect(safeYarnOrNpm()).resolves.toEqual('npm');
});

it('should return system value if NODE_INSTALLER is an unrecognized installer', () => {
it('should return system value if NODE_INSTALLER is an unrecognized installer', async () => {
process.env.NODE_INSTALLER = 'magical_unicorn';
console.warn = vi.fn();
expect(safeYarnOrNpm()).toEqual(systemYarnOrNpm());
const pm = await detect();
await expect(safeYarnOrNpm()).resolves.toEqual(pm);
expect(console.warn).toHaveBeenCalledWith('⚠', expect.stringContaining('Unknown NODE_INSTALLER'));
});
});
4 changes: 1 addition & 3 deletions packages/utils/core-utils/src/electron-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import findUp from 'find-up';
import fs from 'fs-extra';
import semver from 'semver';

import { safeYarnOrNpm } from './yarn-or-npm';

const d = debug('electron-forge:electron-version');

const electronPackageNames = ['electron-nightly', 'electron'];
Expand Down Expand Up @@ -44,7 +42,7 @@ async function determineNodeModulesPath(dir: string, packageName: string): Promi

export class PackageNotFoundError extends Error {
constructor(packageName: string, dir: string) {
super(`Cannot find the package "${packageName}". Perhaps you need to run "${safeYarnOrNpm()} install" in "${dir}"?`);
super(`Cannot find the package "${packageName}". Perhaps you need to run install it in "${dir}"?`);
}
}

Expand Down
10 changes: 5 additions & 5 deletions packages/utils/core-utils/src/yarn-or-npm.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CrossSpawnArgs, CrossSpawnOptions, spawn } from '@malept/cross-spawn-promise';
import chalk from 'chalk';
import { detect } from 'detect-package-manager';
import logSymbols from 'log-symbols';
import yarnOrNpm from 'yarn-or-npm';

export const safeYarnOrNpm = () => {
const system = yarnOrNpm();
export const safeYarnOrNpm = async () => {
const system = await detect();
switch (process.env.NODE_INSTALLER) {
case 'yarn':
case 'npm':
Expand All @@ -17,6 +17,6 @@ export const safeYarnOrNpm = () => {
}
};

export const yarnOrNpmSpawn = (args?: CrossSpawnArgs, opts?: CrossSpawnOptions): Promise<string> => spawn(safeYarnOrNpm(), args, opts);
export const yarnOrNpmSpawn = async (args?: CrossSpawnArgs, opts?: CrossSpawnOptions): Promise<string> => spawn(await safeYarnOrNpm(), args, opts);

export const hasYarn = (): boolean => safeYarnOrNpm() === 'yarn';
export const hasYarn = async () => (await safeYarnOrNpm()) === 'yarn';
4 changes: 0 additions & 4 deletions typings/yarn-or-npm/index.d.ts

This file was deleted.

17 changes: 8 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5034,7 +5034,7 @@ cross-spawn-windows-exe@^1.1.0:
is-wsl "^2.2.0"
which "^2.0.2"

cross-spawn@^6.0.0, cross-spawn@^6.0.5:
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
Expand Down Expand Up @@ -5321,6 +5321,13 @@ detect-node@^2.0.4:
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==

detect-package-manager@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/detect-package-manager/-/detect-package-manager-3.0.2.tgz#ca34261ab84198072580e93ae86582c575428da9"
integrity sha512-8JFjJHutStYrfWwzfretQoyNGoZVW1Fsrp4JO9spa7h/fBfwgTMEIy4/LBzRDGsxwVPHU0q+T9YvwLDJoOApLQ==
dependencies:
execa "^5.1.1"

dezalgo@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
Expand Down Expand Up @@ -14219,14 +14226,6 @@ yargs@^17.7.2:
y18n "^5.0.5"
yargs-parser "^21.1.1"

yarn-or-npm@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/yarn-or-npm/-/yarn-or-npm-3.0.1.tgz#6336eea4dff7e23e226acc98c1a8ada17a1b8666"
integrity sha512-fTiQP6WbDAh5QZAVdbMQkecZoahnbOjClTQhzv74WX5h2Uaidj1isf9FDes11TKtsZ0/ZVfZsqZ+O3x6aLERHQ==
dependencies:
cross-spawn "^6.0.5"
pkg-dir "^4.2.0"

yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
Expand Down

0 comments on commit bf75aa1

Please sign in to comment.