typescript - Script condicional de NPM (Windows/Mac) debe ejecutar diferentes comandos
Caso de uso:
Estoy configurando un hook prepublishOnly en NPM que elimina la carpeta "lib", luego transpila los archivos fuente de TypeScript a una nueva carpeta lib y luego ejecuta la prueba.
El problema:
Se supone que dos personas deben publicar los paquetes de NPM, ambas trabajando en diferentes sistemas operativos (Windows/Mac). Por lo tanto, los comandos para eliminar las carpetas son diferentes.
"scripts": {
"build": "tsc",
"clean": "rm -rf lib",
"clean:windows": "if exist lib rmdir /s /q lib",
"lint": "tslint --project tsconfig.json --format stylish src/**/*.ts",
"format": "prettier --write \"**/*.ts\""
},
"husky": {
"hooks": {
"pre-push": "npm run clean:windows && npm run build && npm run test"
}
},
La pregunta:
¿Hay alguna manera de ejecutar scripts de NPM de manera condicional (basado en el sistema operativo usado) o hay un comando para eliminar carpetas que funcione en estos sistemas operativos?
Respuesta #1
Agregar gulp a tu lista de herramientas parece bastante innecesario si todo lo que quieres hacer es eliminar una carpeta(s) mediante un script de npm de manera multiplataforma. Para una solución ligera, considera las siguientes dos soluciones en su lugar:
Solución 1
Echa un vistazo a rimraf, se describe como:
El comando de UNIX
rm -rfpara node.
Uso
Usa
cdpara ir a tu directorio de proyecto y ejecuta el siguiente comando:npm install rimraf --save-devCambia tu script
cleanenpackage.jsona lo siguiente:"scripts": { "clean": "rimraf lib", ... },Elimina el script
clean:windowsde tupackage.jsonya que ahora es redundante.
Nota No he tenido mucho éxito con ello al instalarlo como una dependencia local, por lo que utilizo la segunda solución que se muestra a continuación. Sin embargo, es posible que tengas más éxito, así que vale la pena intentarlo.
Solución 2
La siguiente solución utiliza el comando rm de shelljs, que es análogo al comando rm -rf de Unix, excepto que es para Node, por lo tanto, es un equivalente multiplataforma.
Los siguientes pasos muestran cómo se puede lograr esto:
cda tu directorio de proyecto e instala shelljs ejecutando el siguiente comando:npm install shelljs --save-devCrea un script personalizado de Node como sigue, llamemos al archivo
clean.js:const shell = require('shelljs'); process.argv.slice(2).forEach(function(_path) { shell.rm('-rf', _path); });y guárdalo en un directorio oculto llamado
.scriptsen el directorio raíz del proyecto. Por ejemplo:. ├── .scripts │ └── clean.js ├── lib │ └── ... ├── node_modules │ └── ... ├── package.json ├── src │ └── ... └── ...Reemplaza tu script
cleanenpackage.jsoncon lo siguiente:"scripts": { "clean": "node .scripts/clean lib", ... },También puedes pasar múltiples argumentos de ruta a
clean.jstambién. Por ejemplo:"scripts": { "clean": "node .scripts/clean lib another/folder/path foo/bar", ... },También se manejan las rutas de archivos. Por ejemplo:
"scripts": { "clean": "node .scripts/clean path/to/quux.js", ... },Elimina el script
clean:windowsde tupackage.jsonya que ahora es redundante.
Notas
clean.jsutiliza elprocess.argvincorporado de Node para obtener un array de argumentos de la línea de comandos pasados a Node cuando se invocó el script.Luego usamos slice() en el arreglo de argumentos a partir del índice
2para asegurarnos de que solo se incluyan los argumentos de la ruta de la carpeta/archivo (por ejemplo,lib).Finalmente, recorremos cada ruta de carpeta en el array usando
forEach()y invocamosshell.rm('-rf', _path);en cada iteración del bucle para eliminar el recurso.
Editar/Actualizar:
Una solución alternativa multiplataforma, (que no estaba disponible cuando se publicó originalmente esta respuesta), es utilizar el paquete shx, que se describe como:
shxes un envoltorio alrededor de los comandos Unix de ShellJS, proporcionando una solución fácil para comandos simples de tipo Unix y multiplataforma en los scripts de paquetes npm
Ejecute el siguiente comando para instalar
shx:npm i -D shxLuego redefine tu script
cleanenpackage.jsonde la siguiente manera:"scripts": { "clean": "shx rm -rf lib" }
Respuesta #2
La forma en que soluciono problemas como este es usar gulp para definir un conjunto de tareas específicas del sistema operativo porque el código que escribes allí es independiente del sistema operativo.
Necesitarás instalar gulp como una dependencia y crear un gulpfile.js en el directorio raíz. En él, define una tarea para eliminar la carpeta.
var gulp = require('gulp'),
path = require('path'),
fs = require('fs-extra');
const rootFolder = path.join(__dirname);
const libFolder = path.join(rootFolder, 'lib');
gulp.task('clean:lib', function () {
return deleteFolder(libFolder);
});
function deleteFolder(folder) {
return fs.removeSync(folder);
}
gulp.task('deleteLib', ['clean:lib']);
Luego, en el script de tu package.json, puedes hacer && gulp deleteLib. (¡Asegúrate de que los paquetes que usas en tu gulpfile estén instalados como dependencias de desarrollo en tu package.json!)
El código no está probado y está escrito de manera improvisada, pero es solo para darte una idea general.
