From e1591dfcdba353a1b1d7b1a283c565fb88e3f63c Mon Sep 17 00:00:00 2001 From: Sonishi Izuka Date: Wed, 24 May 2023 17:34:38 +0900 Subject: [PATCH 1/2] Add a test to get the correct global bin installation path on Windows --- __test__/common.spec.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/__test__/common.spec.js b/__test__/common.spec.js index 612f793..805a297 100644 --- a/__test__/common.spec.js +++ b/__test__/common.spec.js @@ -9,16 +9,16 @@ jest.mock('mkdirp'); describe('common', () => { describe('getInstallationPath()', () => { - let callback, env; + let callback, _process; beforeEach(() => { callback = jest.fn(); - env = { ...process.env }; + _process = { ...global.process, env: { ...process.env } }; }); afterEach(() => { - process.env = env; + global.process = _process; }); it('should get binaries path from `npm bin`', () => { @@ -29,9 +29,21 @@ describe('common', () => { expect(callback).toHaveBeenCalledWith(null, path.sep + path.join('usr', 'local', 'bin')); }); - it('should get binaries path from env', () => { + it('should get binaries path from env on windows platform', () => { + childProcess.exec.mockImplementationOnce((_cmd, cb) => cb(new Error())); + + process.platform = 'win32'; + process.env.npm_config_prefix = String.raw`C:\Users\John Smith\AppData\npm`; + + common.getInstallationPath(callback); + + expect(callback).toHaveBeenCalledWith(null, path.win32.join('C:', 'Users', 'John Smith', 'AppData', 'npm')); + }); + + it('should get binaries path from env on platform different than windows', () => { childProcess.exec.mockImplementationOnce((_cmd, cb) => cb(new Error())); + process.platform = 'linux'; process.env.npm_config_prefix = '/usr/local'; common.getInstallationPath(callback); From 4d60bbd53831d367ff9c3b5f3933874cd4d935fa Mon Sep 17 00:00:00 2001 From: Sonishi Izuka Date: Wed, 24 May 2023 17:41:35 +0900 Subject: [PATCH 2/2] Install global bin to the correct location on Windows On Windows, the globally installed CLI is placed in the `%npm_config_prefix%` directory, not the `%npm_config_prefix%\bin` directory. > When in global mode, executables are linked into `{prefix}/bin` on Unix, > or directly into `{prefix}` on Windows. Ensure that path is in your > terminal's `PATH` environment to run them. > --- https://github.com/npm/cli/blob/1e977eec223463b04a6ad2c1953e31a6d5d22f2c/docs/lib/content/configuring-npm/folders.md?plain=1#L55-L57 This pull request fixes a bug that did not conform to this behavior. Closes https://github.com/go-task/go-npm/issues/4 --- src/common.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common.js b/src/common.js index d7d7434..1cd8550 100644 --- a/src/common.js +++ b/src/common.js @@ -39,7 +39,13 @@ function getInstallationPath(callback) { const packageManager = usedPM(); if (env && env.npm_config_prefix) { - dir = join(env.npm_config_prefix, 'bin'); + if (process.platform === 'win32') { + // On Windows, use the installation directory itself instead of the `bin` folder. + // See: https://docs.npmjs.com/cli/v6/configuring-npm/folders#executables + dir = env.npm_config_prefix; + } else { + dir = join(env.npm_config_prefix, 'bin'); + } } else if (env && env.npm_config_local_prefix) { dir = join(env.npm_config_local_prefix, join('node_modules', '.bin')); } else if (packageManager.name.toLowerCase() === 'pnpm') {