Making Your NPM Package Executable

You’ve probably seen such NPM packages, that you can execute on the shell directly. Let’s take cowsay package for example. If you run npx cowsay Mooo! in your terminal, you’ll see such an output:

Alternatively, you can install this package as a glob…


This content originally appeared on DEV Community and was authored by Orkhan Huseynli

You've probably seen such NPM packages, that you can execute on the shell directly. Let's take cowsay package for example. If you run npx cowsay Mooo! in your terminal, you'll see such an output:

output of running cowsay on terminal which shows ascii cow saying Mooo

Alternatively, you can install this package as a global dependency and then run it:

$ npm install -g cowsay
$ cowsay Mooo!

Shebang

The reason why we can run it in the terminal directly using cowsay command is because its executable file added to our PATH when we installed it with -g flag. You can see where it's located using which command:

$ which cowsay
/usr/bin/cowsay

If you inspect it with long listing format, you'll notice that, it's actually a symbolic link to a JavaScript file:

$ ls -l /usr/bin/cowsay
/usr/bin/cowsay -> ../lib/node_modules/cowsay/cli.js

When we install a package globally on a Linux system, the package will be downloaded into {prefix}/lib/node_modules folder and its bin files will be linked to {prefix}/bin folder. In our case the prefix is just /.

But how does the bash know which interpreter to use to execute this file? Well, if you see the first line of this JavaScript file you'll notice an output as following:

$ head -1 /lib/node_modules/cowsay/cli.js
#!/usr/bin/env node

This line is called hash bang (or shebang) and it is used in scripts to indicate an interpreter for execution under UNIX/Linux operating systems. Simply, this is a directive for the bash that tells it to use indicated interpreter to execute the file.

Let's create a JavaScript file which has no extension and try to execute it using the shell:

$ touch my_script
$ echo "const os = require('os'); console.log(os.cpus().length);" >> my_script
$ chmod u+x my_script
$ ./my_script
./my_script: line 1: syntax error near unexpected token `('
./my_script: line 1: `const os = require('os'); console.log(os.cpus().length);'

If you see these errors, then you're on the right track. The file contains JavaScript code but the shell by default will try to interpret it using /usr/bin/bash interpreter, if you don't believe me, just run bash my_script to get the same results.

To execute this file using Nodejs, we either need to run node my_script or we need to add Shebang line. Let's do the latter. After adding the Shebang, your my_script file should look like mine:

#!/usr/bin/node
const os = require('os');
console.log(os.cpus().length);

You can try running it again as before or you can move this file to /usr/bin directory and try running it directly on your terminal. It will show you the number of logical CPU cores on your machine. For me it is 16:

$ sudo mv my_script /usr/bin/my_script
$ my_script
16

Hi-Mom CLI

Now, let's turn famous hi-mom NPM package to a CLI application. Firsly, let's clone the repository and open it in our editor:

$ git clone https://github.com/tsivinsky/hi-mom.git
$ cd hi-mom && code .

Let's create a cli.js file in the root of the project folder and add the following code as its contents:

#! /usr/bin/node
import { hiMom } from "./index.js";

const name = process.argv[2];
const lang = process.argv[3];

console.log(hiMom(name, lang));

Also add the following line to the package.json file to show NPM where to look for bin files:

...
"bin": "./cli.js",
...

We also need to make sure that this file has execute permission for all users and groups:

$ chmod +x cli.js

Now, if you run npx hi-mom you'll see the desired output:

result of calling npx hi-mom on the terminal which says hi mom

To be able to call it whithout npx, we need to install it globally, hence this package needs to be published to NPM registry. But to keep it simple, we can just create a symbolic link for it. Just run npm link in the root of project folder.

Then you can run it everywhere:

running hi-mom after using npm link on terminal

Conclusion

I hope this article was helpful. If you have any questions or contradictions, please leave a comment and if you liked this post, like and share. Thanks a lot for reading.

References

https://docs.npmjs.com/cli/v9/configuring-npm/package-json#bin
https://docs.npmjs.com/cli/v9/commands/npm-install#global
https://docs.npmjs.com/cli/v9/configuring-npm/folders#description
https://www.baeldung.com/linux/shebang


This content originally appeared on DEV Community and was authored by Orkhan Huseynli


Print Share Comment Cite Upload Translate Updates
APA

Orkhan Huseynli | Sciencx (2023-04-12T21:13:45+00:00) Making Your NPM Package Executable. Retrieved from https://www.scien.cx/2023/04/12/making-your-npm-package-executable/

MLA
" » Making Your NPM Package Executable." Orkhan Huseynli | Sciencx - Wednesday April 12, 2023, https://www.scien.cx/2023/04/12/making-your-npm-package-executable/
HARVARD
Orkhan Huseynli | Sciencx Wednesday April 12, 2023 » Making Your NPM Package Executable., viewed ,<https://www.scien.cx/2023/04/12/making-your-npm-package-executable/>
VANCOUVER
Orkhan Huseynli | Sciencx - » Making Your NPM Package Executable. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/04/12/making-your-npm-package-executable/
CHICAGO
" » Making Your NPM Package Executable." Orkhan Huseynli | Sciencx - Accessed . https://www.scien.cx/2023/04/12/making-your-npm-package-executable/
IEEE
" » Making Your NPM Package Executable." Orkhan Huseynli | Sciencx [Online]. Available: https://www.scien.cx/2023/04/12/making-your-npm-package-executable/. [Accessed: ]
rf:citation
» Making Your NPM Package Executable | Orkhan Huseynli | Sciencx | https://www.scien.cx/2023/04/12/making-your-npm-package-executable/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.