365

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?

3
  • use npm run-func stackoverflow.com/a/43598047/696535 Commented Nov 17, 2017 at 16:16
  • 5
    @Pawel I prefer the accepted answer because it doesn't require installing a third party dependency which may either lose support or contain vulnerabilities. It's a risk you run with any dependency, so limiting dependencies to well vetted and maintained ones is always a good idea. Commented Nov 24, 2017 at 3:57
  • You could also use the package npmjs.com/package/invoke-script Commented Jan 5, 2020 at 18:55

17 Answers 17

550

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.

Sign up to request clarification or add additional context in comments.

20 Comments

This was a useful tip for testing some javascript that was running from AWS lambda - thanks
What happens if the function is async?
In case anyone else is trying to do this in their package.json as a npm script, I tried it with the single quotes, and double quotes inside, but it didn't work until I switched them: "start": "node -e \"require('./server')()\"",
Thanks @winhowes for your reply, I just used your example module.exports.init = function () { console.log('hi'); }; And node -e 'require("./db").init()' didn't work for me somehow. I am not sure what I did wrong, but by following your idea, I used module.exports = myFunction, , and then node -e 'require("./myFunction")()' worked for me.
as an augmentation to @AlexHinton's comment, I now use the following to mimick an event and the callback: node -e 'require("./index").handler(require("./fixtures/sample_event_01.json"), {}, console.log)'. The middle {} would be the context, feel free to adjust. Also console.log is a bit primitive but a nice start. Of course you can also write a dedicate CLI.js that in turn require()'s the index.js/handler as stated in other comments.
|
94

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

18 Comments

I was thinking to use eye_mew' suggestion to use make-runnable, but this is a lot better than that, me thinks. Thanks.
this doesn't work for me; $ run-func db.js init bash: run-func: command not found
Thanks to npx, we can do npx run-func file.js functionName without having to install run-func globally. #winning!
You should mention, that you are one of the contributors of package run-func...
npx run-func /path/to/folder/file.js myfunction This worked for me. thanks.
|
80

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

4 Comments

On my Win10 machine, this syntax is simply echoing the script (in either a PowerShell or Command Prompt terminal). Running it directly instead of via 'npm run' throws 'Unexpected token' pointing to the start of the require parameter. I haven't figured out how to make it work yet.
@CalvinDale same here except I can run the script itself in powershell just fine.
On my machine (Windows 10) i had to switch the double- and single-quotes, like this: "myScript": "node -e \"require('./someFile').someFunction()\"" Otherwise Node would just print out the command inside the single-quotes but not evaluate it. Maybe this solves the issues of @CalvinDale and ferr.
What if we want to add an argument to the function call?
38

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.

Comments

30

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

Comments

21

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

5 Comments

For me is enough, and does not force double quotes escapes in package.json scripts
I don't think this is dirty at all. It's simple and explicit and it works. :-)
You have no idea how much you helped me with this idea! Thank you so much!!
This is IMHO the most practical answer
Bonus: this works with both CJS- and ESM-style imports
12

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

Comments

11

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

Comments

10

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

Comments

7

I do a IIFE, something like that:

(() => init())();

this code will be executed immediately and invoke the init function.

3 Comments

But if you run: node init.js and the file contains an IIFE it will work. I think that I didn't fully understand your question. Sorry.
Totally get that, but if the code contains other functions they may or may not be called
You can even simplify it into (init)(); if you want :)
7

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

2 Comments

Not necessary to use npx, can just do ts-node -e 'require("./index.ts").run();'
Npx will provide consistent reproducibility for ts-node unless a global binary of it has been installed.
3

maybe this method is not what you mean, but who knows it can help

index.js

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

command line

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

Comments

2

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.

Comments

2

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

Comments

1

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

2 Comments

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
This is good for running functions in ts files from cmd. It seems that ts-node is behind the scenes working.
-1

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 "[]" {}

Comments

-2

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

5 Comments

Sure, that's how to run a JS file. The question was more aimed at whether I could run a specific function (out of many possible functions) where the only change was to the command line input rather than JS file itself per function call
This is not dealing with the scenario the person is asking for
@jobmo it is, they want to run a method from the cmd line, this does that. ( i got here by googling the question myself, so someone else might appreciate the answer), don't worry there are a diverse set of answers you are allowed to have a choice
Exactly, the question is about running a method from the cmd line. In this answer, myFile.js is executed.That's it. It is no executing any function. It happens then that the file has a function and the function is called inside the file. That was my point.
You just explained that the answer executions the function from the command line :+1:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.