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)

125voto

hexacyanide Points 15723

Il est en effet possible d'utiliser npm programmatiquement, et elle était décrite dans les anciennes révisions de la documentation. Elle a depuis été retirée de la documentation officielle, mais existe toujours dans le contrôle de source avec la déclaration suivante :

Bien que npm puisse être utilisé de manière programmatique, son API est destinée à être utilisée par le CLI uniquement. CLI uniquement, et aucune garantie n'est donnée quant à son adéquation à tout autre usage. autre but. Si vous voulez utiliser npm pour effectuer une tâche de manière fiable, la chose la plus sûre à faire est d'invoquer la commande npm souhaitée avec les arguments appropriés.

La version sémantique de npm fait référence à la CLI elle-même, plutôt qu'à l'application l'API sous-jacente. La stabilité de l'API interne n'est pas garantie même si la version de npm indique qu'aucun changement de rupture n'a été effectué selon semver .

Dans la documentation originale, l'exemple de code fourni était le suivant :

var npm = require('npm')
npm.load(myConfigObject, function (er) {
  if (er) return handlError(er)
  npm.commands.install(['some', 'args'], function (er, data) {
    if (er) return commandFailed(er)
    // command succeeded, and data might have some info
  })
  npm.registry.log.on('log', function (message) { ... })
})

Desde npm existe dans le node_modules vous pouvez utiliser require('npm') pour le charger comme n'importe quel autre module. Pour installer un module, il faut utiliser npm.commands.install() .

Si vous avez besoin de regarder dans la source alors c'est aussi sur GitHub . Voici un exemple complet du code, qui est équivalent à l'exécution de npm install sans aucun argument de ligne de commande :

var npm = require('npm');
npm.load(function(err) {
  // handle errors

  // install module ffi
  npm.commands.install(['ffi'], function(er, data) {
    // log errors or data
  });

  npm.on('log', function(message) {
    // log installation progress
    console.log(message);
  });
});

Notez que le premier argument de la fonction install est un tableau. Chaque élément du tableau est un module que npm va tenter de s'installer.

Une utilisation plus avancée peut être trouvée dans le npm-cli.js dans le contrôle de la source.

42voto

krankuba Points 475

Vous pouvez utiliser processus_enfant . exec o execSync pour créer un shell et exécuter la commande souhaitée dans ce shell, en mettant en mémoire tampon toute sortie générée :

var child_process = require('child_process');
child_process.execSync('npm install ffi',{stdio:[0,1,2]});

Si une fonction de rappel est fournie, elle est appelée avec les arguments (error, stdout, stderr). De cette façon, vous pouvez exécuter l'installation comme vous le faites manuellement et voir le résultat complet.

La méthode child_process.execSync() est généralement identique à child_process.exec(), à l'exception du fait que la méthode ne reviendra pas avant la fermeture complète du processus enfant.

29voto

TheBrain Points 2474

Oui. vous pouvez utiliser child_process pour exécuter une commande système

var exec = require('child_process').exec,
    child;

 child = exec('npm install ffi',
 function (error, stdout, stderr) {
     console.log('stdout: ' + stdout);
     console.log('stderr: ' + stderr);
     if (error !== null) {
          console.log('exec error: ' + error);
     }
 });

11voto

Cela peut en fait être un peu facile

var exec = require('child_process').exec;
child = exec('npm install ffi').stderr.pipe(process.stderr);

7voto

Megamind Points 65

J'ai eu beaucoup de mal à faire fonctionner le premier exemple à l'intérieur d'un répertoire de projet, je le poste ici au cas où quelqu'un d'autre le trouverait. Pour autant que je puisse dire, NPM fonctionne toujours bien chargé directement, mais parce qu'il suppose une CLI, nous devons nous répéter un peu pour le configurer :

// this must come before load to set your project directory
var previous = process.cwd();
process.chdir(project);

// this is the part missing from the example above
var conf = {'bin-links': false, verbose: true, prefix: project}

// this is all mostly the same

var cli = require('npm');
cli.load(conf, (err) => {
    // handle errors
    if(err) {
        return reject(err);
    }

    // install module
    cli.commands.install(['ffi'], (er, data) => {
        process.chdir(previous);
        if(err) {
            reject(err);
        }
        // log errors or data
        resolve(data);
    });

    cli.on('log', (message) => {
        // log installation progress
        console.log(message);
    });
});

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