Búsqueda de sitios web

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 -rf para node.

Uso

  1. Usa cd para ir a tu directorio de proyecto y ejecuta el siguiente comando:

    npm install rimraf --save-dev
    
  2. Cambia tu script clean en package.json a lo siguiente:

    "scripts": {
      "clean": "rimraf lib",
      ...
    },
    
  3. Elimina el script clean:windows de tu package.json ya 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:

  1. cd a tu directorio de proyecto e instala shelljs ejecutando el siguiente comando:

    npm install shelljs --save-dev
    
  2. Crea 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 .scripts en el directorio raíz del proyecto. Por ejemplo:

    .
    ├── .scripts
    │   └── clean.js
    ├── lib
    │   └── ...
    ├── node_modules
    │   └── ...
    ├── package.json
    ├── src
    │   └── ...
    └── ...
    
  3. Reemplaza tu script clean en package.json con lo siguiente:

    "scripts": {
      "clean": "node .scripts/clean lib",
      ...
    },
    

    También puedes pasar múltiples argumentos de ruta a clean.js tambié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",
      ...
    },
    
  4. Elimina el script clean:windows de tu package.json ya que ahora es redundante.

Notas

  1. clean.js utiliza el process.argv incorporado de Node para obtener un array de argumentos de la línea de comandos pasados a Node cuando se invocó el script.

  2. Luego usamos slice() en el arreglo de argumentos a partir del índice 2 para asegurarnos de que solo se incluyan los argumentos de la ruta de la carpeta/archivo (por ejemplo, lib).

  3. Finalmente, recorremos cada ruta de carpeta en el array usando forEach() y invocamos shell.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:

shx es 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

  1. Ejecute el siguiente comando para instalar shx:

    npm i -D shx
    
  2. Luego redefine tu script clean en package.json de 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.

Artículos relacionados