Node.js absolute path - javascript

I'm trying to build a Electron app which quickly pull the machine info to the user. I'm trying to use the npm module 'shelljs' to be able to use shell script in a node environment. But Electron doesn't really support shelljs so I'm in a bit of a pickle. There is a workaround that includes to use the absolute path to the node binary. Not sure what they mean by that so I thought you guys could help out.
The workaround I got is taken from here where they say this:
Set it like any regular variable.
// This is inside your javascript file
var shell = require('shelljs');
shell.config.execPath = 'path/to/node/binary'; // Replace this with the real path
// The rest of your script...
This is my code where I get an undefined on the execPath:
const shell = require('shelljs')
const path = require('path')
shell.confic.execPath = path.join('C:', 'Program Files', 'nodejs', 'node_modules', 'npm', 'bin')
Am I interpreting the workaround the wrong way?

The spelling error that #Chirag Ravindra pointed out did the trick. After a bit of thinking I came to this solution:
shell.config.execPath = path.join('C:', 'Program Files', 'nodejs', 'node.exe')
//Thomas

Related

gulp watch not work when use absolute path?

I am setting a gulp development environment, but when I used an absolute path in gulp watcher, it didn't work.Does gulp watcher support absolute path?
gulpfile.js
gulp.task('watch', function() {
gulp.watch(
path.join(__dirname, 'public/css/**/*.css'),
gulp.parallel('dev:css', 'dev:cssImgs')
);
});
I found the same error, and sorry for necroing this question in 2019., but this problem isn't solved yet.
It seems that watch process only accept relative paths written in unix style. It won't accept absolute paths or even relative paths with back slashes (windows style).
Using node path to clear out the path won't help on windows, so only solution would be to use node path.normalize('..\\your\\relative\\path\\') and then replace \\ with /.
I wrote one simple function that I will normalize path in unix way no matter on which OS it's used.
/*
This plugin is used to fix path separators for dynamically created links used
for `gulp watch` command.
It converts links like
`../../some//path\with/wrong//\separators/`
to
`../../some/path/with/wrong/separators/`
It also replaces `~` with user home directory path
*/
module.exports = (oldPath) => {
const pathString = oldPath;
const fix = /\\{1,}|\/{1,}/;
const user_home = require('os').homedir();
return pathString.replace(new RegExp(fix, 'gm'), '/').replace(new RegExp(fix, 'gm'), '/').replace('~', user_home)
}
Save that code as fixPath.js and then use it in this manner:
const fixPath = require('./fixPath')
let badPath = '../../some//path\with/wrong//\separators/'
let goodPath = fixPath(badPath) // "../../some/path/with/wrong/separators/"

How to know the exact path to file that was required()

In node console I do: require('path') or require('assert') => how to find out exactly which file was loaded by the command (the absolute path to the file)
I couldn't find a decisive answer anywhere and I couln't get to it myself... I thought it would be easier than it seems to be...
I don't think this is as simple as you were hoping but using the require object you can do this:
// Load up some modules
var _ = require('lodash');
var natural = require('natural');
// These are where Node will go looking for the modules above
console.log('Paths:');
console.log(require.main.paths);
// You can print out the id of each module, which is the path to its location
console.log('Module IDs:');
require.main.children.forEach((module) => {
console.log(module.id);
});
Output:
$ node index.js
Paths:
[ '/Users/tyler/Desktop/js_test/node_modules',
'/Users/tyler/Desktop/node_modules',
'/Users/tyler/node_modules',
'/Users/node_modules',
'/node_modules' ]
Module IDs:
/Users/tyler/Desktop/js_test/node_modules/lodash/lodash.js
/Users/tyler/Desktop/js_test/node_modules/natural/lib/natural/index.js
As far as I can tell the module IDs will be in the order that you require them, so you should be able to work with their indexes or search through the module ids dynamically for whatever you are looking for.

Traversing directory in Node (Grunt)

Having a strange issue when building a grunt plugin.
Basically, I'd like to use a node_module in my grunt task itself. To do this, I want to traverse a level up, then down into the node modules to call their one file specifically.
Originally, I wanted to do this:
../node_modules/github-changes/bin/index.js
However, I get the following error:
Warning: Command failed: /bin/sh: 1: ../node_modules/github-changes/bin/index.js: not found
Use --force to continue.
So, for now I have a hack on using Node's __dirname variable, but it's not very pretty:
var dirHack = __dirname.replace("/tasks", ""), // Terrible hack, need to fix
ghC = dirHack + '/node_modules/github-changes/bin/index.js';
This works, but I'd love to avoid it.
You can see the line here.
What's missing that's causing that error? Am I missing something here?
If github-changes is a dependency, you can resolve a path to file within the package using ghC = require.resolve('github-changes/bin/index.js').
But you're getting that error because you're trying to run that file as a shell script, which it is not. You need to run it with node. The easiest way to find the path to the node executable is process.execPath. See http://nodejs.org/api/process.html#process_process_execpath
Here is an example:
var exec = require('child_process').exec;
var ghC = require.resolve('github-changes/bin/index.js');
exec(process.execPath + ' ' + ghC, function(error) {});

