88
99import { isJsonObject , json } from '@angular-devkit/core' ;
1010import { 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' ;
1212import { tmpdir } from 'node:os' ;
1313import { join } from 'node:path' ;
1414import { PackageManager } from '../../lib/config/workspace-schema' ;
1515import { AngularWorkspace , getProjectByCwd } from './config' ;
1616import { 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+
1828interface 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+ */
3245export 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