Determine NPM modules used from a running node.js application - node.js

Other than grabbing the package.json file at the project root is there a way to determine the list of dependencies of a running node.js application? Does node keep this meta information available as some var in the global namespace?

If you are just looking for the currently installed npm packages in the application directory, then you can install the npm package (npm install -g npm) and programatically invoke ls to list the installed packages and the dependency trees.
Obviously, this has no bearing on whether the installed packages are actually require'd in the application or not.
Usage is not that well documented but this should get you started.
var npm = require('npm');
npm.load(function(err, npm) {
npm.commands.ls([], true, function(err, data, lite) {
console.log(data); //or lite for simplified output
});
});
e.g.:
{ dependencies:
{ npm: { version: '1.1.18', dependencies: [Object] },
request: { version: '2.9.202' } } }
Otherwise, I believe the only other option is to introspect the module module to get information pertaining to the currently loaded/cached module paths. However this definitely does not look to have been developed as a public API. I'm not sure if there are any alternatives so would be keen to hear if there are e.g.
var req = require('request'); // require some module for demo purposes
var m = require('module');
// properties of m contain current loaded module info, e.g. m._cache

I believe you could use require-analyzer, which sort of works according to Isaacs(could miss some). You could hear this in Nodeup's first podcast from 11:55.
Or you could try James node-detective which probably will find your dependencies better(but not by running code), but because of Javascript dynamic nature(12:46).
detective
Find all calls to require() no matter how crazily nested using a
proper walk of the AST.
P.S: to expose those package.json variables to node.js you could use node-pkginfo

Related

Node.js Dependencies as Singletons

I am trying to create my own npm package my-package that relies on a dependency dependency-a and is used in some project cool-project that relies on both my-package and dependency-a.
cool-project
- dependency-a
- my-package
- dependency-a
dependency-a:
export const someVar = 0;
my-package:
import depA from 'dependency-a'
const someFun = () => {
depA.someVar = 1;
}
cool-project:
import depA from 'dependency-a';
import myPackage from 'my-package';
myPackage.someFun();
console.log(depA.someVar); // expected (desired) 1, actual 0
The above would work if myPackage was a module apart of cool-project, however since I want my-package to be a standalone npm module, when I try to link it in cool-project it seems to be relying on a separate version of dependency-a.
Is there a way to create an npm module that can modify a singleton of a third party library, and share that across two modules relying on it automagically. I am using babel/webpack to build my-package so if there is a way to do it through that, then that works for me too!
Side note: I know that I could do something like return depA from my-package--this is not workable for what I need to do. I'm trying to use a version of this example to create a connection middleware for a database.
Add dependency-a as a peer dependency in my-package's package.json file,
"peerDependencies": {
"dependency-a": "1.x"
}
Now, when installing my-package, dependency-a won't be installed automatically if there is another dependency-a (with same version you declared) installed in cool-project.

How to include dependencies in J2V8

How to include dependencies in J2V8? I would like to use certain dependencies in the javascript file for instance the crypto package.
var crypto = require('crypto');
function foo(){ return crypto.createHash('md5').update('Apple').digest("hex");}
However, I got the following error saying require keyword is undefined.
undefined:1: ReferenceError: require is not defined
var crypto = require('crypto');
^
ReferenceError: require is not defined at <anonymous>:1:14
com.eclipsesource.v8.V8ScriptExecutionException
at com.eclipsesource.v8.V8._executeVoidScript(Native Method)
Can anyone tell me how to import an package into J2V8?
Unless you're working with Node, require is not a feature. Usually, you want to use a bundler like webpack to pack your structured source code into one large file so that it can be understood by browsers. This way you can use require and npm packages for your frontend code, which makes development easier, and a bundler turns it with every build (or live update) into a different format, that's hard to read for humans, but is valid Javascript.
I have had success using node modules in J2v8, please check out this blog :http://eclipsesource.com/blogs/2016/07/20/running-node-js-on-the-jvm/
NodeJs nodeJS = NodeJs.createNodeJs();
After registering callbacks
nodeJs.exec(File thescripttoexecute)
Make sure you have the proper path to the node modules in the require() command.
You may have to make a nodejs package that takes dependencies and exports what you need. Then, You have to execute npm install manually.
or You can just npm install what-you-need.
Create Node JS Runtime, and use require with your your-package-dir/index.js or exact location of module that you need. like this:
V8Object module = nvm.require(file);
Now you can call the function likes:
module.executeJSFunction("test");
To deliver entire dependencies you have to bundlize module directory your self.
What if you have to support cross-platform, refer https://www.npmjs.com/package/node-pre-gyp also.

Yeoman generator composeWith

I am building a generator which uses another sub-generator, using composeWith.
I installed my generator using npm install -g generator-my-generator. When running the generator complains that I do not have my sub-generator installed.
My problem is that I don't want to install the sub-generator globally. I tried using it as a dependency / peerDependency (as suggested here), but it did not help.
Is it possible?
You need to provide the path in composeWith third argument:
this.composeWith('generator:name', {}, {
local: require.resolve('generator-foo/generators/name')
});
require.resolve is usually your best bet, but some generators (like generator-node) provide all the paths inside the main module so you don't have to know the package structure.