How to run node js application programmatically using forever

I need to run the set of node js files which contains the configuration information where It has to run typically port number and IP address then using the forever in node.js I need to run the script in the terminal with the configuration without having any manual input.
For Programmatic approach , you can use Forever-Moniter
var forever = require('forever-monitor');
var child = new (forever.Monitor)('your-filename.js', {
max: 3,
silent: true,
options: []
});
child.on('exit', function () {
console.log('your-filename.js has exited after 3 restarts');
});
child.start();
You could make use of the child_process module. Check the doc, there're some useful information there: http://nodejs.org/api/child_process.html
To give a brief example
var exec = require('child_process').exec;
exec('forever', function callback(error, stdout, stderr){
// cb
});
If you don't need a callback / don't want to wait for the execution:
var exec = require('child_process').exec('forever').unref();
Was that helpful?
Best
Marc
Edit: Ok, not sure if I really got the point of your question, but my answer combined with https://stackoverflow.com/a/23871739/823851 might offer a good solution.
Usage:
forever start hello.js to start a process.
forever list to see list of all processes started by forever
forever stop hello.js to stop the process, or forever stop 0 to stop the process with index 0 (as shown by forever list).
node-config is a good module for managing different configurations of a Node.js app.
For example, to make a "production" config, /config/production.json would contain:
{
"port" : "3000",
"ip" : "192.168.1.1"
}
In one of your node application JS files:
config = require('config')
....
var port = config.port;
var ip = config.ip;
And to launch the app in this configuration, just first set your NODE_ENV to production from the shell before running your app.
export NODE_ENV=production
forever start app.js
Make additional config JSON files as needed for each of your environments. default.json is used when no environment is specified.

How to set a including path in the Gjs code?

As i could see, the Gjs imports, loads only /usr/share/gjs-1.0 and /usr/lib/gjs-1.0 by default. I want to modularize an application, like we can do with node, but i must find modules relative to the script file.
I found this two ways to add include paths:
gjs --include-path=my-modules my-script.js
GJS_PATH=my-modules gjs my-script.js
...but both are related to the current directory, not to the file (obliviously), and they needed to be declared on the command line, making this unnecessarily complex.
How can i set a including path in the Gjs code? (So i can make this relative to the file)
Or... There is another way to import files from anywhere, like in python?
(Please, you don't need to propose to use a shellscript launcher to solve the --include-path and GJS_PATH problem. That is obvious, but less powerful. If we do not have a better solution, we survive with that.)
You need to set or modify imports.searchPath (which is not obvious because it doesn't show up with for (x in imports)print(x)). So this:
imports.searchPath.unshift('.');
var foo = imports.foo;
imports the file “foo.js” as the foo object.
This is compatible with Seed, although there imports knows it has a searchPath.
(Earlier versions of this answer were substantially less accurate and more inflammatory. Sorry).
As Douglas says, you do need to modify imports.searchPath to include your library location. Using . is simple, but depends on the files always being run from the same directory location. Unfortunately finding the directory of the currently executing script is a huge hack. Here's how Gnome Shell does it for the extensions API
I've adapted this into the following function for general use:
const Gio = imports.gi.Gio;
function getCurrentFile() {
let stack = (new Error()).stack;
// Assuming we're importing this directly from an extension (and we shouldn't
// ever not be), its UUID should be directly in the path here.
let stackLine = stack.split('\n')[1];
if (!stackLine)
throw new Error('Could not find current file');
// The stack line is like:
// init([object Object])#/home/user/data/gnome-shell/extensions/u#u.id/prefs.js:8
//
// In the case that we're importing from
// module scope, the first field is blank:
// #/home/user/data/gnome-shell/extensions/u#u.id/prefs.js:8
let match = new RegExp('#(.+):\\d+').exec(stackLine);
if (!match)
throw new Error('Could not find current file');
let path = match[1];
let file = Gio.File.new_for_path(path);
return [file.get_path(), file.get_parent().get_path(), file.get_basename()];
}
Here's how you might use it from your entry point file app.js, after defining the getCurrentFile function:
let file_info = getCurrentFile();
// define library location relative to entry point file
const LIB_PATH = file_info[1] + '/lib';
// then add it to the imports search path
imports.searchPath.unshift(LIB_PATH);
Wee! now importing our libraries is super-easy:
// import your app libraries (if they were in lib/app_name)
const Core = imports.app_name.core;

Categories

Resources