node_modules path programmatically - node.js

I am using protractor and I want to get programmatically the npm node_modules path from the global system.
For example my selenium jar is installed here:
C:/Users/myuser/AppData/Roaming/npm/node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.7.1.jar
and I wanted to get
C:/Users/myuser/AppData/Roaming/npm/node_modules/
or
C:/Users/myuser/AppData/Roaming/npm/node_modules/protractor/node_modules/
I wrote this small script, which will look for my jar in the paths
var path = require('path');
var fs = require('fs');
var paths = path.getModulePaths()
for (i=0;i<paths.length;i++) {
file = path.join(paths[i],'webdriver-manager','selenium','selenium-server-standalone-3.7.1.jar')
if (fs.existsSync(file)) {
var seleniumServerJar = file
continue
}
}
here I supposed that this function is available
var paths = path.getModulePaths()
but it's not. I used to write an equivalent in Python, which is:
import sys
print sys.path

I guess you are expecting to start a webdriver manager programatically. Try below code:
var pkgPath = require.resolve('protractor');
var protractorDir = path.resolve(path.join(path.dirname(pkgPath), '..', 'bin'));
var webdriverManagerPath = path.join(protractorDir, '/' + 'webdriver-manager'));

Related

Get cordova package name from javascript hook

I am writing a cordova plugin with a node hook to run after_prepare .
This is for Android only.
From within this hook I need to get the cordova package name, so I can copy a file to the src/com/example/myproject folder (if the package is com.example.myproject).
If I know the package name I can make this path. I have it working hardcoded now but I need this to work with two different package names.
Is there a way to get the package name from within this code in the plugin hook?
module.exports = function(ctx){
var fs = ctx.requireCordovaModule('fs');
var path = ctx.requireCordovaModule('path');
var deferral = ctx.requireCordovaModule('q').defer();
//get package name here
//do other stuff
}
I have done a lot of research but have not been able to find this.
Thanks.
It doesn't look like it is available off of the context object, but you could try to parse the config.xml.
module.exports = function(context) {
var fs = require('fs');
var path = require('path');
var config_xml = path.join(context.opts.projectRoot, 'config.xml');
var et = context.requireCordovaModule('elementtree');
var data = fs.readFileSync(config_xml).toString();
var etree = et.parse(data);
console.log(etree.getroot().attrib.id);
};
The local-webserver plugin uses a similar strategy for reading config properties.
Here my compilation from different answers that works in 2021.
I use it to update some parameters in Xcode project for plugins compilation.
You can see that I am getting here app id and name from config.xml
And you can add it to after_prepare hook:
<hook src="scripts/addBuildSettingsToXcode.js" type="after_prepare" />
#!/usr/bin/env node
let fs = require('fs');
let xcode = require('xcode');
let path = require('path');
let et = require('elementtree');
module.exports = function (context) {
//console.log(context);
function addBuildPropertyToDebugAndRelease(prop, value) {
console.log('Xcode Adding ' + prop + '=' + value);
myProj.addBuildProperty(prop, value, 'Debug');
myProj.addBuildProperty(prop, value, 'Release');
}
function updateBuildPropertyToDebugAndRelease(prop, value) {
console.log('Xcode Updating ' + prop + '=' + value );
myProj.updateBuildProperty(prop, value, 'Debug');
myProj.updateBuildProperty(prop, value, 'Release');
}
// Getting app id and name from config.xml
let config_xml = path.join(context.opts.projectRoot, 'config.xml');
let data = fs.readFileSync(config_xml).toString();
let etree = et.parse(data);
let appId = etree.getroot().attrib.id ;
let appName = etree.getroot().find('name')['text'];
// Building project path
let projectPath = 'platforms/ios/' + appName + '.xcodeproj/project.pbxproj';
// Opening Xcode project and parsing it
myProj = xcode.project(projectPath);
myProj = myProj.parseSync();
// Common properties
addBuildPropertyToDebugAndRelease('DEVELOPMENT_TEAM', 'CGXXXXXXX');
addBuildPropertyToDebugAndRelease('CODE_SIGN_IDENTITY', '"Apple Development"');
// Compilation properties
addBuildPropertyToDebugAndRelease('ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES', 'YES');
// Save project file
fs.writeFileSync(projectPath, myProj.writeSync());
};

Check package version at runtime in nodejs?

