diff --git a/bin/cli.js b/bin/cli.js index 1a4a6ff..f188551 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -1,36 +1,5 @@ #!/usr/bin/env node 'use strict' -const path = require('path') - -function onServerUp (port, directory, isHttps) { - const ansi = require('ansi-escape-sequences') - - const ipList = getIPList() - .map(iface => `[underline]{${isHttps ? 'https' : 'http'}://${iface.address}:${port}}`) - .join(', ') - - console.error(ansi.format( - path.resolve(directory || '') === process.cwd() - ? `serving at ${ipList}` - : `serving [underline]{${directory}} at ${ipList}` - )) -} - -function getIPList () { - const flatten = require('reduce-flatten') - const os = require('os') - - let ipList = Object.keys(os.networkInterfaces()) - .map(key => os.networkInterfaces()[key]) - .reduce(flatten, []) - .filter(iface => iface.family === 'IPv4') - ipList.unshift({ address: os.hostname() }) - return ipList -} - const LocalWebServer = require('../') const ws = new LocalWebServer() const server = ws.getServer() -server.on('listening', function () { - onServerUp(ws.options.port, ws.options['static.root'], server.isHttps) -}) diff --git a/lib/cli-data.js b/lib/cli-data.js index 716326b..c7a3e96 100644 --- a/lib/cli-data.js +++ b/lib/cli-data.js @@ -29,7 +29,11 @@ exports.optionDefinitions = [ }, { name: 'verbose', type: Boolean, alias: 'v', - description: 'Verbose output, useful for debugging.', group: 'misc' + description: 'Verbose output.', group: 'misc' + }, + { + name: 'debug', type: Boolean, + description: 'Very verbose output, intended for debugging.', group: 'misc' }, { name: 'version', type: Boolean, diff --git a/lib/local-web-server.js b/lib/local-web-server.js index c45e55a..25bd0bb 100644 --- a/lib/local-web-server.js +++ b/lib/local-web-server.js @@ -4,6 +4,7 @@ const path = require('path') const CommandLineTool = require('command-line-tool') const flatten = require('reduce-flatten') const arrayify = require('array-back') +const ansi = require('ansi-escape-sequences') /** * @module local-web-server @@ -42,30 +43,8 @@ class LocalWebServer { /* if the user did not supply a stack, use the default */ if (!stackPaths.length) stackPaths.push(path.resolve(__dirname, '..', 'node_modules', 'local-web-server-default-stack')) - /* load the stack */ - const stackModules = stackPaths - .map(stackPath => loadStack(stackPath)) - .map(Middleware => new Middleware()) - .map(module => { - if (module.stack) { - const featureStack = module.stack() - module.optionDefinitions = function () { - return featureStack - .map(Feature => new Feature()) - .map(feature => feature.optionDefinitions && feature.optionDefinitions()) - .filter(definitions => definitions) - .reduce(flatten, []) - } - module.middleware = function (options) { - return featureStack - .map(Feature => new Feature()) - .map(feature => feature.middleware(options)) - .reduce(flatten, []) - .filter(mw => mw) - } - } - return module - }) + /* build the stack */ + const stackModules = buildStack(stackPaths, this.onVerbose.bind(this), this.onDebug.bind(this)) /* gather stack option definitions and parse the command line */ const middlewareOptionDefinitions = stackModules @@ -112,7 +91,14 @@ class LocalWebServer { this.options = options if (options.verbose) { - // debug.setLevel(1) + stackModules + .filter(mw => mw.on) + .forEach(mw => mw.on('verbose', onVerbose)) + } + if (options.debug) { + stackModules + .filter(mw => mw.on) + .forEach(mw => mw.on('debug', onDebug)) } /* --config */ @@ -147,12 +133,7 @@ class LocalWebServer { app.use(compose(middlewareStack)) app.on('error', err => { - const defaultLogInUse = this.stack.some(mw => mw.constructor.name === 'Log') - if (defaultLogInUse) { - if (this.options['log.format']) console.error(ansi.format(err.stack, 'red')) - } else { - console.error(ansi.format(err.stack, 'red')) - } + console.error(ansi.format(err.stack, 'red')) }) return app } @@ -185,9 +166,27 @@ class LocalWebServer { server = http.createServer(app.callback()) } - server.listen(options.port, onListening) + const tableLayout = require('table-layout') + + server.listen(options.port, function () { + const ipList = getIPList() + .map(iface => `[underline]{${server.isHttps ? 'https' : 'http'}://${iface.address}:${options.port}}`) + .join(', ') + console.error(ansi.format('Serving at', 'bold'), ansi.format(ipList)) + }) return server } + + onVerbose (title, msg) { + if (this.options.verbose) { + console.error(ansi.format(title, 'bold'), msg) + } + } + onDebug (title, msg) { + if (this.options.debug) { + console.error(ansi.format(title, 'bold'), msg) + } + } } /** @@ -234,4 +233,49 @@ function isModule (module) { return module.prototype && (module.prototype.middleware || module.prototype.stack) } +function getIPList () { + const flatten = require('reduce-flatten') + const os = require('os') + + let ipList = Object.keys(os.networkInterfaces()) + .map(key => os.networkInterfaces()[key]) + .reduce(flatten, []) + .filter(iface => iface.family === 'IPv4') + ipList.unshift({ address: os.hostname() }) + return ipList +} + +function buildStack (stackPaths, onVerbose, onDebug) { + return stackPaths + .map(stackPath => loadStack(stackPath)) + .map(Middleware => new Middleware()) + .map(module => { + if (module.stack) { + const featureStack = module.stack() + .map(Feature => new Feature()) + .map(feature => { + if (feature.on) { + feature.on('verbose', onVerbose) + feature.on('debug', onDebug) + } + return feature + }) + + module.optionDefinitions = function () { + return featureStack + .map(feature => feature.optionDefinitions && feature.optionDefinitions()) + .filter(definitions => definitions) + .reduce(flatten, []) + } + module.middleware = function (options) { + return featureStack + .map(feature => feature.middleware(options)) + .reduce(flatten, []) + .filter(mw => mw) + } + } + return module + }) +} + module.exports = LocalWebServer