Передать аргументы командной строки в сценарии npm в package.json

У меня есть следующие сценарии в моем package.json:

"scripts": {
    "vumper": "node node_modules/vumper/index.js",
    "format": "prettier --single-quote -width=80 --write package.json"
 },

Пакет «vumper» принимает аргумент командной строки (например, «dv»). То, что я хотел бы сделать, это иметь команду, которая запускает оба из них последовательно.

По сути, я хотел бы иметь возможность запускать:

npm run vumber dv

а потом

npm run format

но в одной команде что-то вроде

npm run my-build dv

который будет запускать обе вышеуказанные команды, правильно принимая аргумент командной строки «dv» и передавая его первому vumper запуска npm. Это возможно?


person Tony Scialo    schedule 17.07.2018    source источник


Ответы (3)


Короткий ответ:

По сути, вам нужен npm-скрипт, подобный этому, где <arg-here> предоставляется через CLI;

...
"scripts": {
  "my-build": "npm run vumper <arg-here> && npm run format",
  ...
},
...

Однако, к сожалению, в npm нет встроенной функции для достижения этой цели.

Специальная опция npm -- (дополнительную информацию об этой опции см. в конце Решения 1 ниже) можно использовать только для передачи аргумента в END сценарий, но НЕ в СРЕДНИЙ. Итак, если бы ваши две команды были в противоположном порядке, параметр -- можно было бы использовать следующим образом:

...
"scripts": {
  "my-build": "npm run format && npm run vumper --",
  ...
},
...

Чтобы преодолеть ограничение отсутствия встроенной функции для передачи аргумента в MIDDLE сценария, рассмотрите следующие решения:

  1. Решение только для Bash см. в разделе Решение 1.

  2. Если требуется межплатформенная поддержка, следуйте решению, описанному в разделе Решение 2.


Решение 1. Bash (MacOS/Linux/и т. д.):

Настройте сценарий my-build в разделе scripts файла package.json для вызова Bash функция оболочки, как показано ниже:

package.json

...
"scripts": {
  "my-build": "func() { npm run vumper \"$1\" && npm run format; }; func",
  "vumper": "node node_modules/vumper/index.js",
  "format": "prettier --single-quote -width=80 --write package.json"
},
...

Пояснение:

Функция Bash с именем func делает следующее:

  1. Сначала работает npm run vumper <arg>. При этом <arg> будет аргументом оболочки, передаваемым через CLI. В сценарии на него ссылается $1 (т. е. первый позиционный параметр/аргумент).
  2. Впоследствии он запускает сценарий с именем format с помощью команды npm run format.

Эти две команды npm run объединены в цепочку с помощью оператора &&, поэтому вторая команда npm run format запустится только в том случае, если начальная команда npm run vumper <arg> завершится успешно (т. е. вернет код выхода 0).

Запуск сценария my-build:

Чтобы вызвать my-build через интерфейс командной строки, вам нужно запустить:

npm run my-build -- dv

Примечание:

  1. В этом случае конечная часть dv является аргументом, который будет передан вашему сценарию vumper.

  2. #P16# <блочная цитата> #P17#

Решение 2. Кроссплатформенность.

Для кроссплатформенного решения (которое успешно работает с Bash, командной строкой Windows/cmd.exe, PowerShell и т. д.) вам потребуется использовать вспомогательный скрипт nodejs следующим образом.

run.js

Давайте назовем скрипт nodejs run.js и сохраним его в корневом каталоге проекта на том же уровне, что и package.json.

const execSync = require('child_process').execSync;

const arg = process.argv[2] || 'dv'; // Default value `dv` if no args provided via CLI.

execSync('npm run vumper ' + arg, {stdio:[0, 1, 2]});
execSync('npm run format', {stdio:[0, 1, 2]});

package.json

Настройте свой скрипт my-build для вызова run.js следующим образом:

...
"scripts": {
  "my-build": "node run",
  "vumper": "node node_modules/vumper/index.js",
  "format": "prettier --single-quote -width=80 --write package.json"
},
...

Запуск скрипта my-build:

Согласно Решению 1, чтобы вызвать my-build через интерфейс командной строки, вам нужно выполнить:

