diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 4a1f69a..06f5914 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -91,6 +91,12 @@ export function objectWithoutKeys(obj: T, ...keys: (keyof * Detects the package manager used in the given directory. */ export async function detectNodePackageManager(directory: string) { + const packageManager = process.env.npm_config_user_agent?.split('/')[0] + if (packageManager && ['npm', 'yarn', 'pnpm'].includes(packageManager)) { + debug.utils(`Detected running package manager: ${packageManager}`) + return packageManager + } + const packageLockFiles: Record = { 'pnpm-lock.yaml': 'pnpm', 'yarn.lock': 'yarn', diff --git a/packages/core/test/actions/install-packages.test.ts b/packages/core/test/actions/install-packages.test.ts index 052e335..7dd6361 100644 --- a/packages/core/test/actions/install-packages.test.ts +++ b/packages/core/test/actions/install-packages.test.ts @@ -62,6 +62,7 @@ it('installs the given php package as development dependencies', async() => awai it('installs the given node package with npm by default', async() => await usingSandbox({ fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = undefined const { executePreset } = await makeTestPreset({ handler: async() => await installPackages({ for: 'node', @@ -87,6 +88,91 @@ it('installs the given node package with npm by default', async() => await using targetStructure: { 'package.json': { type: 'file', content: '{}' } }, })) +it('installs the given node package with npm when npm was used to run the preset', async() => await usingSandbox({ + fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = 'npm' + const { executePreset } = await makeTestPreset({ + handler: async() => await installPackages({ + for: 'node', + packages: 'debug@4.3.3', + }), + }) + + await executePreset() + await expectStructureMatches(targetDirectory, { + 'node_modules': { type: 'directory' }, + 'node_modules/debug': { type: 'directory' }, + 'package-lock.json': { type: 'file' }, + 'package.json': { + type: 'file', + json: { + dependencies: { + debug: '^4.3.3', + }, + }, + }, + }) + }, + targetStructure: { 'package.json': { type: 'file', content: '{}' } }, +})) + +it('installs the given node package with yarn when yarn was used to run the preset', async() => await usingSandbox({ + fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = 'yarn' + const { executePreset } = await makeTestPreset({ + handler: async() => await installPackages({ + for: 'node', + packages: 'debug@^4.3.4', + }), + }) + + await executePreset() + await expectStructureMatches(targetDirectory, { + 'node_modules': { type: 'directory' }, + 'node_modules/debug': { type: 'directory' }, + 'yarn.lock': { type: 'file' }, + 'package.json': { + type: 'file', + json: { + dependencies: { + debug: '^4.3.4', + }, + }, + }, + }) + }, + targetStructure: { 'package.json': { type: 'file', content: '{}' } }, +})) + +it('installs the given node package with pnpm when pnpm was used to run the preset', async() => await usingSandbox({ + fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = 'pnpm' + const { executePreset } = await makeTestPreset({ + handler: async() => await installPackages({ + for: 'node', + packages: 'debug@^4.3.4', + additionalArgs: ['--ignore-workspace'], + }), + }) + + await executePreset() + await expectStructureMatches(targetDirectory, { + 'node_modules': { type: 'directory' }, + 'node_modules/debug': { type: 'directory' }, + 'pnpm-lock.yaml': { type: 'file' }, + 'package.json': { + type: 'file', + json: { + dependencies: { + debug: '^4.3.4', + }, + }, + }, + }) + }, + targetStructure: { 'package.json': { type: 'file', content: '{}' } }, +})) + it('installs the given node package as development dependencies', async() => await usingSandbox({ fn: async({ targetDirectory }, makeTestPreset) => { const { executePreset } = await makeTestPreset({ @@ -123,6 +209,7 @@ it('installs the given node package with the specified package manager', async() for: 'node', packages: 'debug@4.3.3', packageManager: 'pnpm', + additionalArgs: ['--ignore-workspace'], }), }) @@ -175,6 +262,7 @@ it('installs the given packages at once', async() => await usingSandbox({ it('installs packages already present in package.json with npm', async() => await usingSandbox({ fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = undefined const { executePreset } = await makeTestPreset({ handler: async() => await installPackages(), }) @@ -279,3 +367,70 @@ it('installs existing packages with yarn', async() => await usingSandbox({ 'package.json': { type: 'file', content: '{"dependencies": {"debug": "^4.3.4"}}' }, }, })) + +it('installs existing packages with npm when npm was used to run the preset', async() => await usingSandbox({ + fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = 'npm' + const { executePreset } = await makeTestPreset({ + handler: async() => await installPackages({ + for: 'node', + }), + }) + + await executePreset() + await expectStructureMatches(targetDirectory, { + 'node_modules': { type: 'directory' }, + 'node_modules/debug': { type: 'directory' }, + 'package-lock.json': { type: 'file' }, + }) + }, + targetStructure: { + ...emptyPackageJsonStructure, + 'package.json': { type: 'file', content: '{"dependencies": {"debug": "^4.3.4"}}' }, + }, +})) + +it('installs existing packages with yarn when yarn was used to run the preset', async() => await usingSandbox({ + fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = 'yarn' + const { executePreset } = await makeTestPreset({ + handler: async() => await installPackages({ + for: 'node', + }), + }) + + await executePreset() + await expectStructureMatches(targetDirectory, { + 'node_modules': { type: 'directory' }, + 'node_modules/debug': { type: 'directory' }, + 'yarn.lock': { type: 'file' }, + }) + }, + targetStructure: { + ...emptyPackageJsonStructure, + 'package.json': { type: 'file', content: '{"dependencies": {"debug": "^4.3.4"}}' }, + }, +})) + +it('installs existing packages with pnpm when pnpm was used to run the preset', async() => await usingSandbox({ + fn: async({ targetDirectory }, makeTestPreset) => { + process.env.npm_config_user_agent = 'pnpm' + const { executePreset } = await makeTestPreset({ + handler: async() => await installPackages({ + for: 'node', + additionalArgs: ['--ignore-workspace'], + }), + }) + + await executePreset() + await expectStructureMatches(targetDirectory, { + 'node_modules': { type: 'directory' }, + 'node_modules/debug': { type: 'directory' }, + 'pnpm-lock.yaml': { type: 'file' }, + }) + }, + targetStructure: { + ...emptyPackageJsonStructure, + 'package.json': { type: 'file', content: '{"dependencies": {"debug": "^4.3.4"}}' }, + }, +}))