diff --git a/README.md b/README.md index ee9a6bdc..ee19d95e 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ All the commands support these specific v8 options: $ egg-bin [command] --debug --es_staging ``` +if `process.env.NODE_DEBUG_OPTION` is provided (WebStorm etc), will use it as debug options. + ### dev Start dev cluster on `local` env, it will start a master, an agent and a worker. diff --git a/lib/cmd/cov.js b/lib/cmd/cov.js index c689cdca..94e027e0 100644 --- a/lib/cmd/cov.js +++ b/lib/cmd/cov.js @@ -1,7 +1,7 @@ /* istanbul ignore next */ 'use strict'; -const debug = require('debug')('egg-bin:cov'); +const debug = require('debug')('egg-bin'); const path = require('path'); const rimraf = require('mz-modules/rimraf'); const testExclude = require('test-exclude'); diff --git a/lib/cmd/debug.js b/lib/cmd/debug.js index e9020afd..242e50a0 100644 --- a/lib/cmd/debug.js +++ b/lib/cmd/debug.js @@ -1,20 +1,33 @@ 'use strict'; +const semver = require('semver'); const Command = require('./dev'); class DebugCommand extends Command { constructor(rawArgv) { super(rawArgv); + const newDebugger = semver.gte(process.version, '8.0.0'); this.usage = 'Usage: egg-bin debug [dir] [options]'; this.options = { // set default to empty so `--inspect` will always pass to fork inspect: { description: 'V8 Inspector port', - default: '', + default() { + /* istanbul ignore next */ + return newDebugger ? '' : undefined; + }, }, 'inspect-brk': { description: 'whether break at start', }, + + debug: { + description: 'legacy debugger', + default() { + /* istanbul ignore next */ + return newDebugger ? undefined : ''; + }, + }, }; process.env.EGG_DEBUG = 'true'; } diff --git a/lib/cmd/dev.js b/lib/cmd/dev.js index ca8d586b..1292475a 100644 --- a/lib/cmd/dev.js +++ b/lib/cmd/dev.js @@ -1,6 +1,6 @@ 'use strict'; -const debug = require('debug')('egg-bin:dev'); +const debug = require('debug')('egg-bin'); const Command = require('../command'); const path = require('path'); const utils = require('egg-utils'); diff --git a/lib/cmd/test.js b/lib/cmd/test.js index 94afe0b6..076c00b3 100644 --- a/lib/cmd/test.js +++ b/lib/cmd/test.js @@ -1,6 +1,6 @@ 'use strict'; -const debug = require('debug')('egg-bin:test'); +const debug = require('debug')('egg-bin'); const fs = require('fs'); const path = require('path'); const globby = require('globby'); diff --git a/lib/command.js b/lib/command.js index 66632306..3f7a93ee 100644 --- a/lib/command.js +++ b/lib/command.js @@ -2,6 +2,7 @@ const BaseCommand = require('common-bin'); const changeCase = require('change-case'); +const parser = require('yargs-parser'); class Command extends BaseCommand { /** @@ -13,30 +14,19 @@ class Command extends BaseCommand { const context = super.context; const argv = context.argv; - // extract execArgv to special item - const execArgvObj = {}; + let execArgvObj = {}; let debugPort; - const match = (key, arr) => arr.some(x => x instanceof RegExp ? x.test(key) : x === key); // eslint-disable-line no-confusing-arrow - for (const key of Object.keys(argv)) { - let isMatch = false; - - // debug / debug-brk / debug-port / inspect / inspect-brk / inspect-port - if (match(key, [ /^debug.*/, /^inspect.*/ ])) { - isMatch = true; - // extract debug port - if (debugPort === undefined || typeof argv[key] === 'number') { - debugPort = argv[key]; - } - } else if (match(key, [ 'es_staging', 'expose_debug_as', /^harmony.*/ ])) { - isMatch = true; - } - - if (isMatch) { - execArgvObj[key] = argv[key]; - argv[key] = undefined; - // also remove `debugBrk` - argv[changeCase.camelCase(key)] = undefined; - } + + // extract from command argv + debugPort = findDebugPort(argv); + execArgvObj = extractExecArgv(argv); + + // extract from WebStorm env `$NODE_DEBUG_OPTION` + if (context.env.NODE_DEBUG_OPTION) { + console.log('Use $NODE_DEBUG_OPTION: %s', context.env.NODE_DEBUG_OPTION); + const argvFromEnv = parser(context.env.NODE_DEBUG_OPTION); + debugPort = findDebugPort(argvFromEnv); + Object.assign(execArgvObj, extractExecArgv(argvFromEnv)); } context.execArgv = this.helper.unparseArgv(execArgvObj); @@ -50,4 +40,35 @@ class Command extends BaseCommand { } } +function match(key, arr) { + return arr.some(x => x instanceof RegExp ? x.test(key) : x === key); // eslint-disable-line no-confusing-arrow +} + +function findDebugPort(argv) { + let debugPort; + + for (const key of Object.keys(argv)) { + if (match(key, [ /^debug.*/, /^inspect.*/ ]) && typeof argv[key] === 'number') { + debugPort = argv[key]; + } + } + return debugPort; +} + +// pick and remove all execArgv from origin `argv` +function extractExecArgv(argv) { + const execArgvObj = {}; + for (const key of Object.keys(argv)) { + // debug / debug-brk / debug-port / inspect / inspect-brk / inspect-port + if (match(key, [ /^debug.*/, /^inspect.*/, 'es_staging', 'expose_debug_as', /^harmony.*/ ])) { + execArgvObj[key] = argv[key]; + // remove from origin obj + argv[key] = undefined; + // also remove `debugBrk` + argv[changeCase.camelCase(key)] = undefined; + } + } + return execArgvObj; +} + module.exports = Command; diff --git a/package.json b/package.json index 3cd1c93d..b5fdcc53 100644 --- a/package.json +++ b/package.json @@ -11,17 +11,19 @@ "autod": "^2.9.0", "change-case": "^3.0.1", "co-mocha": "^1.2.0", - "common-bin": "^2.4.0", - "debug": "^2.6.8", + "common-bin": "^2.6.1", + "debug": "^3.0.1", "detect-port": "^1.2.1", "egg-utils": "^2.2.0", "globby": "^6.1.0", "intelli-espower-loader": "^1.0.1", "mocha": "^3.5.0", - "mz-modules": "^1.0.0", + "mz-modules": "^2.0.0", "nyc": "^11.1.0", "power-assert": "^1.4.4", + "semver": "^5.4.1", "test-exclude": "^4.1.1", + "yargs-parser": "^7.0.0", "ypkgfiles": "^1.4.0" }, "devDependencies": { @@ -32,8 +34,8 @@ "cross-env": "^3.1.3", "egg-ci": "^1.8.0", "enzyme": "^2.0.0", - "eslint": "^4.3.0", - "eslint-config-egg": "^5.0.0", + "eslint": "^4.5.0", + "eslint-config-egg": "^5.1.0", "jsdom": "^8.0.1", "mm": "^2.1.0", "mz": "^2.6.0", diff --git a/test/egg-bin.test.js b/test/egg-bin.test.js index 6f51133c..4c2ba2c0 100644 --- a/test/egg-bin.test.js +++ b/test/egg-bin.test.js @@ -10,7 +10,7 @@ describe('test/egg-bin.test.js', () => { describe('global options', () => { it('should show version', done => { coffee.fork(eggBin, [ '--version' ], { cwd }) - .debug() + // .debug() .expect('stdout', /\d+\.\d+\.\d+/) .expect('code', 0) .end(done); diff --git a/test/fixtures/demo-app/node_modules/aliyun-egg/index.js b/test/fixtures/demo-app/node_modules/aliyun-egg/index.js index 77b977db..95608e45 100644 --- a/test/fixtures/demo-app/node_modules/aliyun-egg/index.js +++ b/test/fixtures/demo-app/node_modules/aliyun-egg/index.js @@ -6,4 +6,10 @@ exports.startCluster = options => { console.log('process.execArgv:', process.execArgv); } console.log('NODE_ENV: %s', process.env.NODE_ENV); + + // make sure exit + setTimeout(function() { + console.log('exist by setTimeout'); + process.exit(0); + }, 3000); }; diff --git a/test/lib/cmd/autod.test.js b/test/lib/cmd/autod.test.js index 89b508bc..60024762 100644 --- a/test/lib/cmd/autod.test.js +++ b/test/lib/cmd/autod.test.js @@ -6,10 +6,19 @@ const coffee = require('coffee'); const eggBin = require.resolve('../../../bin/egg-bin.js'); describe('test/lib/cmd/autod.test.js', () => { + it('should autod modify', function* () { + const cwd = path.join(__dirname, '../../fixtures/autod-missing'); + yield coffee.fork(eggBin, [ 'autod' ], { cwd }) + // .debug() + .expect('stdout', /"urllib": "\d+.\d+.\d+/) + .expect('code', 0) + .end(); + }); + it('should autod check fail', function* () { const cwd = path.join(__dirname, '../../fixtures/autod-missing'); yield coffee.fork(eggBin, [ 'autod', '--check' ], { cwd }) - .debug() + // .debug() .expect('code', 1) .expect('stderr', /\[ERROR\] Missing dependencies: \["urllib"\]/) .end(); @@ -18,7 +27,7 @@ describe('test/lib/cmd/autod.test.js', () => { it('should autod check pass', function* () { const cwd = path.join(__dirname, '../../fixtures/autod-exists'); yield coffee.fork(eggBin, [ 'autod', '--check' ], { cwd }) - .debug() + // .debug() .expect('code', 0) .end(); }); diff --git a/test/lib/cmd/cov.test.js b/test/lib/cmd/cov.test.js index 9d83a4c6..d37883b0 100644 --- a/test/lib/cmd/cov.test.js +++ b/test/lib/cmd/cov.test.js @@ -42,7 +42,7 @@ describe('test/lib/cmd/cov.test.js', () => { mm(process.env, 'TESTS', 'test/**/*.test.js'); mm(process.env, 'NYC_CWD', cwd); const child = coffee.fork(eggBin, [ 'cov' ], { cwd }) - .debug() + // .debug() .beforeScript(path.join(__dirname, 'mock-win32.js')) .expect('stdout', /should success/) .expect('stdout', /a\.test\.js/) @@ -79,8 +79,7 @@ describe('test/lib/cmd/cov.test.js', () => { child.expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/); } - yield child.expect('code', 0) - .end(); + yield child.expect('code', 0).end(); assert(fs.existsSync(path.join(cwd, 'coverage/coverage-final.json'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov-report/index.html'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov.info'))); @@ -101,8 +100,7 @@ describe('test/lib/cmd/cov.test.js', () => { child.expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/); } - yield child.expect('code', 0) - .end(); + yield child.expect('code', 0).end(); assert(fs.existsSync(path.join(cwd, 'coverage/coverage-final.json'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov-report/index.html'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov.info'))); @@ -123,8 +121,7 @@ describe('test/lib/cmd/cov.test.js', () => { child.expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/); } - yield child.expect('code', 0) - .end(); + yield child.expect('code', 0).end(); assert(fs.existsSync(path.join(cwd, 'coverage/coverage-final.json'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov-report/index.html'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov.info'))); diff --git a/test/lib/cmd/debug.test.js b/test/lib/cmd/debug.test.js index f5801a12..594cffa3 100644 --- a/test/lib/cmd/debug.test.js +++ b/test/lib/cmd/debug.test.js @@ -13,7 +13,7 @@ describe('test/lib/cmd/debug.test.js', () => { it('should startCluster success', () => { return coffee.fork(eggBin, [ 'debug' ], { cwd }) - .debug() + // .debug() .expect('stderr', /Debugger listening/) // node 8 missing "chrome-devtools" url // .expect('stderr', /chrome-devtools:/) @@ -22,17 +22,26 @@ describe('test/lib/cmd/debug.test.js', () => { .end(); }); - it('should startCluster with port', done => { - coffee.fork(eggBin, [ 'debug', '--port', '6001' ], { cwd }) + it('should startCluster with port', () => { + return coffee.fork(eggBin, [ 'debug', '--port', '6001' ], { cwd }) // .debug() .expect('stderr', /Debugger listening/) .expect('stdout', /"port":6001/) .expect('stdout', /"workers":1/) .expect('stdout', /"baseDir":".*?demo-app"/) .expect('stdout', /"framework":".*?aliyun-egg"/) - .expect('stdout', /--inspect/) .expect('code', 0) - .end(done); + .end(); + }); + + it('should debug with $NODE_DEBUG_OPTION', () => { + const env = Object.assign({}, process.env, { NODE_DEBUG_OPTION: '--inspect=5555' }); + return coffee.fork(eggBin, [ 'debug' ], { cwd, env }) + // .debug() + .expect('stderr', /Debugger listening.*5555/) + .expect('stdout', /"workers":1/) + .expect('code', 0) + .end(); }); describe('auto detect available port', () => { @@ -44,13 +53,13 @@ describe('test/lib/cmd/debug.test.js', () => { after(() => server.close()); - it('should auto detect available port', done => { - coffee.fork(eggBin, [ 'debug' ], { cwd }) + it('should auto detect available port', () => { + return coffee.fork(eggBin, [ 'debug' ], { cwd }) // .debug() .expect('stdout', /,"workers":1/) .expect('stderr', /\[egg-bin] server port 7001 is in use/) .expect('code', 0) - .end(done); + .end(); }); }); });