jfkint
jfkint

Reputation: 119

Node.JS: Make module runnable through require or from command line

I have a script setupDB.js that runs asynchronously and is intended to be called from command line. Recently, I added test cases to my project, some of which require a database to be set up (and thus the execution of aforementioned script).

Now, I would like to know when the script has finished doing its thing. At the moment I'm simply waiting for a few seconds after requiring setupDB.js before I start my tests, which is obviously a bad idea.

The problem with simply exporting a function with a callback parameter is that it is important that the script can be run without any overhead, meaning no command line arguments, no additional function calls etc., since it is part of a bigger build process.

Do you have any suggestions for a better approach?

Upvotes: 2

Views: 2271

Answers (3)

Yuriy Rypka
Yuriy Rypka

Reputation: 2107

make-runnable npm module can help with this.

Upvotes: 0

l3l_aze
l3l_aze

Reputation: 613

I was also looking for this recently, and came across a somewhat-related question: "Node.JS: Detect if called through require or directly by command line " which has an answer that helped me build something like the following just a few minutes ago where the export is only run if it's used as a module, and the CLI library is only required if ran as a script.

function doSomething (opts) {
}

/*
 * Based on
 * https://stackoverflow.com/a/46962952/7665043
 */
function isScript () {
  return require.main && require.main.filename === /\((.*):\d+:\d+\)$/.exec((new Error()).stack.split('\n')[ 2 ])[ 1 ]
}

if (isScript) {
  const cli = require('some CLI library')
  opts = cli.parseCLISomehow()

  doSomething(opts)
} else {
  module.exports = {
    doSomething
  }
}

There may be some reason that this is not a good idea, but I am not an expert.

Upvotes: 1

jfkint
jfkint

Reputation: 119

I have now handled it this way: I export a function that does the setup. At the beginning I check if the script has been called from command line, and if so, I simply call the function. At the same time, I can also call it directly from another module and pass a callback.

if (require.main === module) {
// Called from command line
    runSetup(function (err, res) {
        // do callback handling
    });
}

function runSetup(callback) {
     // do the setup
}
exports.runSetup = runSetup;

Upvotes: 1

Related Questions