From 91e46a34b685ebbf134d573209731868cae304d0 Mon Sep 17 00:00:00 2001 From: milaninfy <111582375+milaninfy@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:20:12 -0400 Subject: [PATCH] fix(init): use locally installed version of given package (#7721) `npm init` calls `libnpmexec` with path and runPath, for most cases it would not matter but when we have a package installed locally on root and we want to run `npm init that-package -w workspace` it should identify that-package is installed and use that to init new workspace package. here the `path` is where node_modules are and `runPath` is cwd to run the command. Fixes: https://github.com/npm/cli/issues/7700 --- lib/commands/init.js | 5 ++--- test/lib/commands/init.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/commands/init.js b/lib/commands/init.js index 4c68210483598..b8ef3e59ccf29 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -95,7 +95,7 @@ class Init extends BaseCommand { await this.update(workspacesPaths) } - async execCreate (args, path = process.cwd()) { + async execCreate (args, runPath = process.cwd()) { const [initerName, ...otherArgs] = args let packageName = initerName @@ -129,7 +129,6 @@ class Init extends BaseCommand { globalBin, chalk, } = this.npm - const runPath = path const scriptShell = this.npm.config.get('script-shell') || undefined const yes = this.npm.config.get('yes') @@ -140,7 +139,7 @@ class Init extends BaseCommand { globalBin, output, chalk, - path, + path: this.npm.localPrefix, runPath, scriptShell, yes, diff --git a/test/lib/commands/init.js b/test/lib/commands/init.js index f210c9bc2c931..1e45347429258 100644 --- a/test/lib/commands/init.js +++ b/test/lib/commands/init.js @@ -1,5 +1,6 @@ const t = require('tap') const fs = require('node:fs/promises') +const nodePath = require('node:path') const { resolve, basename } = require('node:path') const _mockNpm = require('../../fixtures/mock-npm') const { cleanTime } = require('../../fixtures/clean-snapshot') @@ -428,4 +429,33 @@ t.test('workspaces', async t => { t.equal(ws.version, '1.0.0') t.equal(ws.license, 'ISC') }) + t.test('init pkg - installed workspace package', async t => { + const { npm } = await mockNpm(t, { + prefixDir: { + 'package.json': JSON.stringify({ + name: 'init-ws-test', + dependencies: { + '@npmcli/create': '1.0.0', + }, + workspaces: ['test/workspace-init-a'], + }), + 'test/workspace-init-a': { + 'package.json': JSON.stringify({ + version: '1.0.0', + name: '@npmcli/create', + bin: { 'init-create': 'index.js' }, + }), + 'index.js': `#!/usr/bin/env node + require('fs').writeFileSync('npm-init-test-success', '') + console.log('init-create ran')`, + }, + }, + }) + await npm.exec('install', []) // reify + npm.config.set('workspace', ['test/workspace-init-b']) + await npm.exec('init', ['@npmcli']) + const exists = await fs.stat(nodePath.join( + npm.prefix, 'test/workspace-init-b', 'npm-init-test-success')) + t.ok(exists.isFile(), 'bin ran, creating file inside workspace') + }) })