Directly call globally installed Node.js modules - node.js

Supposed I want to write a module for Node.js that shall be installed globally. I do not want to write any C++ (or something else), but plain Node.js code.
Basically, this is very easy. Just write the module, and install it using npm install -g.
Now, most globally installed modules provide the possibility to call them directly, e.g. you can type express at your command prompt and run the globally installed application bootstrapper of Express.
Now my question is: How do I achieve this?
If I simply install a module globally, this does not make one of the files available as an executable, or puts that file onto the PATH.
What steps do I need to do in order to achieve this?
So my question is basically: What steps need to be done to create globally available executable out of a "normal" Node.js module?

You need to write an executable file. This is what will be executed when a user types your command. Here's an example taken from JSHint:
#!/usr/bin/env node
require("./../src/cli/cli.js").interpret(process.argv);
Convention says to place this file in a bin directory in the root of your project. You then just need to update your package.json file to tell it where to find your executable:
{
"bin": {
"jshint": "./bin/jshint"
}
}
In this case, the executable file can be run from the terminal with the jshint command. When it runs, it simply requires another file and calls a method in it, passing through any command line arguments.

Related

Distribute a binary executable with a nodejs module when publishing to npmjs.com

I have an executable file myutil.exe which I call from my nodejs module to perform some functions.
I wish to package this up, publish my NodeJS module to npmjs.com and and the executable should be part of this nodejs library when used on this windows platform, since my nodejs code calls the executable to perform a function. I run this command line binary from nodejs already.
How to do this and how best to include this executable binary in this? should it be hosted outside of the package somehow?
Also note, its just a restriction, at this moment it must be an executable on windows, or an runnable binary on Linux systems due to the nature of the code inside of it, cannot be a DLL/library. Later perhaps I can move some of its code into a DLL/library.
supply a bin field in your package.json which is a map of command name to local file name. On install, npm will symlink that file into prefix/bin for global installs, or ./node_modules/.bin/ for local installs.
For example, if you have this in the package.json, and installed your package globally, the command npmputty will be available in the PATH.
"bin": {
"npmputty": "./bin/putty.exe"
},
If you prefer to not release this executable in the package, it is possible to implement a postinstall script to download it from somewhere like github.com.
{
"scripts" : {
"postinstall" : "scripts/download_from_github.js"
}
}

Finding node module from different directory?

Always feel stupid asking here because people are always confused with my questions, or I have a dumb problem, but, I'm working on a program in node.js and the text editor I'm using (NP++) doesn't seem to like to save files in the system32 directoy, (The directory where my modules are), and that is where my script is as well. (So I have .../.../node_modules/(modules) and .../.../node_modules/script.js) this becomes a pain when I want to edit the script, I have to clone the script to my desktop, then edit it, then overwrite the one in the node_modules directory. I tried saving the script to my desktop and running it, but it just gives me an error of module not found. (In my script I have the modules as var example = require('example.js')) Is there any way I can get it to get the modules from the node_modules directory, while keeping the script file somewhere easily accessible and editable? (i.e desktop?) (Sorry if this is confusing, not the best at these kind of things)
I'm not 100% sure that this is what's happening because I haven't used npm on Windows, but it sounds to me like you're installing your dependencies globally using npm -g. The more proper way to use Node is to install your dependencies locally, using npm without the -g flag. That way your dependencies get installed in your current working directory.
For example, let's say you've saved your project in a directory on your Desktop, and your script uses require("lodash"). If you cd to your directory and run npm install lodash, then the lodash module will be available to your script.

NPM - Conditional additions to global path

In a Node package.json file, you can map multiple executables to the PATH environmental variable on a global NPM install (npm install -g):
"bin": {
"foo": "./bin/foo.js",
"bar": "./bin/bar.js"
},
I have a unique project that requires mapping existing PATH variables on Operating Systems that do not have it. For example, I want to add a command named grep to PATH, if and only if it is being installed on a Windows computer. If the computer is running any other OS, the NPM installation will obviously fail.
Is there any way to run logic that pre-determines what bin options are available in the installation?
Oh snap - I just had an idea!
Would this work:
Parent module has npm (programmatic version) as a dependency.
On global installation, run a post-install script as declared in the package.json of parent module.
Post-install script does a check on the system to see which commands exist. This would be more mature than "Windows or not Windows" - it would try to exec a list of commands and see which ones fail.
For every command that doesn't exist, post-install script programmatically runs npm install -g on all sub-modules (one for each command, such as grep).
This would take a while and the npm module is huge, but it seems like it would work. No?
There doesn't seem to be a way to do this directly through package.json, but it might be possible (and desirable) to do something like:
Make a separate npm module for each executable you want to register (eg my-win-grep).
In the my-win-grep module, implement the executable code you want to run, and register the PATH/executable value in this module.
In the package.json for my-win-grep, include an os field that limits it to installing on windows.
In your original module, list my-win-grep as an optionalDependency.
In this way, if someone installs your original module on Windows, it would install my-win-grep, which would register an executable to run under the grep command.
For users on other systems, the my-win-grep module would not install because of the os requirement, but the main module would continue to install because it ignores failures under optionalDependencies. So the original grep executable would remain untouched.
Updated question
This approach does sound like it should work - as you say, the npm dependency is pretty large, but it does avoid having to preform additional symlinking, and still has the benefit outlined above of having each piece of OS specific functionality in a separate module.
The only thing to watch for, possibly, in the programmatic npm docs:
You cannot set configs individually for any single npm function at
this time. Since npm is a singleton, any call to npm.config.set will
change the value for all npm commands in that process
So this might just mean that you can't specify -g on your installs, but instead would have to set it globally before the first install. This shouldn't be a problem, but you'll probably need to test it out to find out exactly.
Lastly...
You might also want to have a look at https://github.com/lastboy/package-script - even if you don't use it, it might give you some inspiration for your implementation.

Create shell executable Global node module

I tried to create node module, I succeeded,
I used npm install -g at code directory, and it created this module folder in \AppData\Roaming\npm\node_modules\myfirstmodule, Now I want to make one file executable as command, like pm2. How can I do this? so I can type myfirstmodule in command prompt at any location and it will execute index.js from that module.
Your package.json can provide a map called bin which will make commands available. See this tutorial for more details.

Writing a Go program that acts as an executable as well as a module

I am currently trying to do my first steps in Go. Now I've ported a tool that I once written in Node.js, and I was surprised how easy that was, and how clean and concise the code is.
Anyway, I've got a question that I was not able to figure out by myself so far: In Node.js it's possible to add the main entry as well as the bin entry to the package.json file. This basically means that you can create a module that works as a executable when installed using
$ npm install -g <module>
but as a library when installed using
$ npm install <module>
The trick here is that the first one uses the bin entry, which then internally uses a file from the module's lib folder, but the second version directly points to this lib file.
So ... now I would like to have the same behavior in Go: I would like to write a package that you can directly run as an executable, but that as well you can import into another application as a library. How would I do that?
Obviously I can't put two calls to package into a .go file. Any hints?
What about the solution in the following blog post? http://dan.munckton.co.uk/blog/2013/06/21/go-lang-packaging-creating-a-library-that-bundles-an-executable/

Resources