diff --git a/packages/cli/src/services/__tests__/util.spec.ts b/packages/cli/src/services/__tests__/util.spec.ts index ee7945915..a814f3c23 100644 --- a/packages/cli/src/services/__tests__/util.spec.ts +++ b/packages/cli/src/services/__tests__/util.spec.ts @@ -35,7 +35,7 @@ describe('util', () => { const basePath = path.resolve('/project') const makePm = (name: string): PackageManager => ({ name, - representativeLockfile: undefined, + representativeLockfiles: [], representativeConfigFile: undefined, installCommand: () => ({ executable: name, args: ['install'], unsafeDisplayCommand: `${name} install` }), execCommand: (args: string[]) => ({ executable: name, args, unsafeDisplayCommand: `${name} ${args.join(' ')}` }), diff --git a/packages/cli/src/services/check-parser/package-files/package-manager.ts b/packages/cli/src/services/check-parser/package-files/package-manager.ts index 8b36e89fa..67b7df4fa 100644 --- a/packages/cli/src/services/check-parser/package-files/package-manager.ts +++ b/packages/cli/src/services/check-parser/package-files/package-manager.ts @@ -29,7 +29,7 @@ export interface AddCommandOptions { export interface PackageManager { get name (): string - get representativeLockfile (): string | undefined + get representativeLockfiles (): string[] get representativeConfigFile (): string | undefined installCommand (): Runnable addCommand (options: AddCommandOptions): Runnable @@ -44,9 +44,20 @@ export abstract class PackageManagerDetector { abstract get name (): string abstract detectUserAgent (userAgent: string): boolean abstract detectRuntime (): boolean - abstract get representativeLockfile (): string | undefined + abstract get representativeLockfiles (): string[] abstract get representativeConfigFile (): string | undefined - abstract detectLockfile (dir: string): Promise + + async detectLockfile (dir: string): Promise { + for (const lockfile of this.representativeLockfiles) { + try { + return await accessR(path.join(dir, lockfile)) + } catch { + continue + } + } + throw new NotDetectedError() + } + abstract detectConfigFile (dir: string): Promise abstract detectExecutable (lookup: PathLookup): Promise abstract installCommand (): Runnable @@ -71,18 +82,14 @@ export class NpmDetector extends PackageManagerDetector implements PackageManage return false } - get representativeLockfile (): string { - return 'package-lock.json' + get representativeLockfiles (): string[] { + return ['package-lock.json'] } get representativeConfigFile (): undefined { return } - async detectLockfile (dir: string): Promise { - return await accessR(path.join(dir, this.representativeLockfile)) - } - // eslint-disable-next-line require-await, @typescript-eslint/no-unused-vars async detectConfigFile (dir: string): Promise { throw new NotDetectedError() @@ -126,19 +133,14 @@ export class CNpmDetector extends PackageManagerDetector implements PackageManag return false } - get representativeLockfile (): undefined { - return + get representativeLockfiles (): string[] { + return [] } get representativeConfigFile (): undefined { return } - // eslint-disable-next-line require-await - async detectLockfile (): Promise { - throw new NotDetectedError() - } - // eslint-disable-next-line require-await, @typescript-eslint/no-unused-vars async detectConfigFile (dir: string): Promise { throw new NotDetectedError() @@ -182,18 +184,14 @@ export class PNpmDetector extends PackageManagerDetector implements PackageManag return false } - get representativeLockfile (): string { - return 'pnpm-lock.yaml' + get representativeLockfiles (): string[] { + return ['pnpm-lock.yaml'] } get representativeConfigFile (): string { return 'pnpm-workspace.yaml' } - async detectLockfile (dir: string): Promise { - return await accessR(path.join(dir, this.representativeLockfile)) - } - async detectConfigFile (dir: string): Promise { return await accessR(path.join(dir, this.representativeConfigFile)) } @@ -307,18 +305,14 @@ export class YarnDetector extends PackageManagerDetector implements PackageManag return false } - get representativeLockfile (): string { - return 'yarn.lock' + get representativeLockfiles (): string[] { + return ['yarn.lock'] } get representativeConfigFile (): undefined { return } - async detectLockfile (dir: string): Promise { - return await accessR(path.join(dir, this.representativeLockfile)) - } - // eslint-disable-next-line require-await, @typescript-eslint/no-unused-vars async detectConfigFile (dir: string): Promise { throw new NotDetectedError() @@ -362,18 +356,14 @@ export class DenoDetector extends PackageManagerDetector implements PackageManag return process.versions.deno !== undefined } - get representativeLockfile (): string { - return 'deno.lock' + get representativeLockfiles (): string[] { + return ['deno.lock'] } get representativeConfigFile (): string { return 'deno.json' } - async detectLockfile (dir: string): Promise { - return await accessR(path.join(dir, this.representativeLockfile)) - } - async detectConfigFile (dir: string): Promise { return await accessR(path.join(dir, this.representativeConfigFile)) } @@ -460,18 +450,14 @@ export class BunDetector extends PackageManagerDetector implements PackageManage return process.versions.bun !== undefined } - get representativeLockfile (): string { - return 'bun.lockb' + get representativeLockfiles (): string[] { + return ['bun.lock', 'bun.lockb'] } get representativeConfigFile (): undefined { return } - async detectLockfile (dir: string): Promise { - return await accessR(path.join(dir, this.representativeLockfile)) - } - // eslint-disable-next-line require-await, @typescript-eslint/no-unused-vars async detectConfigFile (dir: string): Promise { throw new NotDetectedError() @@ -731,9 +717,7 @@ export async function detectNearestLockfile ( } } - const lockfiles = detectors.reduce((acc, detector) => { - return acc.concat(detector.representativeLockfile ?? []) - }, []) + const lockfiles = detectors.flatMap(detector => detector.representativeLockfiles) throw new NoLockfileFoundError(searchPaths, lockfiles) } diff --git a/packages/cli/src/testing/fixture-sandbox.ts b/packages/cli/src/testing/fixture-sandbox.ts index db87d55ab..6c4a0d812 100644 --- a/packages/cli/src/testing/fixture-sandbox.ts +++ b/packages/cli/src/testing/fixture-sandbox.ts @@ -6,7 +6,7 @@ import Debug from 'debug' const debug = Debug('checkly:cli:testing:fixture-sandbox') -import { detectNearestPackageJson, detectPackageManager, PackageManager } from '../services/check-parser/package-files/package-manager' +import { detectNearestLockfile, detectNearestPackageJson, detectPackageManager, PackageManager } from '../services/check-parser/package-files/package-manager' export interface CreateFixtureSandboxOptions { /** @@ -113,7 +113,10 @@ export class FixtureSandbox { if (installPackages && injectPackedSelf) { debug('Injecting containing package') - const lockfile = packageManager.representativeLockfile + const { lockfile } = await detectNearestLockfile(root, { + detectors: [packageManager.detector()], + root, + }) // Take a backup of the original package.json so that we can restore // it later. @@ -123,12 +126,7 @@ export class FixtureSandbox { ) // Same for the lockfile. - if (lockfile) { - await fs.cp( - path.join(root, lockfile), - path.join(root, `${lockfile}.backup`), - ) - } + await fs.cp(lockfile, `${lockfile}.backup`) const packageJson = await detectNearestPackageJson(__dirname) @@ -153,12 +151,7 @@ export class FixtureSandbox { ) // Restore original lockfile. - if (lockfile) { - await fs.rename( - path.join(root, `${lockfile}.backup`), - path.join(root, lockfile), - ) - } + await fs.rename(`${lockfile}.backup`, lockfile) } return new FixtureSandbox({