Nota: Essa abordagem modifica o seu package.json
em tempo real, use-o se você não tiver alternativa.
Eu tive que passar argumentos de linha de comando para meus scripts, que eram algo como:
"scripts": {
"start": "npm run build && npm run watch",
"watch": "concurrently \"npm run watch-ts\" \"npm run watch-node\"",
...
}
Então, isso significa que inicio meu aplicativo npm run start
.
Agora, se eu quiser passar alguns argumentos, começaria talvez:
npm run start -- --config=someConfig
O que isto faz é: npm run build && npm run watch -- --config=someConfig
. O problema é que ele sempre anexa os argumentos ao final do script. Isso significa que todos os scripts encadeados não recebem esses argumentos (Args pode ou não ser exigido por todos, mas isso é uma história diferente). Além disso, quando os scripts vinculados são chamados, esses scripts não receberão os argumentos passados. ou seja, o watch
script não receberá os argumentos passados.
O uso de produção do meu aplicativo é como um .exe
, portanto, passar os argumentos no exe funciona bem, mas se você quiser fazer isso durante o desenvolvimento, fica problemático.
Não consegui encontrar uma maneira adequada de conseguir isso, então é isso que tentei.
Criei um arquivo javascript: start-script.js
no nível pai do aplicativo, tenho um "default.package.json" e, em vez de manter "package.json", mantenho "default.package.json". O objetivo de start-script.json
é ler default.package.json
, extrair scripts
e procurar npm run scriptname
e anexar os argumentos passados a esses scripts. Depois disso, ele criará um novo package.json
e copiará os dados de default.package.json com scripts modificados e depois chamará npm run start
.
const fs = require('fs');
const { spawn } = require('child_process');
// open default.package.json
const defaultPackage = fs.readFileSync('./default.package.json');
try {
const packageOb = JSON.parse(defaultPackage);
// loop over the scripts present in this object, edit them with flags
if ('scripts' in packageOb && process.argv.length > 2) {
const passedFlags = ` -- ${process.argv.slice(2).join(' ')}`;
// assuming the script names have words, : or -, modify the regex if required.
const regexPattern = /(npm run [\w:-]*)/g;
const scriptsWithFlags = Object.entries(packageOb.scripts).reduce((acc, [key, value]) => {
const patternMatches = value.match(regexPattern);
// loop over all the matched strings and attach the desired flags.
if (patternMatches) {
for (let eachMatchedPattern of patternMatches) {
const startIndex = value.indexOf(eachMatchedPattern);
const endIndex = startIndex + eachMatchedPattern.length;
// save the string which doen't fall in this matched pattern range.
value = value.slice(0, startIndex) + eachMatchedPattern + passedFlags + value.slice(endIndex);
}
}
acc[key] = value;
return acc;
}, {});
packageOb.scripts = scriptsWithFlags;
}
const modifiedJSON = JSON.stringify(packageOb, null, 4);
fs.writeFileSync('./package.json', modifiedJSON);
// now run your npm start script
let cmd = 'npm';
// check if this works in your OS
if (process.platform === 'win32') {
cmd = 'npm.cmd'; // https://github.com/nodejs/node/issues/3675
}
spawn(cmd, ['run', 'start'], { stdio: 'inherit' });
} catch(e) {
console.log('Error while parsing default.package.json', e);
}
Agora, em vez de fazer npm run start
, eu façonode start-script.js --c=somethis --r=somethingElse
A execução inicial parece boa, mas não foi testada completamente. Use-o, se quiser, para o desenvolvimento de aplicativos.
yargs
; todos os parâmetros após o--
podem ser analisados perfeitamente em seu script.