npm run my-build -- dv

Пояснение:

  • run.js использует process.argv для получения аргумент, передаваемый через интерфейс командной строки (например, dv). Если при запуске npm run my-build аргумент не указан, значение по умолчанию (то есть dv) передается в vumper npm-скрипт.

  • run.js также использует child_process.execSync(...) для shell- out/вызвать две команды npm run.

person RobC    schedule 18.07.2018
comment
Разве нет пакета cli npm, который просто делал бы что-то вроде const args = process.argv.slice(3); const command = args.reduce( (res, arg, index) => res.replace(new RegExp(`\\$${ index + 1 }`, 'g'), arg), process.argv[2] ); const execSync = require('child_process').execSync; execSync(command, { stdio: [0, 1, 2] }); ?. Таким образом, я могу просто обернуть любой скрипт \ и добавить к нему префикс такого кли и запустить любой скрипт с упорядоченными аргументами... - person Miguel Enrique León Figueras; 05.05.2020

Npm теперь имеет встроенную опцию для передачи аргументов cli напрямую в скрипты. Аргументы cli хранятся в переменных окружения с префиксом npm_config_<flagname>, и они требуют очень строгого синтаксиса в форме --<flagname>=<flagvalue>.

Пример:

 "my-build": "npm run vumper %npm_config_myflag% && npm run format",

В терминале запустите npm run my-build --myflag=my_value, чтобы выполнить npm run vumper my_value && npm run format.

Примечание:

Чтобы сослаться на переменную окружения в скрипте npm, вы должны использовать специфичный для платформы синтаксис, то есть %npm_config_myflag% в Windows или $npm_config_myflag в Linux.

ОБНОВИТЬ:

Чтобы избежать риска конфликта с переменными npm_config, используемыми для настройки самого npm, просто добавьте к своим аргументам уникальный префикс, например, имя вашего приложения.

Потенциальный конфликт является очень распространенной проблемой, которая применяется во многих контекстах: любое приложение может использовать переменные среды, уже используемые другими приложениями; по этой причине перед переменными среды обычно стоит имя приложения (например, NVM_HOME, JAVA_HOME). Но этот потенциальный конфликт не является веской причиной избегать использования переменных среды. То же самое, на мой взгляд, относится к npm params / npm_config env vars. В документе ничего не говорится о риске конфликты, подразумевая, что я предполагаю, что они должны управляться как обычно.

person Mabsten    schedule 05.11.2020
comment
Конкретная платформа была для меня ключевой. Я пробовал $npm_config_myflag в Windows и сошел с ума - person Nick Graham; 11.11.2020
comment
npm также создает свои собственные переменные env с именем npm_config_* для внутренних целей. Обязательно выберите имя для флага/параметра (например, --myflag=*), которое не переопределяет имя, используемое внутри, так как это может привести к нежелательным результатам. Вы можете cd перейти в каталог вашего проекта и запустить npm run env, чтобы получить список переменных окружения, которые добавляет npm. Например. передача --tag=foo не является хорошей идеей, потому что npm добавляет переменную env npm_config_tag (обычно ее значение равно latest). Используя этот метод, неясно, какие внутренние npm_config_* vars npm могут быть добавлены в будущем, которые вы в конечном итоге можете переопределить. - person RobC; 23.02.2021
comment
Вы можете обратиться к этому подходу, но использование этого подхода может быть опасным, как объяснил @RobC в комментарии. Так что не в отношении решения этого вопроса, а в целом, если чье-то требование состоит в том, чтобы добавить аргумент в конец команды, тогда не используйте подход с переменной среды, в таком случае он / она может использовать npm run ‹scriptname› -- ‹argument ›. - person Aman Kumar Gupta; 01.03.2021

Мой предпочтительный метод — использование переменных среды:

{
  "scripts": {
    "ncc-build": "ncc build $ACTION/src/index.ts -o $ACTION/dist",
    "build:pr-changelog": "ACTION=pr-changelog npm run ncc-build",
  }
}

Он должен работать в системах UNIX. Однако я не уверен в совместимости с Windows platfrom.

person axelraden    schedule 14.03.2021