Reputation: 31810
Is it possible to automatically download the required modules for a node.js script? I'm wondering if it's possible to generate a list of required modules for a node.js script (like the one below), and install them automatically, instead of installing them manually, one-by-one (using npm).
#!/usr/bin/env node
var DNode = require('dnode');
var sys = require('sys');
var fs = require('fs');
var http = require('http');
var html = fs.readFileSync(__dirname + '/web.html');
var js = require('dnode/web').source();
//the rest of this script is omitted.
Upvotes: 19
Views: 25001
Reputation: 17
when I open the script on windows by right clicking then open with nodejs it tries to install the node modules in system32 and it fails
I modified the script and it works
oneliner:
var req=async m=>{let r=require;try{r.resolve(m)}catch(e){console.log('Installing ' + m);r('child_process').execSync('npm i --prefix "'+__dirname+'" ' +m);await setImmediate(()=>{})}return r(m)};
full:
var cp = require('child_process');
var req = async module => {
try {
require.resolve(module);
} catch (e) {
console.log(`Could not resolve "${module}"\nInstalling`);
cp.execSync(`npm install --prefix "${__dirname}" ${module}`);
await setImmediate(() => {});
console.log(`"${module}" has been installed`);
}
console.log(`Requiring "${module}"`);
try {
return require(module);
} catch (e) {
console.log(`Could not include "${module}". Restart the script`);
process.exit(1);
}
};
Upvotes: 0
Reputation: 5291
I was inspired by @Aminadav Glickshtein's answer to create a script of my own that would synchronously install the needed modules, because his answer lacks these capabilities.
I needed some help, so I started an SO question here. You can read about how this script works there.
The result is as follows:
const cp = require('child_process')
const req = async module => {
try {
require.resolve(module)
} catch (e) {
console.log(`Could not resolve "${module}"\nInstalling`)
cp.execSync(`npm install ${module}`)
await setImmediate(() => {})
console.log(`"${module}" has been installed`)
}
console.log(`Requiring "${module}"`)
try {
return require(module)
} catch (e) {
console.log(`Could not include "${module}". Restart the script`)
process.exit(1)
}
}
const main = async () => {
const http = await req('http')
const path = await req('path')
const fs = await req('fs')
const express = await req('express')
// The rest of the app's code goes here
}
main()
And a one-liner (139 characters!). It doesn't globally define child_modules
, has no last try-catch
and doesn't log anything in the console:
const req=async m=>{let r=require;try{r.resolve(m)}catch(e){r('child_process').execSync('npm i '+m);await setImmediate(()=>{})}return r(m)}
const main = async () => {
const http = await req('http')
const path = await req('path')
const fs = await req('fs')
const express = await req('express')
// The rest of the app's code goes here
}
main()
Upvotes: 0
Reputation: 24590
I have written a script for this.
Place it at the start of your script, and any uninstalled modules will be installed when you run it.
(function () {
var r = require
require = function (n) {
try {
return r(n)
} catch (e) {
console.log(`Module "${n}" was not found and will be installed`)
r('child_process').exec(`npm i ${n}`, function (err, body) {
if (err) {
console.log(`Module "${n}" could not be installed. Try again or install manually`)
console.log(body)
exit(1)
} else {
console.log(`Module "${n}" was installed. Will try to require again`)
try{
return r(n)
} catch (e) {
console.log(`Module "${n}" could not be required. Please restart the app`)
console.log(e)
exit(1)
}
}
})
}
}
})()
Upvotes: 6
Reputation: 36900
Yes, there is a great piece of code called NPM for exactly this: https://npmjs.org/
You specify dependent packages in a package.json
file (see the docs for syntax) and you can use npm install .
to pull them in all at once, and then require
them from your script.
Package.json syntax page: https://docs.npmjs.com/getting-started/using-a-package.json
The first time you install a module, your can provide any number of modules to install, and add the --save
argument to automatically add it to your package.json
npm i --save dnode request bluebird
The next time, someone will execute npm i
it will automatically install all the modules specified in your package.json
Upvotes: 19