|
10 | 10 | // Requirements
|
11 | 11 | // ------------------------------------------------------------------------------
|
12 | 12 |
|
| 13 | +const fs = require('fs') |
13 | 14 | const path = require('path')
|
14 | 15 | const parseArgs = require('shell-quote').parse
|
15 | 16 | const createHeader = require('./create-header')
|
@@ -128,6 +129,9 @@ function cleanTaskArg (arg) {
|
128 | 129 | * An array of options which are inserted before the task name.
|
129 | 130 | * @param {object} options.labelState - A state object for printing labels.
|
130 | 131 | * @param {boolean} options.printName - The flag to print task names before running each task.
|
| 132 | + * @param {object} options.packageInfo - A package.json's information. |
| 133 | + * @param {object} options.packageInfo.body - A package.json's JSON object. |
| 134 | + * @param {string} options.packageInfo.path - A package.json's file path. |
131 | 135 | * @returns {Promise}
|
132 | 136 | * A promise object which becomes fullfilled when the npm-script is completed.
|
133 | 137 | * This promise object has an extra method: `abort()`.
|
@@ -156,12 +160,37 @@ module.exports = function runTask (task, options) {
|
156 | 160 | }
|
157 | 161 |
|
158 | 162 | // Execute.
|
159 |
| - const npmPath = options.npmPath || path.basename(process.env.npm_execpath).startsWith('npx') // eslint-disable-line no-process-env |
160 |
| - ? path.join(path.dirname(process.env.npm_execpath), path.basename(process.env.npm_execpath).replace('npx', 'npm')) // eslint-disable-line no-process-env |
161 |
| - : process.env.npm_execpath // eslint-disable-line no-process-env |
162 |
| - const npmPathIsJs = typeof npmPath === 'string' && /\.m?js/.test(path.extname(npmPath)) |
163 |
| - const execPath = (npmPathIsJs ? process.execPath : npmPath || 'npm') |
| 163 | + let npmPath = options.npmPath |
| 164 | + if (!npmPath && process.env.npm_execpath) { |
| 165 | + const basename = path.basename(process.env.npm_execpath) |
| 166 | + let newBasename = basename |
| 167 | + if (basename.startsWith('npx')) { |
| 168 | + newBasename = basename.replace('npx', 'npm') // eslint-disable-line no-process-env |
| 169 | + } else if (basename.startsWith('pnpx')) { |
| 170 | + newBasename = basename.replace('pnpx', 'pnpm') // eslint-disable-line no-process-env |
| 171 | + } |
| 172 | + |
| 173 | + npmPath = newBasename === basename |
| 174 | + ? path.join(path.dirname(process.env.npm_execpath), newBasename) |
| 175 | + : process.env.npm_execpath // eslint-disable-line no-process-env |
| 176 | + } |
| 177 | + |
| 178 | + const npmPathIsJs = typeof npmPath === 'string' && /\.(c|m)?js/.test(path.extname(npmPath)) |
| 179 | + let execPath = (npmPathIsJs ? process.execPath : npmPath || 'npm') |
| 180 | + |
| 181 | + if (!npmPath && !process.env.npm_execpath) { |
| 182 | + // When a script is being run via pnpm, npmPath and npm_execpath will be null or undefined |
| 183 | + // Attempt to figure out whether we're running via pnpm |
| 184 | + const projectRoot = path.dirname(options.packageInfo.path) |
| 185 | + const hasPnpmLockfile = fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml')) |
| 186 | + const { status: pnpmFound, output } = spawn.sync('which', 'pnpm', { silent: true }) |
| 187 | + if (hasPnpmLockfile && __dirname.split(path.delimiter).includes('.pnpm') && pnpmFound) { |
| 188 | + execPath = output |
| 189 | + } |
| 190 | + } |
| 191 | + |
164 | 192 | const isYarn = process.env.npm_config_user_agent && process.env.npm_config_user_agent.startsWith('yarn') // eslint-disable-line no-process-env
|
| 193 | + |
165 | 194 | const spawnArgs = ['run']
|
166 | 195 |
|
167 | 196 | if (npmPathIsJs) {
|
|
0 commit comments