Use a node module from casperjs

Is it possible to install a node module, installed via npm, and then require it from a casperjs script?
(I see lots of posts and tools for running casper or phantom from inside node.js, but that is not what I'm trying to do.)
The casperjs docs seem to say it is possible, but only show with hand-written toy modules that don't really do anything. The real-world module I'm trying to install is imap, but at this point I cannot get any module to work, even built-in ones like net. Simple example:
npm install imap
echo "var test = require('imap');" > test.js
casperjs test.js
Gives me:
CasperError: Can't find module imap
/usr/local/src/casperjs/bin/bootstrap.js:263 in patchedRequire
test.js:1
(I can see the imap module from npm ls, and I can use it fine from a node.js script.)
Or alternatively with a built-in module:
echo "var test = require('net');" > test.js
casperjs test.js
Complains "Can't find module net"
I have npm --version of 1.4.14 and nodejs --version of v0.10.29. Are either of those too old, I wonder? (Casper is 1.1.0-beta, and Phantom is 1.9.7, both of which are the latest versions.)
PhantomJS and SlimerJS (the engines that are used for CasperJS) are not Node.js modules. They can be installed through npm for convenience. They have a different base infrastructure of modules which is distinct from Node.js.
You will not be able to use imap or any module that depends on the net module. As Fanch points out, there are modules that can work inside the phantomjs runtime.
If a module only uses some functionality of some native node.js module, you could try to change the implementation to use the API that phantomjs provides. I don't think this is easy though. Most of the time you will run into a wall.
In the case of imap, it is pretty hopeless. You cannot even re-implement the require("net").Socket, because WebSockets are not supported in phantomjs (at least in 1.9.7).
Here an example with the colors module :
var colors = require('colors');
casper.test.begin('\n*Colors module*\n', function suite(test) {
casper.start()
.thenOpen('https://www.google.fr/', function() {
console.log("test require\n".zebra);
console.log("test require\n".rainbow);
console.log("test require\n".red.underline.bold);
})
.run(function() {
test.done();
});
});
node-modules
colors
testnode.js
casperjs test testnode.js
output :
It seems it's not as simple when the required module has dependencies.
In my case, I wanted to load underscorejs. Underscore is a series of functions and don't have complicated interactions with javascript objects, so there is no problem just requiring the javascript file and then having access to its functions.
I started by finding the root to my nodejs installation (from the CLI):
node --help
Which led me to finding my node path:
echo $NODE_PATH
Which was at:
/usr/local/lib/node_modules/
Underscore was at
/usr/local/lib/node_modules/underscore/underscore.js
So my final require statement in my CasperJS script was.
var _ = require('/usr/local/lib/node_modules/underscore/underscore.js');
Now in my script I test to see if underscorejs is loaded:
this.echo(_.now());
And I see the current time.
CAVEAT: Since this is running asynchronously, if you put your _.now() statement right after the require, it will give you an undefined object error. As a note, I'm using Casper 1.1, which uses PhantomJS's native require() function. If you are using < Casper 1.1, I don't think require will work.
UPDATE:
Since this is the case, I use CasperJS then() function to load my utilities synchronously, making sure to declare my variables within the global scope. Here's how that looks:
//at the top of the file-ish, declare variables that will hold loaded libraries.
var utils, _;
var casper = require('casper').create(); //create casper
casper.start('http://example.com'); //start casper at URL.
casper.then(function loadRequires(){ //load the requirements
utils = require('utils', function(){this.echo('utils loded')});
_ = require('/usr/local/lib/node_modules/underscore/underscore.js');
});
casper.then(function myAwesomeStuff() {
this.echo(_.now()); //now, access the loaded requirements
utils.dump('this stuff is soooo awesome!!!!!!!!!!!!!!!!!!!!');
//do stuff on the page you opened in the start function here.
);
});
You can read more about the Casper prototype and the then() method at the API docs: http://casperjs.readthedocs.org/en/latest/modules/casper.html#casper-prototype

Can I access locally-installed packages from a globally-installed package?

I don't know if I've worded the question properly, so I apologize if it isn't clear from the title what I mean.
Say I have an NPM package which installs an executable. Presumably I want users to install this package with the -g flag so that they can run it whenever.
In this case, when I call require() from within the executable, it will look for packages installed globally.
But suppose this package provides generic functionality for Node projects. I might want to know which packages the current project has installed locally. Should I just assume:
path.join(process.cwd(), 'node_modules')
Or is there a more "correct" way to set the NODE_PATH in this case? (Or rather than set NODE_PATH, should I just require(absolute_path_to_file)?)
require will not only lookup the package inside $(CWD)\node_modules but also inside all node_modules of parent, grandparent, etc. So you can use resolve on npm to solve this problem
FILE: your_global_command.js
// npm install resolve
var resolve = require('resolve').sync;
// Lookup for local module at current working dir
function require_cwd(name) {
var absolute_path = resolve(name, { basedir: process.cwd() });
return require(absolute_path);
}
// Load local express
// this will throw an error when express is not found as local module
var express = require_cwd('express');
I also create a package to require a package at current-working-dir (instead of __dirname of module):
https://npmjs.org/package/require-cwd

Resources