102 votes

Puis-je installer un paquet NPM à partir de javascript s'exécutant dans Node.js ?

Puis-je installer un paquet NPM à partir d'un fichier javascript s'exécutant dans Node.js ? Par exemple, j'aimerais avoir un script, appelons-le "script.js" qui d'une manière ou d'une autre (...en utilisant NPM ou non...) installe un package habituellement disponible via NPM. Dans cet exemple, j'aimerais installer "FFI". (npm install ffi)

4voto

James A. Rosen Points 25774

pacote est le paquet que npm utilise pour récupérer les métadonnées des paquets et les tarballs. Il dispose d'une API publique et stable.

4voto

tarkh Points 1442

Une autre option, qui n'a pas été mentionnée ici, est de faire un fork et de lancer le CLI directement à partir de ./node_modules/npm/bin/npm-cli.js

Par exemple, vous voulez être en mesure d'installer des modules de nœuds en exécutant script sur une machine qui n'a pas NPM installé. Et vous VOULEZ le faire avec CLI. Dans ce cas, il suffit d'installer NPM dans votre node_modules localement tout en construisant votre programme ( npm i npm ).

Alors utilisez-le comme ceci :

// Require child_process module
const { fork } = require('child_process');
// Working directory for subprocess of installer
const cwd = './path-where-to-run-npm-command'; 
// CLI path FROM cwd path! Pay attention
// here - path should be FROM your cwd directory
// to your locally installed npm module
const cli = '../node_modules/npm/bin/npm-cli.js';
// NPM arguments to run with
// If your working directory already contains
// package.json file, then just install it!
const args = ['install']; // Or, i.e ['audit', 'fix']

// Run installer
const installer = fork(cli, args, {
  silent: true,
  cwd: cwd
});

// Monitor your installer STDOUT and STDERR
installer.stdout.on('data', (data) => {
  console.log(data);
});
installer.stderr.on('data', (data) => {
  console.log(data);
});

// Do something on installer exit
installer.on('exit', (code) => {
  console.log(`Installer process finished with code ${code}`);
});

Ensuite, votre programme pourrait même être empaqueté dans un fichier binaire, par exemple avec PKG paquet. Dans ce cas, vous devez utiliser --ignore-scripts option npm, parce que node-gyp nécessaire pour exécuter preinstall scripts.

2voto

Davide Icardi Points 2215

Je suis l'auteur d'un module qui permet de faire exactement ce que vous avez en tête. Voir live-plugin-manager .

Vous pouvez installer et exécuter pratiquement n'importe quel paquet à partir de NPM, Github ou d'un dossier.

Voici un exemple :

import {PluginManager} from "live-plugin-manager";

const manager = new PluginManager();

async function run() {
  await manager.install("moment");

  const moment = manager.require("moment");
  console.log(moment().format());

  await manager.uninstall("moment");
}

run();

Dans le code ci-dessus, j'installe moment au moment de l'exécution, le charge et l'exécute. À la fin, je le désinstalle.

En interne, je ne dirige pas npm cli mais en réalité, ils téléchargent des paquets et s'exécutent à l'intérieur d'un sandbox VM de node.

1voto

Dmitry Sheiko Points 101

Une excellente solution de @hexacyanide, mais il s'est avéré que NPM n'émet plus d'événement "log" (du moins à partir de la version 6.4.1). Au lieu de cela, ils s'appuient sur un module autonome https://github.com/npm/npmlog . Heureusement, il s'agit d'un singleton, ce qui nous permet d'accéder à la même instance que celle utilisée par NPM pour les journaux et de nous abonner aux événements des journaux :

const npmlog = require( "npm/node_modules/npmlog" ),
      npm = require( "npm" );

npmlog.on( "log", msg => {
   console.log({ msg });
});

 process.on("time", milestone => {
   console.log({ milestone });
 });

 process.on("timeEnd", milestone => {
   console.log({ milestone });    
 });

 npm.load({
    loaded: false,
    progress: false,
    "no-audit": true
  }, ( err ) => {

 npm.commands.install( installDirectory, [
      "cross-env@^5.2.0",
      "shelljs@^0.8.2"
    ], ( err, data ) => {
       console.log( "done" );    
    });

  });

Comme vous pouvez le voir dans le code, NPM émet également des mesures de performance sur le fichier process Nous pouvons donc également l'utiliser pour suivre l'évolution de la situation.

0voto

vipulgupta2048 Points 99

Ajoutant un peu plus à la grande réponse de tarkh . Si vous n'avez pas l'intention d'installer npm CLI explicitement et que vous installez déjà npm via le fichier package.json. Alors le fichier dans le répertoire ./node_modules/npm/bin/npm-cli.js est le CLI qui peut être utilisé pour exécuter des commandes.

Afin de le rendre globalement disponible, exécutez la commande suivante et ajoutez le binaire au chemin.

ln -sf /usr/app/node_modules/npm/bin/npm-cli.js /usr/bin/npm

En outre, si cela peut aider quelqu'un. Voici comment vous pouvez imiter les npm install afin d'installer tous les paquets dans le package.json.

const npm = require('npm');
const Bluebird = require('bluebird');

    async installDependencies() {
            await Bluebird.promisify(npm.load)({
                loglevel: 'silent',
                progress: false,
            });
            await Bluebird.promisify(npm.install)(
                "/path/to/directory/where/package.json/is",
            );
        }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X