I have a project of 100+ javascript files each with 1-5 missing semicolons according to JSHint (as a result multiple people working on the project with different conventions).
I'd like to bulk fix everything as it's not practical to fix each individually. I've found this: https://github.com/jshint/fixmyjs but I don't see a way only fix semicolons without 'fixing' other things (tabs -> spaces, for example).
Does anyone know of way to do this? I'm comfortable with the possibility that it might cause breakage/introduce bugs. I've look over the errors and they look pretty routine.
I really hope you like this as a solution. Be vary careful that you verify with jshint again after you've fixed the issues. And out of curiosity, how did you manage to get so many broken javascript files?
#!/bin/sh
function fixFile {
for i in `jshint $1 | grep -i "Missing semicolon" \
| sed -e 's/\([^0-9]*\)\([0-9]*\)\(.*$\)/\2/'`;
do
sed -i $1 -e $i's/\(\s*\)$/;/'
done
}
fixFile $1
The above uses jshint to produce some error lines, greps them for the missing semicolon errors only, extracts the line number of each error, then seds the file in place on that line to remove any trailing whitespace and replace it with a semicolon.
The file...
var a = 5, c = 4
function helloWorld() {
if (this == doesntmakesense)
console.log('hello' + 'world');
}
console.log(a+c);
console.log('finished')
...becomes...
var a = 5, c = 4;
function helloWorld() {
if (this == doesntmakesense)
console.log('hello' + 'world');
}
console.log(a+c);
console.log('finished');
Where petty semantic errors are ignored, and only semicolons treated.
I'd save the bash script as something like fixFile.sh and then run find . -name "*.js" -exec ./fixFile.sh {} \;
But please commit beforehand. All commands are run at your own risk ;)
There is a safer way of adding missing semicolons than using regular expressions. Use the following steps to configure fixmyjs to only fix semicolons as originally asked by Evan:
Install fixmyjs
npm install fixmyjs -g
Create a fixmyjs config file fixmyjs-config with the following content
{ "asi": false }
Run fixmyjs
fixmyjs --config [fixmyjs-config] --legacy yourfile.js
Reference: https://github.com/jshint/fixmyjs/issues/86
Google Closure JS Linter has a program that comes with it, able to correct some of the more regular violations such as this one I believe, it's named fixjsstyle (python btw)
Related
I have a gulp task getBuildNumber which uses Child Process to execute the script.
gulp.task('getBuildNumber', function() {
var buildNumber = child_process.execSync("echo $BUILD_NUMBER").toString().trim();
console.log(buildNumber);
});
When I run the following command for gulp
npm run gulp -- getBuildNumber
I always get the output as $BUILD_NUMBER and not the actual Jenkins build number.
Can someone please suggest on how to proceed with this?
You can access environment variables with process.env.
For example:
console.log(process.env.BUILD_NUMBER);
According to https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback, you need to escape special characters:
exec('echo "The \\$HOME variable is $HOME"');
In your case, this means you'd need to use
[...]child_process.execSync("echo \\$BUILD_NUMBER").toString().trim();[...]
^^
I'm using Browserify to bundle up my JS before pushing to my Bitbucket repo, and then using Codeship to test the build and push to Heroku.
I'm using Node/Express to serve my app, and in my index.jade I have a <script /> pointing to /dist/index.js.
A couple of times, I've mistakenly pushed my latest code with broken Browserify output, ie. the contents of /dist/index.js will be:
console.error('cannot find module XYZ')
And I've deployed this to my live app. UH OH.
I've put in a very rudimentary test which gets ran on Codeship which I'm hoping should avoid this in the future:
var exit = function() {
process.exit(1)
}
var success = function() {
process.exit(0)
}
var fs = require('fs')
var index
try {
index = fs.readFileSync(__dirname + '/../public/dist/index.js', 'utf-8')
} catch (e) {
exit()
}
if(!index){
exit()
}
var invalid = index.length < 1000
if(invalid){
return exit()
}
success()
I'm just checking if the file exists, and that the contents of the file is over 1000 characters.
Not sure if there's a specific answer to this, but would be a reasonable approach to making sure broken Browserify output never gets committed/deployed?
I haven't used Codeship before, but I have used other similar services. You haven't described how you push - I'm going to assume you're using git.
With git, this becomes easy: write a pre-push hook that will abort the push if something fails. Here's an example from a project I'm working on:
#!/bin/bash
# the protected branches
#
protected_branches='develop master'
# Check if we actually have commits to push
#
commits=`git log #{u}..`
if [ -z "$commits" ]; then
exit 0
fi
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
# is the current branch in the list of protected branchs? if so, then run the
# tests
#
if grep -q "$current_branch" <<< "$protected_branches"; then
# move into the dir containing the tests
#
pushd $(git rev-parse --show-toplevel)/contract >/dev/null
gulp test
RESULT=$?
# back to whatever dir we were in before
#
popd >/dev/null
if [ $RESULT -ne 0 ]; then
echo "-------- Failed Tests"
exit 1
fi
fi
exit 0
This is a modified version of a script I found in this blog post.
Basically, this script checks to see if I'm pushing one of the protected branches and, if so, runs my tests. If those test fail, then the push is aborted.
You could, of course, change the conditions under which the push is aborted. For example, write some code to check & see if your browserify bundle is correct and fail if it's not. You mention checking the length of your bundle - maybe something like length=$(ls -l | cut -c 30-34) and then check the value of length (sorry, I'm not a real bash guru).
The benefit of this approach is that the messed up code never leaves your local machine - you run the test locally and if it fails, the code doesn't get pushed. This is likely to be faster than running in on Codeship's service.
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).
I'm writing this script that takes in t and uses it in test.js. I'm going to have the output be emailed to me and my collegues.
% mongo my_db --eval 't=9999;' --quiet test.js
9999
------------------------------------------------
Info about stuff going back 9999 days to 2012-08-17.
------------------------------------------------
Stuff x: 433321 (12.43%)
Stuff y: 2723426 (81.57%)
Total: 4524524524
Is there a way to not have what I pass in to --eval be outputted to console so I don't have that dangling '9999' at the top of my results?
Edit: This may be a bug with the --quiet option
See:
https://jira.mongodb.org/browse/SERVER-4391
Bit of a hack, but until that bug gets fixed you could just pipe to tail +2 first and that would exclude the output you do not want, something like:
% mongo my_db --eval 't=9999;' --quiet test.js | tail +2
This worked for me in a quick test to leave out the 9999 line.
Just in case anybody stumbles over this issue. I had the same problem and got an answer on that solves the problem without shell magic:
Use result from mongodb in shell script
I realize it has been a while. Posting a solution, hoping it might help someone who landed into this.
Prefixing a command with a void usually silences outputs.
For example, try:
$ mongo <server>/db script.js --eval 'void (yyyymm="2011-11")'
(NOTE: brackets are important)
Is there a way to execute some code (in a file or from a string, doesn't really matter) before dropping into interactive mode in node.js?
For example, if I create a script __preamble__.js which contains:
console.log("preamble executed! poor guy!");
and a user types node __preamble__.js they get this output:
preamble executed! poor guy!
> [interactive mode]
Really old question but...
I was looking for something similar, I believe, and found out this.
You can open the REPL (typing node on your terminal) and then load a file.
Like this: .load ./script.js.
Press enter and the file content will be executed. Now everything created (object, variable, function) in your script will be available.
For example:
// script.js
var y = {
name: 'obj',
status: true
};
var x = setInterval(function () {
console.log('As time goes by...');
}, 5000);
On the REPL:
//REPL
.load ./script.js
Now you type on the REPL and interact with the "living code".
You can console.log(y) or clearInterval(x);
It will be a bit odd, cause "As time goes by..." keep showing up every five seconds (or so).
But it will work!
You can start a new repl in your Node software pretty easily:
var repl = require("repl");
var r = repl.start("node> ");
r.context.pause = pauseHTTP;
r.context.resume = resumeHTTP;
From within the REPL you can then call pause() or resume() and execute the functions pauseHTTP() and resumeHTTP() directly. Just assign whatever you want to expose to the REPL's context member.
This can be achieved with the current version of NodeJS (5.9.1):
$ node -i -e "console.log('A message')"
The -e flag evaluates the string and the -i flag begins the interactive mode.
You can read more in the referenced pull request
node -r allows you to require a module when REPL starts up. NODE_PATH sets the module search path. So you can run something like this on your command line:
NODE_PATH=. node -r myscript.js
This should put you in a REPL with your script loaded.
I've recently started a project to create an advanced interactive shell for Node and associated languages like CoffeeScript. One of the features is loading a file or string in the context of the interpreter at startup which takes into account the loaded language.
http://danielgtaylor.github.com/nesh/
Examples:
# Load a string (Javascript)
nesh -e 'var hello = function (name) { return "Hello, " + name; };'
# Load a string (CoffeeScript)
nesh -c -e 'hello = (name) -> "Hello, #{name}"'
# Load a file (Javascript)
nesh -e hello.js
# Load a file (CoffeeScript)
nesh -c -e hello.coffee
Then in the interpreter you can access the hello function.
Edit: Ignore this. #jaywalking101's answer is much better. Do that instead.
If you're running from inside a Bash shell (Linux, OS X, Cygwin), then
cat __preamble__.js - | node -i
will work. This also spews lots of noise from evaluating each line of preamble.js, but afterwords you land in an interactive shell in the context you want.
(The '-' to 'cat' just specifies "use standard input".)
Similar answer to #slacktracer, but if you are fine using global in your script, you can simply require it instead of (learning and) using .load.
Example lib.js:
global.x = 123;
Example node session:
$ node
> require('./lib')
{}
> x
123
As a nice side-effect, you don't even have to do the var x = require('x'); 0 dance, as module.exports remains an empty object and thus the require result will not fill up your screen with the module's content.
Vorpal.js was built to do just this. It provides an API for building an interactive CLI in the context of your application.
It includes plugins, and one of these is Vorpal-REPL. This lets you type repl and this will drop you into a REPL within the context of your application.
Example to implement:
var vorpal = require('vorpal')();
var repl = require('vorpal-repl');
vorpal.use(repl).show();
// Now you do your custom code...
// If you want to automatically jump
// into REPl mode, just do this:
vorpal.exec('repl');
That's all!
Disclaimer: I wrote Vorpal.
There isn't a way do this natively. You can either enter the node interactive shell node or run a script you have node myScrpt.js. #sarnold is right, in that if you want that for your app, you will need to make it yourself, and using the repl toolkit is helpful for that kind of thing
nit-tool lets you load a node module into the repl interactive and have access to inner module environment (join context) for development purposes
npm install nit-tool -g
First I tried
$ node --interactive foo.js
but it just runs foo.js, with no REPL.
If you're using export and import in your js, run npm init -y, then tell node that you're using modules with the "type": "module", line -
{
"name": "neomem",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "home.js",
"keywords": [],
"author": "",
"license": "ISC"
}
Then you can run node and import a file with dynamic import -
$ node
Welcome to Node.js v18.1.0.
Type ".help" for more information.
> home = await import('./home.js')
[Module: null prototype] {
get: [AsyncFunction: get],
start: [AsyncFunction: start]
}
> home.get('hello')
Kind of a roundabout way of doing it - having a command line switch would be nice...