Nota: este enfoque modifica su package.json
sobre la marcha, úselo si no tiene otra alternativa.
Tuve que pasar argumentos de línea de comando a mis scripts que eran algo así como:
"scripts": {
"start": "npm run build && npm run watch",
"watch": "concurrently \"npm run watch-ts\" \"npm run watch-node\"",
...
}
Entonces, esto significa que comienzo mi aplicación con npm run start
.
Ahora, si quiero pasar algunos argumentos, comenzaría con quizás:
npm run start -- --config=someConfig
Lo que esto hace es: npm run build && npm run watch -- --config=someConfig
. El problema con esto es que siempre agrega los argumentos al final del guión. Esto significa que todos los scripts encadenados no obtienen estos argumentos (Args puede o no ser requerido por todos, pero esa es una historia diferente). Además, cuando se invocan los scripts vinculados, esos scripts no obtendrán los argumentos pasados. es decir, el watch
script no obtendrá los argumentos pasados.
El uso de producción de mi aplicación es como .exe
, por lo que pasar los argumentos en el exe funciona bien, pero si desea hacer esto durante el desarrollo, se vuelve problamático.
No pude encontrar ninguna manera adecuada de lograr esto, así que esto es lo que he intentado.
He creado un archivo javascript: start-script.js
en el nivel primario de la aplicación, tengo un "default.package.json" y en lugar de mantener "package.json", mantengo "default.package.json". El propósito de start-script.json
es leer default.package.json
, extraer scripts
y buscar y npm run scriptname
luego agregar los argumentos pasados a estos scripts. Después de esto, creará uno nuevo package.json
y copiará los datos de default.package.json con scripts modificados y luego llamará 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);
}
Ahora, en lugar de hacerlo npm run start
, hagonode start-script.js --c=somethis --r=somethingElse
La ejecución inicial se ve bien, pero no se ha probado a fondo. Úselo, si lo desea para su desarrollo de aplicaciones.
yargs
; Todos los parámetros posteriores--
se pueden analizar perfectamente en su secuencia de comandos.