Traversing directory in Node (Grunt) - javascript

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) {});

Related

Node.js absolute path

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

Getting test results when creating a Karma server programmatically

I am trying to run multiple Karma test files in parallel from inside a Node script and get to know which tests are passing or failing. Right now what I have is this:
const exec = require("child_process").exec;
exec("karma start " + filename, (error, stdout, stderr) => {
// handle errors and test results...
});
The code above works well, and I can get the information on tests passed or failed from stdout. However, it requires having installed Karma and all of the associated dependencies (reporters, browser launchers, etc.) globally. I am looking for a solution that doesn't require me to install all dependencies globally.
My first thought was this:
const karma = require("karma");
const server = new karma.Server(config, () => {
// some logic
});
However, when trying this other approach, I have been unable to gather the test results programmatically.
When using new karma.Server(), is there any way in which I could know which tests have passed or failed (and, ideally, a stack trace of the error)? Alternatively, is there any other way in which I can execute my tests and get the desired information programmatically without the need to install dependencies globally?
Actually, changing the exec line to this seems to do the trick:
exec("node node_modules/karma/bin/karma start " + filename, (error, stdout, stderr) => {
It turns out I'd only need to run the locally installed version of Karma instead of the global one. :-)

Watching folder for change in Node.js

Im looking for a way to notice changes in a directory in Node.js. I read THIS and was thinking thats exactly what i want. But chokidar spawns to many events.
My code looks like this:
chokidar = require('chokidar');
var watcher = chokidar.watch('./Update', {ignored: /[\/\\]\./, persistent: true});
var count=0;
watcher
.on('add', function(path)
{
count++;
console.log('File ' + path + ' has been added' + count);
})
.on('error', function(error) {console.error('Error happened', error);})
When i run it and move a file in the Update directory i get the following output:
File Update\Neues Textdokument.txt has been added1
File Update\Neues Textdokument.txt has been added2
File Update\Neues Textdokument.txt has been added3
In the future i want to replace the console output with code that actualy does something, so i cant have moving one file spawning 3 events. Am I using the libary wrong? Or is the libary just not suited for what I want to do? If so what libary should i use instead?
try the following patch:
https://github.com/paulmillr/chokidar/pull/124
as stated in
https://github.com/paulmillr/chokidar/issues/104
In the end I am using version 0.7.1 of chokidar. It works fine as long the folder is empty at the moment the file is added, but im still looking for a better solution

Running a Grunt Task directly from Node

How do I execute a Grunt task directly from Node without shelling out to the CLI?
I've got the following "POC" code; however, "stuff" is never logged.
var grunt = require('grunt');
grunt.registerTask('default', 'Log some stuff.', function() {
console.log('stuff');
});
grunt.task.run('default'); // This is probably not the right command
I'm pretty new to Grunt, so I'm probably missing something obvious. I suspect the command I'm using to "run" the task is just queuing it, and doesn't actually start running things. I can't find documentation for manually running things, though.
Update
While this is the answer, Grunt has tons of issues with being run directly from Node. Not the least of which is when the grunt task fails, it calls process.exit and nicely quits your node instance. I cannot recommend trying to get this to work.
Ok, I'll just answer my own question. I was right, the command I had was wrong.
Updated code:
var grunt = require('grunt');
grunt.registerTask('default', 'Log some stuff.', function() {
console.log('stuff');
});
grunt.tasks(['default']);
it take much time and finally, I already made it working for me
var util = require('util')
var exec = require('child_process').exec;
var child = exec("/usr/local/bin/grunt --gruntfile /path/to/Gruntfile.js", function (error, stdout, stderr) {
util.print('stdout: ' + stdout);
util.print('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
What if you do the following?
grunt.tasks("default");
I've created an Grunt runner in one of my projects that does some parsing and then call the line above. Almostly what you already answered, but with support for a Gruntfile.js.
We're using Jenkins for our builds. So here is how we resolved the issue using bash:
#!/bin/bash
export PATH=$PATH:/usr/local/bin
grunt full-build | tee /dev/stderr | awk '/Aborted/ || /Fatal/{exit 1}'
echo rv: $?
exit $?
The use of /dev/stderr is because we're running within Jenkins and we still want to ouput to show up within the console.
Visualjeff

Console.log debug messages managing

My JS code is usually full of console.log() debug messages. Sometimes it is better to turn them off, or to turn off some part of them.
I can, for example, wrap console.log() statement in some function with conditions which are defined by some constants. Is it the best way to manage debug output or are more elegant alternatives?
Bunyan logging module is popular for node.js
Example code hi.js:
var bunyan = require('bunyan');
var log = bunyan.createLogger({name: 'myapp'});
log.info('hi');
log.warn({lang: 'fr'}, 'au revoir');
Output:
{"name":"myapp","hostname":"localhost","pid":40161,"level":30,"msg":"hi","time":"2013-01- 04T18:46:23.851Z","v":0}
{"name":"myapp","hostname":"localhost","pid":40161,"level":40,"lang":"fr","msg":"au revoir","time":"2013-01-04T18:46:23.853Z","v":0}
You can then filtering from command lines:
$ node hi.js | bunyan -l warn
[2013-01-04T19:08:37.182Z] WARN: myapp/40353 on localhost: au revoir (lang=fr)
Wrapping console.log into a function works well. But notice that there are also a lot of logging utilities out there for javascript. A little google on "js logger" may yield suitable results.
If you're using Node.js then debug is extremely effective as an alternative to console.log()
It's basically a substitute for console.log() except you can enable it at the command line with the DEBUG environment variable based on how you've initialized it in each file.
Let's say I have a project with a couple of files referenced from my index.js file:
one.js
var debug = require('debug')('one-one');
var func = function() {
debug('func');
}
two.js
var debug = require('debug')('one-two');
var func = function() {
debug('func');
}
You've initialized debug with the name "one-one" in the first file and "one-two" in the second file.
On the command line I can run them like this:
node index.js
Result: no debug output. However, if I run it like this:
DEBUG=* node index.js
The both the debug statements will get written out, however, in different colors and with the debug name (one-one or one-two) so I can tell which file they came from.
Now let's say you want to narrow it down a bit more. You could run:
DEBUG=*-two node index.js
To only get output from debug that's been set with "-two" at the end of the name or
DEBUG=one-* node index.js
to get everything starting with "one-"
You can also say that you want everything, or a set of things, or exclude patterns or sets. To exclude something you precede it with a dash, an example:
DEBUG=one*,monkey*,-monkey:banana,-elephant,-chimp:* node index.js
This will include everything starting with "one" or "monkey" and exclude anything called "monkey:banana", or "elephant" or starting with "chimp:"
If you wanted to exclude everything except then:
DEBUG=*,-pattern1,-pattern2 node index.js
JS logger is quite good and lightweight tool with flixible settings for log messages levels and several predefined logging levels (DEBUG, INFO, WARN, ERROR).

Categories

Resources