Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run node.js cli with experimental-specifier-resolution=node?

Tags:

node.js

yargs

Our team has built a small CLI used for maintenance. The package.json specifies a path for with the bin property, and everything works great; "bin": { "eddy": "./dist/src/cli/entry.js"}

Autocompletion is achived by using [email protected]. However we recently converted the project to use es6 modules, because of a migration to Sveltekit, i.e. the package.json now contains type: module. Because of this, the CLI now only works if we run with:

what works

node --experimental-specifier-resolution=node ./dist/src/cli/entry.js help

However, if we run this without the flag, we get an error "module not found":

Error [ERR_MODULE_NOT_FOUND]: Cannot find module...

So the question is

Can we somehow "always" add the experimental-specifier-resolution=node to the CLI - so we can continue to use the shorthand eddy, and utilize auto completion?

like image 779
DauleDK Avatar asked Jun 24 '21 07:06

DauleDK


People also ask

What is ESM in node JS?

ECMAScript modules, also known as ESM, is the official standard format to package JavaScript, and fortunately Node. js supports it 🎉.

Can I use ES6 modules in node JS?

The syntax for importing modules in ES6 looks like this. The reason for this error is that Node js doesn't support ES6 import directly. If you try to use import for importing modules directly in node js it will throw out that error.

Why should I Write my CLI in Node JS?

One of the reasons why Node.js got so popular is the rich package ecosystem with over 900,000 packages in the npm registry. By writing your CLIs in Node.js you can tap into this ecosystem including it's big amount of CLI-focused packages.

How do I run a node Program in shell script?

The usual way to run a Node.js program is to run the globally available node command (once you install Node.js) and pass the name of the file you want to execute. If your main Node.js application file is app.js, you can call it by typing: Above, you are explicitly telling the shell to run your script with node.

What is the extension of the MJS file in Node JS?

The file has an .mjs extension. The file does not have a .cjs extension, and the nearest parent package.json file contains a top-level "type" field with a value of "module". Otherwise, the file is loaded using the CommonJS module loader.

How to install and run nodemon locally?

This local installation of nodemon can be run by calling it from within npm script such as npm start or using npx nodemon. Run the application using the nodemon command followed by the application's file name:


Video Answer


1 Answers

There are two probable solutions here.

Solution 1

Your entry.js file should start with a shebang like #!/usr/bin/env node. You cannot specify the flag directly here, however, if you could provide the absolute path to node directly in the shebang, you can specify the flag.

Assuming you have node installed in /usr/bin/node, you can write the shebang in entry.js like:

#!/usr/bin/node --experimental-specifier-resolution=node

(Use which node to find the absolute path)

However, this is not a very portable solution. You cannot always assume everyone has node installed in the same path. Also some may use nvm to manage versions and can have multiple version in different path. This is the reason why we use /usr/bin/env to find the required node installation in the first place. This leads to the second solution.

Solution 2

You can create a shell script that would intern call the cli entry point with the required flags. This shell script can be specified in the package.json bin section.

The shell script (entry.sh) should look like:

#!/usr/bin/env bash
/usr/bin/env node --experimental-specifier-resolution=node ./entry.js "$@"

Then, in your package.json, replace bin with:

"bin": { "eddy": "./dist/src/cli/entry.sh"}

So when you run eddy, it will run the entry.js using node with the required flag. The "$@" in the command will be replaced by any arguments that you pass to eddy.

So eddy help will translate to /usr/bin/env node --experimental-specifier-resolution=node ./entry.js help

like image 171
Vivek Avatar answered Oct 23 '22 16:10

Vivek