Browse Source

refactor, tests

master
Lloyd Brookes 8 years ago
parent
commit
3d521399f6
  1. 2
      README.md
  2. 2
      lib/cli-data.js
  3. 79
      lib/local-web-server.js
  4. 1
      package.json
  5. 12
      test/test-middleware.js
  6. 36
      test/test.js

2
README.md

@ -8,7 +8,7 @@
***Requires node v4.0.0 or higher. Install the [previous release](https://github.com/75lb/local-web-server/tree/prev) for older node support.*** ***Requires node v4.0.0 or higher. Install the [previous release](https://github.com/75lb/local-web-server/tree/prev) for older node support.***
# local-web-server # local-web-server
An application shell for building a simple, command-line web server for productive web development.
An application shell for building a simple, command-line web server for productive web development. It contains no middleware of its own but will load default-stack unless you specify otherwise.
It is trivial is bundle and deploy with your project. Also deploys to heroku well for demo projects. It is trivial is bundle and deploy with your project. Also deploys to heroku well for demo projects.

2
lib/cli-data.js

@ -4,7 +4,7 @@ exports.optionDefinitions = [
description: 'Web server port.', group: 'server' description: 'Web server port.', group: 'server'
}, },
{ {
name: 'stack', type: String,
name: 'stack', type: String, multiple: true,
description: 'Middleware stack.', group: 'server' description: 'Middleware stack.', group: 'server'
}, },
{ {

79
lib/local-web-server.js

@ -18,13 +18,14 @@ const tool = new CommandLineTool()
* @extends module:middleware-stack * @extends module:middleware-stack
*/ */
class LocalWebServer { class LocalWebServer {
constructor (stack) {
constructor (initOptions) {
initOptions = initOptions || {}
const commandLineArgs = require('command-line-args') const commandLineArgs = require('command-line-args')
const commandLineUsage = require('command-line-usage') const commandLineUsage = require('command-line-usage')
const cli = require('../lib/cli-data') const cli = require('../lib/cli-data')
/* manually scan for any --stack passed, as we may need to display stack options */ /* manually scan for any --stack passed, as we may need to display stack options */
const stackPaths = []
const stackPaths = initOptions.stack || []
const stackIndex = process.argv.indexOf('--stack') const stackIndex = process.argv.indexOf('--stack')
if (stackIndex > -1) { if (stackIndex > -1) {
for (var i = stackIndex + 1; i < process.argv.length; i++) { for (var i = stackIndex + 1; i < process.argv.length; i++) {
@ -38,11 +39,30 @@ class LocalWebServer {
} }
/* load the stack */ /* load the stack */
// if (!stackPaths.length) stackPaths.push('local-web-server-default-stack')
// console.log(stackPaths)
if (!stackPaths.length) stackPaths.push(path.resolve(__dirname, '..', 'node_modules', 'local-web-server-default-stack'))
const stackModules = stackPaths const stackModules = stackPaths
.map(stackPath => loadStack(stackPath)) .map(stackPath => loadStack(stackPath))
.map(Middleware => new Middleware()) .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
})
/* gather stack option definitions and parse the command line */ /* gather stack option definitions and parse the command line */
const middlewareOptionDefinitions = stackModules const middlewareOptionDefinitions = stackModules
@ -67,11 +87,9 @@ class LocalWebServer {
/* combine in stored config */ /* combine in stored config */
const loadConfig = require('config-master') const loadConfig = require('config-master')
const stored = loadConfig('local-web-server') const stored = loadConfig('local-web-server')
options = Object.assign(stored, options.server, options.middleware, options.misc)
options = Object.assign({ port: 8000 }, initOptions, stored, options.server, options.middleware, options.misc)
this.options = options this.options = options
// console.log(options)
if (options.verbose) { if (options.verbose) {
// debug.setLevel(1) // debug.setLevel(1)
} }
@ -95,33 +113,32 @@ class LocalWebServer {
.filter(mw => mw.middleware) .filter(mw => mw.middleware)
.map(mw => mw.middleware) .map(mw => mw.middleware)
.map(middleware => middleware(options)) .map(middleware => middleware(options))
.filter(middleware => middleware)
.reduce(flatten, []) .reduce(flatten, [])
.filter(middleware => middleware)
.map(convert) .map(convert)
this.stack = compose(middlewareStack) this.stack = compose(middlewareStack)
} }
} }
getApplication (options) {
getApplication () {
const Koa = require('koa') const Koa = require('koa')
const app = new Koa() const app = new Koa()
app.use(this.stack) app.use(this.stack)
app.on('error', err => {
if (this.options['log-format']) {
console.error(ansi.format(err.stack, 'red'))
}
})
return app return app
} }
getServer (options) {
const app = this.getApplication(options)
options = this.options
getServer () {
const app = this.getApplication()
const options = this.options
let key = options.key let key = options.key
let cert = options.cert let cert = options.cert
app.on('error', err => {
if (options['log-format']) {
console.error(ansi.format(err.stack, 'red'))
}
})
if (options.https) {
if (options.https && !(key && cert)) {
key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key') key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key')
cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt') cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt')
} }
@ -144,15 +161,19 @@ class LocalWebServer {
return server return server
} }
listen (options, callback) {
options = this.options
const server = this.getServer()
const port = options.port || 8000
server.listen(port, () => {
onServerUp(port, options.directory, server.isHttps)
if (callback) callback()
listen () {
const options = this.options
const server = this._server = this.getServer()
return new Promise ((resolve, reject) => {
server.listen(options.port, () => {
onServerUp(options.port, options.directory, server.isHttps)
resolve(server)
})
}) })
return server
}
close () {
this._server.close()
} }
} }
@ -223,8 +244,8 @@ function loadStack (modulePath) {
} }
} }
} }
if (!module.prototype.middleware) {
tool.halt(new Error('Must supply a Middleware'))
if (!(module && (module.prototype.middleware || module.prototype.stack))) {
tool.halt(new Error('Not valid Middleware: ' + modulePath))
} }
return module return module
} }