I have some of my entries in package.json defined as "*"
"dependencies": {
"express": "4.*",
"passport": "*",
"body-parser": "*",
"express-error-handler": "*"
},
I wan't to freeze those values to the current version. How can I know what version my packages are at run time? I don't mind checking one by one since I don't have many of them :)
BTW: I cannot do npm list --depth=0 because I cannot access the vm directly (PaaS restriction), just the logs.
You can use the fs module to read the directories in the node_modules directory and then read package.json in each of them.
var fs = require('fs');
var dirs = fs.readdirSync('node_modules');
var data = {};
dirs.forEach(function(dir) {
try{
var file = 'node_modules/' + dir + '/package.json';
var json = require(file);
var name = json.name;
var version = json.version;
data[name] = version;
}catch(err){}
});
console.debug(data['express']); //= 4.11.2
Just in case if you need the version on the front-end, there is an npm package just for this and it can be used both on client-side and server-side.
global-package-version
You can use it in your code like this
import globalPackageVersion from 'global-package-version';
// package name is 'lodash'
globalPackageVersion(require('lodash/package.json'));
// You can type 'packageVersion' in browser console to check lodash version
// => packageVersion = { lodash: '4.7.2'}
packageVersion becomes a global object when used in server side and becomes a window object when used on the client side. Works well with webpack and all other bundling tools.
Disclaimer: I am the author of this package :)
I've 'modernised' a bit #laggingreflex answer, this works on ES6+, node 10, tested on a lambda running in aws. It's an endpoint from an express app.
const fs = require("fs");
module.exports.dependencies = async (_req, res) => {
const dirs = fs.readdirSync("./node_modules");
const modulesInfo = dirs.reduce((acc, dir) => {
try {
const file = `${dir}/package.json`;
const { name, version } = require(file);
return { ...acc, [name]: version };
} catch (err) {}
}, {});
res.status(200).json(modulesInfo);
};
The accepted solution can be improved upon in both terms of performance and stability:
1: the package name IS THE directory. In typically cases where you are looking for a specific package, you do not need to load every module.
2: this code will not run on all os due to the way the paths are formed
3: using require means the path needs to be relative to the current file (this would only work if your file is located at the top of your project folder & along side node_modules). In most cases, using readFile or readFileSync is a easier approach.
const fs = require('fs');
const path = require('path');
const dirs = fs.readdirSync('node_modules');
const data = {};
//add ones you care about
const trackedPackages = ['express', 'passport', 'body-parser'];
dirs.forEach(function(dir) {
if(trackedPackages.indexOf(dir) > -1){
try{
const json = JSON.parse(
fs.readFileSync(path.join('node_modules', dir, 'package.json'), 'utf8')
);
data[dir] = json.version;
}catch(e){
console.log(`failed to read/parse package.json for ${dir}`, e);
}
}
});
console.debug(data['express']); //= 4.11.2

How do I get the ‘program name’ (invocation location) in Node.js?

I want the equivalent of $PROGRAM_NAME in Ruby, or ARGV[0] in C-likes, for Node.js. When I have a Node script that looks something like this,
#!/usr/bin/env node
console.log(process.argv[0])
… I get “node” instead of the name of the file that code is saved in. How do I get around this?
You can either use this (if called from your main.js file):
var path = require('path');
var programName = path.basename(__filename);
Or this, anywhere:
var path = require('path');
var programName = path.basename(process.argv[1]);
Use __filename? It returns the currently executing script.
http://nodejs.org/docs/latest/api/globals.html#globals_filename
For working with command line option strings check out the optimist module by Substack. Optimist will make your life much easier.
var inspect = require('eyespect').inspector();
var optimist = require('optimist')
var path = require('path');
var argv = optimist.argv
inspect(argv, 'argv')
var programName = path.basename(__filename);
inspect(programName, 'programName')
To install the needed dependencies:
npm install -S eyespect optimist

Meteor project path from a smartpackage

I was looking for a way to look up the meteor project path from a smart package (e.g.: obtain the path of the directory where the .meteor folder is ...).
I was not able to do it using node's __dirname and __filename because somehow in meteor they are not avaiable.
Any tips ?
As of Meteor 0.6.0 this would be:
var path = Npm.require('path');
var basepath = path.resolve('.');
From a smartpackage (0.6.5+):
var path = Npm.require('path');
var base = path.resolve('.');
base in this case gets you the position of your package ..
/User/username/projects/project/.meteor/local/programm/server/...
.. might even be deeper
but we want
/User/username/projects/project/
.. so split at .meteor
base = base.split('.meteor')[0];
Or as two-liner
var path = Npm.require('path');
var base = path.resolve('.').split('.meteor')[0];;
This works for me in Meteor 0.5.0:
var require = __meteor_bootstrap__.require;
var path = require('path');
var basepath = (path.resolve('.'));
You can actually get access to node:
var __dirname = __meteor_bootstrap__.__dirname;
You could try (only on server side)
process.env.PWD which returns something like that for me (OSX):
'/Users/myusername/Desktop/myproject'
With that command you get the root of meteor project.

Retrieving files from Directory Node Js

I am using readDirSync to get the files from a Diretory. PLease find the code and error as following.
var fs = require('fs');
var files = fs.readdirSync('./application/models/');
for(var i in files) {
var definition = require('../application/models/'+files[i]).Model;
console.log('Model Loaded: ' + files[i]);
}
I am getting error for line number 2 .
ENOENT, No such file or directory './application/models/' at Object.readdirSync (fs.js:376:18)
I have application/models on the same dir. I already checked for '/application/models/' and
'application/models/' but failed. I can see the same thing running on server.
Please help
Thanks
If you are using relative path when calling readdirSync, make sure it is relative to process.cwd().
However, "require" should be relative to the current script.
For example, given the following structure
server.js (node process)
/lib/importer.js (the current script)
/lib/application/models/
you may need to write importer.js as:
var fs = require('fs');
var files = fs.readdirSync('./lib/application/models/');
for (var i in files) {
var definition = require('./application/models/' + files[i]).Model;
console.log('Model Loaded: ' + files[i]);
}
Have you tried the following?
var files = fs.readdirSync(__dirname+'/application/models/');

Resources