क्या मैं Node.js में चल रहे जावास्क्रिप्ट से NPM पैकेज स्थापित कर सकता हूँ?


91

क्या मैं Node.js में चल रही जावास्क्रिप्ट फ़ाइल से NPM पैकेज स्थापित कर सकता हूँ? उदाहरण के लिए, मैं एक स्क्रिप्ट रखना चाहता हूं, इसे "script.js" कहें जो किसी भी तरह (... NPM का उपयोग कर रहा है या नहीं ...) आमतौर पर NPM के माध्यम से उपलब्ध एक पैकेज स्थापित करता है। इस उदाहरण में, मैं "FFI" स्थापित करना चाहूंगा। (npm इंस्टाल करें ffi)

जवाबों:


109

यह वास्तव में npm प्रोग्रामेटिक रूप से उपयोग करना संभव है , और इसे प्रलेखन के पुराने संशोधनों में उल्लिखित किया गया था। तब से इसे आधिकारिक दस्तावेज से हटा दिया गया है, लेकिन फिर भी निम्नलिखित विवरण के साथ स्रोत नियंत्रण पर मौजूद है:

यद्यपि npm को प्रोग्रामेटिक रूप से उपयोग किया जा सकता है, इसका API केवल CLI द्वारा उपयोग के लिए है, और किसी भी अन्य उद्देश्य के लिए इसकी फिटनेस के बारे में कोई गारंटी नहीं दी गई है। यदि आप किसी कार्य को मज़बूती से करने के लिए npm का उपयोग करना चाहते हैं, तो सबसे सुरक्षित बात यह है कि उपयुक्त तर्क के साथ वांछित npm कमांड को लागू करना है।

एनपीएम का शब्दार्थ संस्करण अंतर्निहित एपीआई के बजाय सीएलआई को ही संदर्भित करता है। आंतरिक API को स्थिर रहने की गारंटी नहीं है यहां तक ​​कि जब npm का संस्करण इंगित करता है कि कोई ब्रेकिंग परिवर्तन सेमेस्टर के अनुसार नहीं किए गए हैं

मूल दस्तावेज में, निम्नलिखित कोड नमूना है जो प्रदान किया गया था:

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) { ... })
})

चूंकि npmnode_modules फ़ोल्डर में मौजूद है , आप require('npm')इसे किसी अन्य मॉड्यूल की तरह लोड करने के लिए उपयोग कर सकते हैं । मॉड्यूल स्थापित करने के लिए, आप उपयोग करना चाहेंगे npm.commands.install()

यदि आपको स्रोत में देखना है तो यह GitHub पर भी है । यहां कोड का एक पूर्ण कार्य उदाहरण दिया गया है, जो npm installबिना किसी कमांड-लाइन तर्क के चलने के बराबर है:

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);
  });
});

ध्यान दें कि इंस्टॉल फ़ंक्शन के लिए पहला तर्क एक सरणी है। सरणी का प्रत्येक तत्व एक मॉड्यूल है जिसे npm स्थापित करने का प्रयास करेगा।

npm-cli.jsस्रोत नियंत्रण पर फ़ाइल में अधिक उन्नत उपयोग पाया जा सकता है ।


5
अगर यह किसी की मदद करता है तो सुनिश्चित करें कि आप npm install npm --saveपहले करते हैं । उदाहरण महान काम करता है :)
mikermcneil

6
इसके अलावा, सावधान रहना - npmबहुत सारी निर्भरताएं हैं, इसलिए इसे अपने मॉड्यूल में जोड़ने से सबसे अधिक संभावना होगी कि इसे डाउनलोड करने में बहुत अधिक समय लगेगा। child_processअपने उपयोगकर्ताओं की मशीनों पर पहले से स्थापित वैश्विक npm का लाभ उठाने के उत्तरों में से एक को देखें ।
mikermcneil

1
पारित न npm.configकरने के लिए npm.load! यहां तक ​​कि @isaacs को नहीं पता कि फिर किस तरह की अजीब चीजें होंगी! इसके बजाय github.com/npm/npm/issues/4861#issuecomment-40533836 देखें , आप केवल 1 तर्क छोड़ सकते हैं।
जॉर्जी इवानकिन

2
मैं गंतव्य पथ कैसे निर्धारित करूं? (जब यह अलग है कि process.cwd())
गजस

1
चेतावनी के बावजूद एनपीएम आयात करने की इच्छा रखने वालों के लिए, ग्लोबल-एनपीएम बेहतर है (छोटा, कोई निर्भरता नहीं)npm install npm --save
ज़ुनामियस

26

हाँ। आप एक system कमांड निष्पादित करने के लिए child_process का उपयोग कर सकते हैं

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);
     }
 });

2
हां, आप कर सकते हैं, हालांकि कुछ निर्भरताएं स्थापित करने में असफल रहेंगी (अनुभव से बात करना, क्योंकि एक बार जब मैंने वास्तव में नोड के लिए CI सर्वर लिखा था )
Matej

5
खिड़कियों पर यह काम नहीं करता है! npm.cmdइसके बदले आपको कॉल करना होगा।
21

26

आप child_process का उपयोग कर सकते हैं । कार्यकारी या execSync अंडे देने के लिए एक खोल तो उस खोल के भीतर वांछित आदेश पर अमल, किसी भी उत्पन्न आउटपुट बफ़र:

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

