Reputation: 8065
I'm writing a web app in Node. If I've got some JS file db.js
with a function init
in it how could I call that function from the command line?
Upvotes: 361
Views: 353250
Reputation: 11
If you're running node from command line, you can use eval
(yeah I know it's not recommended but honestly there's no risk here). I personally put "fn_" at the front to distinguish function calls, but you can just skip the if
statement (and the string replace
) entirely if you wish to.
// callFromScript.js
let args = process.argv.slice(2);
if (args[0].startsWith("fn_")) {
let methodName = args[0].replace("fn_", "");
let methodArgs = args.slice(1);
methodArgs.forEach((arg, index) => {
let isObjectLike = arg.startsWith('{') || arg.startsWith('[');
if (!isObjectLike && isNaN(arg)) {
methodArgs[index] = `"${arg}"`;
}
});
let methodSyntax = `${methodName}(${methodArgs.join(',')})`;
console.log(methodSyntax);
try {
eval(methodSyntax);
} catch (error) {
throw error;
}
}
function test() {
console.log("Success");
}
function testArgs(a1, a2, a3, a4) {
console.log(a1, a2, a3, a4);
}
node callFromScript.js fn_test
node callFromScript.js fn_testArgs 1 text "[]" {}
Upvotes: -1
Reputation: 1714
You can also run TypeScript with ts-node
similar to @LeeGoddard answer.
In my case, I wanted to use app
and init
separately for testing purposes.
// app.ts
export const app = express();
export async function init(): Promise<void> {
// app init logic...
}
// commonjs
npx ts-node -e 'require("./src/app").init();'
// esmodule
npx ts-node -e 'import("./src/app").then(a => a.init());'
Upvotes: 7
Reputation: 385
Following on from the other answers here, if you wanted to make this reusable you could create a script as follows:
// rn-fn.js
const [, , filePath, fn, ...args] = process.argv;
import(filePath).then((mod) => mod[fn](...args));
Then as an example:
// hello.js
export function hello(str) {
console.log(`hello ${str}`)
}
Running:
node ./rn-fn.js ./hello.js hello world
at the command line should then return
hello world
Upvotes: 1
Reputation: 11173
No comment on why you want to do this, or what might be a more standard practice: here is a solution to your question.... Keep in mind that the type of quotes required by your command line may vary.
In your db.js
, export the init
function. There are many ways, but for example:
module.exports.init = function () {
console.log('hi');
};
Then call it like this, assuming your db.js
is in the same directory as your command prompt:
node -e 'require("./db").init()'
If your db.js
were a module db.mjs
, use a dynamic import to load the module:
node -e 'import("./db.mjs").then( loadedModule => loadedModule.init() )'
To other readers, the OP's init
function could have been called anything, it is not important, it is just the specific name used in the question.
Upvotes: 547
Reputation: 12545
Updated for 2022 - If you've switched to ES Modules, you can't use the require tricks, you'd need to use dynamic imports:
node -e 'import("./db.js").then(dbMod => dbMod.init());'
or with the --experimental-specifier-resolution=node flag:
node --experimental-specifier-resolution=node -e 'import("./db").then(dbMod => dbMod.init());'
Upvotes: 10
Reputation: 10410
If you want to include environment variables from your .env files, you can use env-cmd
:
npx env-cmd node -e 'require("./db").init()'
If you want run a specific function in the file too, use run-func
:
npx env-cmd npx run-func db.js init someArg
Or, to provide an argument for the accepted answer you'd have to do something like:
npx env-cmd node -e 'require("./db").init(someArg)'
Writing/updating an expression here is less explicit (so easier to miss when you're checking back, for example) than providing different arguments to the commands, so I recommend using env-cmd
with run-func
.
Note: I also usually add --experimental-modules
on the end when necessary.
Upvotes: 2
Reputation: 19
Inspired by https://github.com/DVLP/run-func/blob/master/index.js
I create https://github.com/JiangWeixian/esrua
if file index.ts
export const welcome = (msg: string) => {
console.log(`hello ${msg}`)
}
just run
esrua ./index.ts welcome -p world
will output hello world
Upvotes: 1
Reputation: 9133
Try make-runnable.
In db.js, add require('make-runnable');
to the end.
Now you can do:
node db.js init
Any further args would get passed to the init
method, in the form of a list or key-value pairs.
Upvotes: 38
Reputation: 2042
maybe this method is not what you mean, but who knows it can help
const arg = process.argv.splice(2);
function printToCli(text){
console.log(text)
}
switch(arg[0]){
case "--run":
printToCli("how are you")
break;
default: console.log("use --run flag");
}
and run command node . --run
probuss-MacBook-Air:fb_v8 probus$ node . --run
how are you
probuss-MacBook-Air:fb_v8 probus$
and you can add more arg[0] , arg[1], arg[2] ... and more
for node . --run -myarg1 -myarg2
Upvotes: 3
Reputation: 18212
Update 2020 - CLI
As @mix3d pointed out you can just run a command where file.js
is your file and someFunction
is your function optionally followed by parameters separated with spaces
npx run-func file.js someFunction "just some parameter"
That's it.
file.js
called in the example above
const someFunction = (param) => console.log('Welcome, your param is', param)
// exporting is crucial
module.exports = { someFunction }
More detailed description
Run directly from CLI (global)
Install
npm i -g run-func
Usage i.e. run function "init", it must be exported, see the bottom
run-func db.js init
or
Run from package.json script (local)
Install
npm i -S run-func
Setup
"scripts": {
"init": "run-func db.js init"
}
Usage
npm run init
Params
Any following arguments will be passed as function parameters init(param1, param2)
run-func db.js init param1 param2
Important
the function (in this example init
) must be exported in the file containing it
module.exports = { init };
or ES6 export
export { init };
Upvotes: 92
Reputation: 4948
Sometimes you want to run a function via CLI, sometimes you want to require
it from another module. Here's how to do both.
// file to run
const runMe = () => {}
if (require.main === module) {
runMe()
}
module.exports = runMe
Upvotes: 28
Reputation: 612
I do a IIFE, something like that:
(() => init())();
this code will be executed immediately and invoke the init function.
Upvotes: 7
Reputation: 15653
As per the other answers, add the following to someFile.js
module.exports.someFunction = function () {
console.log('hi');
};
You can then add the following to package.json
"scripts": {
"myScript": "node -e 'require(\"./someFile\").someFunction()'"
}
From the terminal, you can then call
npm run myScript
I find this a much easier way to remember the commands and use them
Upvotes: 79
Reputation: 3578
This one is dirty but works :)
I will be calling main()
function from my script. Previously I just put calls to main at the end of script. However I did add some other functions and exported them from script (to use functions in some other parts of code) - but I dont want to execute main() function every time I import other functions in other scripts.
So I did this, in my script i removed call to main(), and instead at the end of script I put this check:
if (process.argv.includes('main')) {
main();
}
So when I want to call that function in CLI: node src/myScript.js main
Upvotes: 20
Reputation: 76458
If your file just contains your function, for example:
myFile.js:
function myMethod(someVariable) {
console.log(someVariable)
}
Calling it from the command line like this nothing will happen:
node myFile.js
But if you change your file:
myFile.js:
myMethod("Hello World");
function myMethod(someVariable) {
console.log(someVariable)
}
Now this will work from the command line:
node myFile.js
Upvotes: -2
Reputation: 4688
simple way:
let's say you have db.js file in a helpers directory in project structure.
now go inside helpers directory and go to node console
helpers $ node
2) require db.js file
> var db = require("./db")
3) call your function (in your case its init())
> db.init()
hope this helps
Upvotes: 11
Reputation: 533
If you turn db.js
into a module you can require it from db_init.js
and just: node db_init.js
.
db.js:
module.exports = {
method1: function () { ... },
method2: function () { ... }
}
db_init.js:
var db = require('./db');
db.method1();
db.method2();
Upvotes: 10