1
package.json

@ -46,6 +46,7 @@
"jsdoc-to-markdown": "^1.3.6", "jsdoc-to-markdown": "^1.3.6",
"koa-cache-control": "^1.0.0", "koa-cache-control": "^1.0.0",
"koa-livereload": "~0.2.0", "koa-livereload": "~0.2.0",
"node-fetch": "^1.5.3",
"req-then": "~0.2.4", "req-then": "~0.2.4",
"tape": "^4.6.0" "tape": "^4.6.0"
} }

12
test/test-middleware.js

@ -0,0 +1,12 @@
'use strict'
class TestMiddleware {
middleware (option) {
return function (ctx, next) {
ctx.body = '1234512345'
return next()
}
}
}
module.exports = TestMiddleware

36
test/test.js

@ -0,0 +1,36 @@
'use strict'
const test = require('tape')
const request = require('req-then')
const LocalWebServer = require('../')
const c = require('./common')
const path = require('path')
test('stack', function (t) {
t.plan(2)
const ws = new LocalWebServer({
stack: [ path.resolve(__dirname, 'test-middleware.js') ]
})
const server = ws.getServer()
server.listen(8100, () => {
request('http://localhost:8100/')
.then(c.checkResponse(t, 200, /1234512345/))
.then(server.close.bind(server))
.catch(c.fail(t))
})
})
test('https', function (t) {
t.plan(2)
const ws = new LocalWebServer({
stack: [ path.resolve(__dirname, 'test-middleware.js') ],
https: true,
port: 8100
})
ws.listen()
.then(() => {
request('https://localhost:8100/')
.then(c.checkResponse(t, 200, /1234512345/))
.then(ws.close.bind(ws))
.catch(c.fail(t))
})
})
Loading…
Cancel
Save