pax_global_header00006660000000000000000000000064126742074460014526gustar00rootroot0000000000000052 comment=5467529adb5512292c8dd341691ba75b2293ed7e js-flagged-respawn-0.3.2/000077500000000000000000000000001267420744600152105ustar00rootroot00000000000000js-flagged-respawn-0.3.2/.gitignore000066400000000000000000000000151267420744600171740ustar00rootroot00000000000000*.flags.json js-flagged-respawn-0.3.2/.travis.yml000066400000000000000000000001751267420744600173240ustar00rootroot00000000000000language: node_js node_js: - "0.8" - "0.10" - "0.11" matrix: fast_finish: true allow_failures: - node_js: 0.11 js-flagged-respawn-0.3.2/LICENSE000066400000000000000000000020401267420744600162110ustar00rootroot00000000000000Copyright (c) 2014 Tyler Kellen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. js-flagged-respawn-0.3.2/README.md000066400000000000000000000046051267420744600164740ustar00rootroot00000000000000# flagged-respawn [![Build Status](https://secure.travis-ci.org/js-cli/js-flagged-respawn.svg)](http://travis-ci.org/js-cli/js-flagged-respawn) > A tool for respawning node binaries when special flags are present. [![NPM](https://nodei.co/npm/flagged-respawn.png)](https://nodei.co/npm/flagged-respawn/) ## What is it? Say you wrote a command line tool that runs arbitrary javascript (e.g. task runner, test framework, etc). For the sake of discussion, let's pretend it's a testing harness you've named `testify`. Everything is going splendidly until one day you decide to test some code that relies on a feature behind a v8 flag in node (`--harmony`, for example). Without much thought, you run `testify --harmony spec tests.js`. It doesn't work. After digging around for a bit, you realize this produces a [`process.argv`](http://nodejs.org/docs/latest/api/process.html#process_process_argv) of: `['node', '/usr/local/bin/test', '--harmony', 'spec', 'tests.js']` Crap. The `--harmony` flag is in the wrong place! It should be applied to the **node** command, not our binary. What we actually wanted was this: `['node', '--harmony', '/usr/local/bin/test', 'spec', 'tests.js']` Flagged-respawn fixes this problem and handles all the edge cases respawning creates, such as: - Providing a method to determine if a respawn is needed. - Piping stderr/stdout from the child into the parent. - Making the parent process exit with the same code as the child. - If the child is killed, making the parent exit with the same signal. To see it in action, clone this repository and run `npm install` / `npm run respawn` / `npm run nospawn`. ## Sample Usage ```js #!/usr/bin/env node const flaggedRespawn = require('flagged-respawn'); // get a list of all possible v8 flags for the running version of node const v8flags = require('v8flags').fetch(); flaggedRespawn(v8flags, process.argv, function (ready, child) { if (ready) { console.log('Running!'); // your cli code here } else { console.log('Special flags found, respawning.'); } if (process.pid !== child.pid) { console.log('Respawned to PID:', child.pid); } }); ``` ## Release History * 2016-03-22 - v0.3.2 - fix issue with v8 flags values being dropped * 2014-09-12 - v0.3.1 - use `{ stdio: 'inherit' }` for spawn to maintain colors * 2014-09-11 - v0.3.0 - for real this time * 2014-09-11 - v0.2.0 - cleanup * 2014-09-04 - v0.1.1 - initial release js-flagged-respawn-0.3.2/index.js000066400000000000000000000007651267420744600166650ustar00rootroot00000000000000const reorder = require('./lib/reorder'); const respawn = require('./lib/respawn'); module.exports = function (flags, argv, execute) { if (!flags) { throw new Error('You must specify flags to respawn with.'); } if (!argv) { throw new Error('You must specify an argv array.'); } var proc = process; var reordered = reorder(flags, argv); var ready = JSON.stringify(argv) === JSON.stringify(reordered); if (!ready) { proc = respawn(reordered); } execute(ready, proc); }; js-flagged-respawn-0.3.2/lib/000077500000000000000000000000001267420744600157565ustar00rootroot00000000000000js-flagged-respawn-0.3.2/lib/reorder.js000066400000000000000000000005221267420744600177550ustar00rootroot00000000000000module.exports = function (flags, argv) { if (!argv) { argv = process.argv; } var args = [argv[1]]; argv.slice(2).forEach(function (arg) { var flag = arg.split('=')[0]; if (flags.indexOf(flag) !== -1) { args.unshift(arg); } else { args.push(arg); } }); args.unshift(argv[0]); return args; }; js-flagged-respawn-0.3.2/lib/respawn.js000066400000000000000000000005721267420744600177770ustar00rootroot00000000000000const spawn = require('child_process').spawn; module.exports = function (argv) { var child = spawn(argv[0], argv.slice(1), { stdio: 'inherit' }); child.on('exit', function (code, signal) { process.on('exit', function () { if (signal) { process.kill(process.pid, signal); } else { process.exit(code); } }); }); return child; }; js-flagged-respawn-0.3.2/package.json000066400000000000000000000017071267420744600175030ustar00rootroot00000000000000{ "name": "flagged-respawn", "description": "A tool for respawning node binaries when special flags are present.", "version": "0.3.2", "homepage": "https://github.com/js-cli/js-flagged-respawn", "author": { "name": "Tyler Kellen", "url": "http://goingslowly.com/" }, "repository": { "type": "git", "url": "git://github.com/js-cli/js-flagged-respawn.git" }, "bugs": { "url": "https://github.com/js-cli/js-flagged-respawn/issues" }, "licenses": [ { "type": "MIT", "url": "https://github.com/js-cli/js-flagged-respawn/blob/master/LICENSE" } ], "scripts": { "respawn": "node test/bin/respawner --harmony test", "nospawn": "node test/bin/respawner test", "test": "mocha -R spec test" }, "main": "index.js", "engines": { "node": ">= 0.8.0" }, "keywords": [ "respawn flags" ], "devDependencies": { "chai": "~1.9.1", "mocha": "~1.21.4", "v8flags": "~1.0.1" } } js-flagged-respawn-0.3.2/test/000077500000000000000000000000001267420744600161675ustar00rootroot00000000000000js-flagged-respawn-0.3.2/test/bin/000077500000000000000000000000001267420744600167375ustar00rootroot00000000000000js-flagged-respawn-0.3.2/test/bin/exit_code.js000066400000000000000000000003331267420744600212370ustar00rootroot00000000000000#!/usr/bin/env node const flaggedRespawn = require('../../'); flaggedRespawn(['--harmony'], process.argv, function (ready) { if (ready) { setTimeout(function () { process.exit(100); }, 100); } }); js-flagged-respawn-0.3.2/test/bin/respawner.js000066400000000000000000000007001267420744600213000ustar00rootroot00000000000000#!/usr/bin/env node const flaggedRespawn = require('../../'); // get a list of all possible v8 flags for the running version of node const v8flags = require('v8flags').fetch(); flaggedRespawn(v8flags, process.argv, function (ready, child) { if (ready) { console.log('Running!'); } else { console.log('Special flags found, respawning.'); } if (child.pid !== process.pid) { console.log('Respawned to PID:', child.pid); } }); js-flagged-respawn-0.3.2/test/bin/signal.js000066400000000000000000000004421267420744600205520ustar00rootroot00000000000000#!/usr/bin/env node const flaggedRespawn = require('../../'); flaggedRespawn(['--harmony'], process.argv, function (ready, child) { if (ready) { setTimeout(function() { process.exit(); }, 100); } else { console.log('got child!'); child.kill('SIGHUP'); } }); js-flagged-respawn-0.3.2/test/index.js000066400000000000000000000070201267420744600176330ustar00rootroot00000000000000const expect = require('chai').expect; const exec = require('child_process').exec; const reorder = require('../lib/reorder'); const flaggedRespawn = require('../'); describe('flaggedRespawn', function () { var flags = ['--harmony', '--use_strict', '--stack_size'] describe('reorder', function () { it('should re-order args, placing special flags first', function () { var needsRespawn = ['node', 'file.js', '--flag', '--harmony', 'command']; var noRespawnNeeded = ['node', 'bin/flagged-respawn', 'thing']; expect(reorder(flags, needsRespawn)) .to.deep.equal(['node', '--harmony', 'file.js', '--flag', 'command']); expect(reorder(flags, noRespawnNeeded)) .to.deep.equal(noRespawnNeeded); }); it('should keep flags values when not placed first', function () { var args = ['node', 'file.js', '--stack_size=2048']; var expected = ['node', '--stack_size=2048', 'file.js']; expect(reorder(flags, args)).to.deep.equal(expected); }); it('should ignore special flags when they are in the correct position', function () { var args = ['node', '--harmony', 'file.js', '--flag']; expect(reorder(flags, reorder(flags, args))).to.deep.equal(args); }); }); describe('execute', function () { it('should throw if no flags are specified', function () { expect(function () { flaggedRespawn.execute(); }).to.throw; }); it('should throw if no argv is specified', function () { expect(function () { flaggedRespawn.execute(flags); }).to.throw; }); it('should respawn and pipe stderr/stdout to parent', function (done) { exec('node ./test/bin/respawner.js --harmony', function (err, stdout, stderr) { expect(stdout.replace(/[0-9]/g, '')).to.equal('Special flags found, respawning.\nRespawned to PID: \nRunning!\n'); done(); }); }); it('should respawn and pass exit code from child to parent', function (done) { exec('node ./test/bin/exit_code.js --harmony', function (err, stdout, stderr) { expect(err.code).to.equal(100); done(); }); }); it.skip('should respawn; if child is killed, parent should exit with same signal', function (done) { // TODO: figure out why travis hates this exec('node ./test/bin/signal.js --harmony', function (err, stdout, stderr) { console.log('err', err); console.log('stdout', stdout); console.log('stderr', stderr); expect(err.signal).to.equal('SIGHUP'); done(); }); }); it('should call back with ready as true when respawn is not needed', function () { var argv = ['node', './test/bin/respawner']; flaggedRespawn(flags, argv, function (ready) { expect(ready).to.be.true; }); }); it('should call back with ready as false when respawn is needed', function () { var argv = ['node', './test/bin/respawner', '--harmony']; flaggedRespawn(flags, argv, function (ready) { expect(ready).to.be.false; }); }); it('should call back with the child process when ready', function () { var argv = ['node', './test/bin/respawner', '--harmony']; flaggedRespawn(flags, argv, function (ready, child) { expect(child.pid).to.not.equal(process.pid); }); }); it('should call back with own process when respawn not needed', function () { var argv = ['node', './test/bin/respawner']; flaggedRespawn(flags, argv, function (ready, child) { expect(child.pid).to.equal(process.pid); }); }); }); });