यदि एक कॉलबैक फ़ंक्शन प्रदान किया जाता है, तो इसे तर्कों (त्रुटि, स्टडआउट, स्टेडर) के साथ कहा जाता है। इस तरह आप इंस्टॉलेशन को चला सकते हैं जैसे आप इसे मैनुअल करते हैं और पूरा आउटपुट देखते हैं।

Child_process.execSync () विधि आम तौर पर अपवाद के साथ child_process.exec () के समान है कि विधि वापस नहीं आएगी जब तक कि बच्चा प्रक्रिया पूरी तरह से बंद नहीं हो जाती।


2
यह उन सभी उत्तरों से एकमात्र विकल्प है जो उदाहरण के लिए आपको npm स्थापित चलाने देता है और पूर्ण आउटपुट प्राप्त करता है जैसे कि आप मैन्युअल रूप से कमांड निष्पादित कर रहे थे! धन्यवाद!
जोर्न बर्कफेल्ड

1
क्या करता stdio: [0,1,2]है?
जैच स्मिथ

एक कॉलबैक फ़ंक्शन child_process.exec प्रदान की जाती है, तो यह तर्क [process.stdin, process.stdout, process.stderr] या [0,1,2] के अनुसार के बराबर के साथ कहा जाता है एपीआई डॉक
krankuba

11

यह वास्तव में थोड़ा आसान हो सकता है

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

2
इसका यह भी फायदा है कि स्ट्रैडर (और स्टडआउट) मुद्रित होते हैं जैसे कि वे होते हैं, निष्पादन के अंत में नहीं!
मवरमंड

1
यह उसी सीमा तक प्रिंट नहीं होता है जितना नीचे @krankuba का उत्तर है, जहां तक ​​मैं बता सकता हूं।
ज़च स्मिथ

6

मेरे पास एक समय की एक परियोजना की निर्देशिका के अंदर काम करने के लिए पहला उदाहरण प्राप्त करने की कोशिश करने की एक बिल्ली थी, किसी और के यहां मिलने की स्थिति में यहां पोस्ट करना। जहां तक ​​मैं बता सकता हूं, एनपीएम अभी भी सीधे लोड किए गए ठीक काम करता है, लेकिन क्योंकि यह सीएलआई मानता है, हमें खुद को थोड़ा सेटिंग सेट करना होगा:

// 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);
    });
});

3

pacote पैकेज है जो npm पैकेज मेटाडेटा और टारबॉल लाने के लिए उपयोग करता है। इसमें एक स्थिर, सार्वजनिक एपीआई है।


2

मैं एक मॉड्यूल का लेखक हूं जो आपके दिमाग में वही करने की अनुमति देता है। लाइव-प्लगइन-प्रबंधक देखें ।

आप एनपीएम, जीथब या फ़ोल्डर से लगभग किसी भी पैकेज को स्थापित और चला सकते हैं।

यहाँ एक उदाहरण है:

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();

उपरोक्त कोड में मैं momentरनटाइम पर पैकेज स्थापित करता हूं , इसे लोड और निष्पादित करता हूं । अंत में मैं इसे अनइंस्टॉल कर देता हूं।

आंतरिक रूप से मैं npmcli नहीं चलाता, लेकिन वास्तव में संकुल डाउनलोड करता हूँ और नोड VM सैंडबॉक्स के अंदर चलाता हूँ।


1

@Hexacyanide द्वारा एक महान समाधान, लेकिन यह निकला कि एनपीएम "लॉग" इवेंट को अब और कम से कम (संस्करण 6.4.1 के रूप में) उत्सर्जित नहीं करता है। इसके बजाय वे एक स्टैंडअलोन मॉड्यूल https://github.com/npm/npmlog पर भरोसा करते हैं । सौभाग्य से यह एक सिंगलटन है, इसलिए हम लॉग्स के लिए एनपीएम के उपयोग और लॉग इवेंट्स के लिए सदस्यता लेने के बहुत ही उदाहरण तक पहुंच सकते हैं:

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" );    
    });

  });

जैसा कि आप कोड से देख सकते हैं, एनपीएम पर प्रदर्शन मेट्रिक्स का भी उत्सर्जन करता है process, इसलिए हम इसका उपयोग प्रगति की निगरानी के लिए भी कर सकते हैं।


1

एक अन्य विकल्प, जिसका उल्लेख यहां नहीं किया गया है, वह है कांटा और सीएलआई को सही से चलाना ./node_modules/npm/bin/npm-cli.js

उदाहरण के लिए आप मशीन पर स्क्रिप्ट चलाने से नोड मॉड्यूल स्थापित करने में सक्षम होना चाहते हैं, जिसमें एनपीएम स्थापित नहीं है। और आप इसे CLI के साथ करना चाहते हैं। इस मामले में बस अपने प्रोग्राम ( npm i npm) का निर्माण करते समय स्थानीय रूप से अपने नोड_मॉडल में एनपीएम स्थापित करें ।

फिर इसे इस तरह उपयोग करें:

// 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}`);
});

तब आपका प्रोग्राम बाइनरी फ़ाइल में भी पैक किया जा सकता है, उदाहरण के लिए पीकेजी पैकेज के साथ । इस स्थिति में आपको --ignore-scriptsnpm विकल्प का उपयोग करने की आवश्यकता है , क्योंकि पूर्व-स्थापना स्क्रिप्ट को चलाने के लिए नोड-जिप आवश्यक है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.