Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2037b91

Browse files
committed
fix(@angular/cli): improve bun lockfile detection and optimize lockfile checks
This commit refactors the package manager lockfile detection logic to: - Introduce a `LOCKFILE_NAMES` constant for better maintainability and clarity. - Enhance Bun lockfile detection by checking for both `bun.lockb` and `bun.lock`. - Optimize lockfile checks by reading the root directory files once and passing them to the `hasLockfile` method, reducing redundant file system operations. This addresses issues where Bun lockfiles might not have been correctly identified. closes #31128
1 parent b366c56 commit 2037b91

File tree

1 file changed

+35
-24
lines changed

1 file changed

+35
-24
lines changed

packages/angular/cli/src/utilities/package-manager.ts

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,23 @@
88

99
import { isJsonObject, json } from '@angular-devkit/core';
1010
import { execSync, spawn } from 'node:child_process';
11-
import { existsSync, promises as fs, realpathSync, rmSync } from 'node:fs';
11+
import { promises as fs, readdirSync, realpathSync, rmSync } from 'node:fs';
1212
import { tmpdir } from 'node:os';
1313
import { join } from 'node:path';
1414
import { PackageManager } from '../../lib/config/workspace-schema';
1515
import { AngularWorkspace, getProjectByCwd } from './config';
1616
import { memoize } from './memoize';
1717

18+
/**
19+
* A map of package managers to their corresponding lockfile names.
20+
*/
21+
const LOCKFILE_NAMES: Readonly<Record<PackageManager, string | readonly string[]>> = {
22+
[PackageManager.Yarn]: 'yarn.lock',
23+
[PackageManager.Pnpm]: 'pnpm-lock.yaml',
24+
[PackageManager.Bun]: ['bun.lockb', 'bun.lock'],
25+
[PackageManager.Npm]: 'package-lock.json',
26+
};
27+
1828
interface PackageManagerOptions {
1929
saveDev: string;
2030
install: string;
@@ -29,7 +39,13 @@ export interface PackageManagerUtilsContext {
2939
root: string;
3040
}
3141

42+
/**
43+
* Utilities for interacting with various package managers.
44+
*/
3245
export class PackageManagerUtils {
46+
/**
47+
* @param context The context for the package manager utilities, including workspace and global configuration.
48+
*/
3349
constructor(private readonly context: PackageManagerUtilsContext) {}
3450

3551
/** Get the package manager name. */
@@ -216,10 +232,12 @@ export class PackageManagerUtils {
216232
return packageManager;
217233
}
218234

219-
const hasNpmLock = this.hasLockfile(PackageManager.Npm);
220-
const hasYarnLock = this.hasLockfile(PackageManager.Yarn);
221-
const hasPnpmLock = this.hasLockfile(PackageManager.Pnpm);
222-
const hasBunLock = this.hasLockfile(PackageManager.Bun);
235+
const filesInRoot = readdirSync(this.context.root);
236+
237+
const hasNpmLock = this.hasLockfile(PackageManager.Npm, filesInRoot);
238+
const hasYarnLock = this.hasLockfile(PackageManager.Yarn, filesInRoot);
239+
const hasPnpmLock = this.hasLockfile(PackageManager.Pnpm, filesInRoot);
240+
const hasBunLock = this.hasLockfile(PackageManager.Bun, filesInRoot);
223241

224242
// PERF NOTE: `this.getVersion` spawns the package a the child_process which can take around ~300ms at times.
225243
// Therefore, we should only call this method when needed. IE: don't call `this.getVersion(PackageManager.Pnpm)` unless truly needed.
@@ -265,25 +283,18 @@ export class PackageManagerUtils {
265283
return PackageManager.Npm;
266284
}
267285

268-
private hasLockfile(packageManager: PackageManager): boolean {
269-
let lockfileName: string;
270-
switch (packageManager) {
271-
case PackageManager.Yarn:
272-
lockfileName = 'yarn.lock';
273-
break;
274-
case PackageManager.Pnpm:
275-
lockfileName = 'pnpm-lock.yaml';
276-
break;
277-
case PackageManager.Bun:
278-
lockfileName = 'bun.lockb';
279-
break;
280-
case PackageManager.Npm:
281-
default:
282-
lockfileName = 'package-lock.json';
283-
break;
284-
}
285-
286-
return existsSync(join(this.context.root, lockfileName));
286+
/**
287+
* Checks if a lockfile for a specific package manager exists in the root directory.
288+
* @param packageManager The package manager to check for.
289+
* @param filesInRoot An array of file names in the root directory.
290+
* @returns True if the lockfile exists, false otherwise.
291+
*/
292+
private hasLockfile(packageManager: PackageManager, filesInRoot: string[]): boolean {
293+
const lockfiles = LOCKFILE_NAMES[packageManager];
294+
295+
return typeof lockfiles === 'string'
296+
? filesInRoot.includes(lockfiles)
297+
: lockfiles.some((lockfile) => filesInRoot.includes(lockfile));
287298
}
288299

289300
private getConfiguredPackageManager(): PackageManager | undefined {

0 commit comments

Comments
 (0)