You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.3 KiB
JavaScript
180 lines
4.3 KiB
JavaScript
// https://github.com/DTrejo/run.js
|
|
// Used to run code in a directory and rerun it if any files are changed.
|
|
// Usage: ./cli.js servercode.js
|
|
// Where servercode.js is whatever js file you want node to run
|
|
|
|
// Excludes filetypes in the ignoreExtensions array
|
|
var util = require('util')
|
|
, fs = require('fs')
|
|
, path = require('path')
|
|
, spawn = require('child_process').spawn
|
|
, minimatch = require('minimatch')
|
|
, child // child process which runs the user's code
|
|
, ignoreExtensions = ['.dirtydb', '.db', '.styl', '.css']
|
|
, ignoreFiles = [ 'node_modules' ]
|
|
// switched out for coffee depending on extension.
|
|
, node = 'node'
|
|
, args = process.argv
|
|
, signal = null
|
|
|
|
//
|
|
// Tell user the correct usage if they miss-type
|
|
//
|
|
if (args.length <= 2) {
|
|
console.log('Found ' + (args.length - 2)
|
|
, 'argument(s). Expected one or more.')
|
|
console.log(
|
|
'Usage: \n runjs [SIGNAL] somecode.js [--args]\n'
|
|
+ 'Ex: \n runjs somecode.js --args'
|
|
+ ' \n runjs SIGUSR2 somecode.js --args\n'
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
//
|
|
// If we define a signal, parse it out and then remove from the array
|
|
//
|
|
if (args[2].match(/^SIG/)) {
|
|
signal = args.splice(2, 1)[0];
|
|
}
|
|
|
|
//
|
|
// use `coffee` if the file ends with .coffee
|
|
//
|
|
if (args[2].match(/\.coffee$/)) node = 'coffee'
|
|
|
|
|
|
//
|
|
// Exclude files based on .gitignore
|
|
//
|
|
if (fs.existsSync('.gitignore')) {
|
|
ignoreFiles = ignoreFiles.concat(fs.readFileSync('.gitignore', 'utf8')
|
|
.split('\n')
|
|
.filter(function(s) {
|
|
s = s.trim()
|
|
return s.indexOf('#') !== 0 && s.length > 0
|
|
})
|
|
)
|
|
}
|
|
|
|
console.log('Watching', path.resolve('./'), 'and all sub-directories not'
|
|
, 'excluded by your .gitignore. Will not monitor dotfiles.')
|
|
|
|
watchFiles(parseFolder('.'), restart) // watch all files, restart if problem
|
|
run()
|
|
|
|
|
|
process.stdin.setEncoding('utf8')
|
|
|
|
// executes the command given by the second argument
|
|
;function run() {
|
|
// run the server
|
|
var childArgs = args.slice(2) || []
|
|
child = spawn(node, childArgs)
|
|
|
|
// let the child's output escape.
|
|
child.stdout.on('data', function(data) {
|
|
process.stdout.write(data)
|
|
})
|
|
child.stderr.on('data', function(error) {
|
|
process.stdout.write(error)
|
|
})
|
|
|
|
// let the user's typing get to the child
|
|
process.stdin.pipe(child.stdin)
|
|
|
|
console.log('\nStarting: ' + childArgs.join(' '))
|
|
}
|
|
|
|
;function restart() {
|
|
// kill if running
|
|
if (child) {
|
|
if (signal) {
|
|
child.kill(signal)
|
|
} else {
|
|
child.kill()
|
|
run()
|
|
}
|
|
} else {
|
|
run()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parses a folder recursively and returns a list of files
|
|
*
|
|
* @param root {String}
|
|
* @return {Array}
|
|
*/
|
|
;function parseFolder(root) {
|
|
var fileList = []
|
|
, files = fs.readdirSync(root)
|
|
|
|
files.forEach(function(file) {
|
|
var pathname = path.join(root, file)
|
|
, stat = fs.lstatSync(pathname)
|
|
|
|
if (stat === undefined) return
|
|
|
|
// add files to file list
|
|
if (!stat.isDirectory()) {
|
|
fileList.push(pathname)
|
|
|
|
// recur if directory
|
|
} else {
|
|
// don't watch folders matched by .gitignore regexes
|
|
for (var i = 0, pattern; pattern = ignoreFiles[i]; i++) {
|
|
if (minimatch(file, pattern)) {
|
|
console.log('Found & ignored', './' + pathname, '; is listed in .gitignore')
|
|
return
|
|
}
|
|
}
|
|
fileList = fileList.concat(parseFolder(pathname))
|
|
}
|
|
})
|
|
|
|
return fileList
|
|
}
|
|
|
|
|
|
/**
|
|
* Add change listener to files, which is called whenever one changes.
|
|
* Ignores certain extensions.
|
|
*
|
|
* @param files {Array}
|
|
* @param callback {function}
|
|
*/
|
|
;function watchFiles(files, callback) {
|
|
|
|
var config = { persistent: true, interval: 25 }
|
|
files.forEach(function (file) {
|
|
|
|
// don't watch dotfiles.
|
|
if (file.indexOf('.') === 0) return
|
|
|
|
// don't watch things with ignored extensions
|
|
var ext = path.extname(file)
|
|
if (ignoreExtensions.indexOf(ext) !== -1) {
|
|
console.log('Found & ignored', './' + file, '; has ignored extension')
|
|
return
|
|
}
|
|
|
|
// don't watch files matched by .gitignore regexes
|
|
for (var i = 0, pattern; pattern = ignoreFiles[i]; i++) {
|
|
if (minimatch(file, pattern)) {
|
|
console.log('Found & ignored', './' + file, '; is listed in .gitignore')
|
|
return
|
|
}
|
|
}
|
|
|
|
// if any file changes, run the callback
|
|
fs.watchFile(file, config, function (curr, prev) {
|
|
|
|
if ((curr.mtime + '') != (prev.mtime + '')) {
|
|
console.log('./' + file + ' changed')
|
|
if (callback) callback()
|
|
}
|
|
})
|
|
})
|
|
}
|