Comparing version 1.0.0-pre.8 to 1.0.0-pre2.0
@@ -9,13 +9,20 @@ 'use strict' | ||
write (name, value) { | ||
if (this.options.verbose) { | ||
const output = {} | ||
output[name] = value | ||
console.log(require('util').inspect(output, { depth: 6, colors: true })) | ||
const util = require('./util') | ||
if (name === 'koa.error') { | ||
util.printError(value.stack, 'Middleware error') | ||
} else if (name === 'server.error') { | ||
util.printError(value.stack, 'Server error') | ||
} else { | ||
if (name === 'server.listening') { | ||
const ansi = require('ansi-escape-sequences') | ||
const ipList = value | ||
.map(iface => ansi.format(iface, 'underline')) | ||
.join(', ') | ||
console.error(`Serving at ${ipList}`) | ||
if (this.options.verbose) { | ||
const output = {} | ||
output[name] = value | ||
console.log(require('util').inspect(output, { depth: 6, colors: true })) | ||
} else { | ||
if (name === 'server.listening') { | ||
const ansi = require('ansi-escape-sequences') | ||
const ipList = value | ||
.map(iface => ansi.format(iface, 'underline')) | ||
.join(', ') | ||
console.error(`Serving at ${ipList}`) | ||
} | ||
} | ||
@@ -22,0 +29,0 @@ } |
@@ -188,3 +188,4 @@ 'use strict' | ||
{ | ||
optionList: this.partialDefinitions().filter(def => def.section === 'extension') | ||
optionList: this.partialDefinitions().filter(def => def.section === 'extension'), | ||
hide: 'app' | ||
}, | ||
@@ -279,10 +280,12 @@ { | ||
} else { | ||
const Lws = require('../lws') | ||
const lws = new Lws() | ||
/* load view */ | ||
const View = require('../view') | ||
const ActiveView = View.load(options.view) || require('../cli-view') | ||
options.view = new ActiveView(options) | ||
const view = new ActiveView(options) | ||
lws.on('verbose', view.write.bind(view)) | ||
const Lws = require('../lws') | ||
const lws = new Lws(options) | ||
lws.launch() | ||
const server = lws.create(options) | ||
@@ -294,3 +297,3 @@ if (options.app) { | ||
} | ||
return lws | ||
return server | ||
} | ||
@@ -297,0 +300,0 @@ } |
112
lib/lws.js
@@ -7,2 +7,3 @@ /** | ||
const t = require('typical') | ||
const EventEmitter = require('events') | ||
@@ -12,28 +13,9 @@ /** | ||
*/ | ||
class Lws { | ||
constructor (options) { | ||
this.options = options | ||
const View = require('./view') | ||
this.view = options.view || new View() | ||
/* validate stack */ | ||
const Stack = require('./stack') | ||
if (!(options.stack instanceof Stack)) { | ||
options.stack = Stack.create(options.stack) | ||
} | ||
/** | ||
* Server instance. | ||
* @type {HTTPServer|HTTPSServer} | ||
*/ | ||
this.server = this.createServer(options) | ||
if (t.isDefined(options.maxConnections)) this.server.maxConnections = options.maxConnections | ||
if (t.isDefined(options.keepAliveTimeout)) this.server.keepAliveTimeout = options.keepAliveTimeout | ||
const Koa = require('koa') | ||
this.app = new Koa() | ||
class Lws extends EventEmitter { | ||
propagate (from) { | ||
from.on('verbose', (key, value) => this.emit('verbose', key, value)) | ||
} | ||
/** | ||
* Launch a server. | ||
* Create a listening server. | ||
* @param [options] {object} - Server options | ||
@@ -49,14 +31,36 @@ * @param [options.port] {number} - Port | ||
*/ | ||
launch () { | ||
this.attachView() | ||
const options = this.options | ||
create (options) { | ||
/* validate stack */ | ||
const Stack = require('./stack') | ||
if (!(options.stack instanceof Stack)) { | ||
options.stack = Stack.create(options.stack) | ||
} | ||
/* propagate stack middleware events */ | ||
this.propagate(options.stack) | ||
/** | ||
* Server instance. | ||
* @type {HTTPServer|HTTPSServer} | ||
*/ | ||
const server = this.createServer(options) | ||
if (t.isDefined(options.maxConnections)) server.maxConnections = options.maxConnections | ||
if (t.isDefined(options.keepAliveTimeout)) server.keepAliveTimeout = options.keepAliveTimeout | ||
/* attach to view to server */ | ||
createServerEventStream(server, options) | ||
this.propagate(server) | ||
/* build Koa application, add it to server */ | ||
const Koa = require('koa') | ||
const app = new Koa() | ||
app.on('error', err => { | ||
this.emit('verbose', 'koa.error', err) | ||
}) | ||
const middlewares = options.stack.getMiddlewareFunctions(options) | ||
middlewares.forEach(middleware => this.app.use(middleware)) | ||
this.server.on('request', this.app.callback()) | ||
middlewares.forEach(middleware => app.use(middleware)) | ||
server.on('request', app.callback()) | ||
/* start server */ | ||
this.server.listen(options.port, options.hostname) | ||
server.listen(options.port, options.hostname) | ||
/* emit memory usage stats every 30s */ | ||
const interval = setInterval(() => { | ||
@@ -69,21 +73,7 @@ const byteSize = require('byte-size') | ||
memUsage.external = byteSize(memUsage.external).toString() | ||
this.view.write('process.memoryUsage', memUsage) | ||
this.emit('verbose', 'process.memoryUsage', memUsage) | ||
}, 30000) | ||
interval.unref() | ||
} | ||
attachView () { | ||
const options = this.options | ||
/* attach view to middlewares */ | ||
options.stack.attachView(this.view) | ||
/* attach view to Koa */ | ||
this.app.on('error', err => { | ||
this.view.write('koa-error', err.stack) | ||
util.printError(err, 'Middleware error') | ||
}) | ||
/* attach to view to server */ | ||
attachServerToView(this.server, this.view, options) | ||
return server | ||
} | ||
@@ -97,3 +87,2 @@ | ||
createServer (options) { | ||
let ServerFactory = require('./server-factory') | ||
const loadModule = require('load-module') | ||
@@ -108,5 +97,10 @@ | ||
/* create server */ | ||
/* The base HTTP server factory */ | ||
let ServerFactory = require('./server-factory') | ||
/* use HTTPS server factory */ | ||
if (options.https || (options.key && options.cert) || options.pfx) { | ||
ServerFactory = require('./server-factory-https')(ServerFactory) | ||
/* use user-supplied server factory */ | ||
} else if (options.server) { | ||
@@ -116,3 +110,3 @@ ServerFactory = loadModule(options.server)(ServerFactory) | ||
const factory = new ServerFactory() | ||
factory.view = this.view | ||
this.propagate(factory) | ||
return factory.create(options) | ||
@@ -122,6 +116,9 @@ } | ||
function attachServerToView (server, view, options) { | ||
/** | ||
* Pipe server events into 'verbose' event stream | ||
*/ | ||
function createServerEventStream (server, options) { | ||
function write (name, value) { | ||
return function () { | ||
view.write(name, value) | ||
server.emit('verbose', name, value) | ||
} | ||
@@ -141,15 +138,15 @@ } | ||
socket.id = cId++ | ||
view.write('server.socket.new', socketProperties(socket)) | ||
write('server.socket.new', socketProperties(socket))() | ||
socket.on('connect', write('server.socket.connect', socketProperties(socket, cId))) | ||
socket.on('data', function () { | ||
view.write('server.socket.data', socketProperties(this)) | ||
write('server.socket.data', socketProperties(this))() | ||
}) | ||
socket.on('drain', function () { | ||
view.write('server.socket.drain', socketProperties(this)) | ||
write('server.socket.drain', socketProperties(this))() | ||
}) | ||
socket.on('timeout', function () { | ||
view.write('server.socket.timeout', socketProperties(this)) | ||
write('server.socket.timeout', socketProperties(this))() | ||
}) | ||
socket.on('close', function () { | ||
view.write('server.socket.close', socketProperties(this)) | ||
write('server.socket.close', socketProperties(this))() | ||
}) | ||
@@ -161,4 +158,3 @@ socket.on('end', write('server.socket.end', socketProperties(socket, cId))) | ||
server.on('error', err => { | ||
view.write('server.error', err.stack) | ||
util.printError(err, 'Server error') | ||
write('server.error', err.stack)() | ||
}) | ||
@@ -182,3 +178,3 @@ server.on('request', write('server.request')) | ||
} | ||
view.write('server.listening', ipList) | ||
write('server.listening', ipList)() | ||
}) | ||
@@ -185,0 +181,0 @@ } |
@@ -1,2 +0,2 @@ | ||
'use strict' | ||
const EventEmitter = require('events') | ||
@@ -10,7 +10,3 @@ /** | ||
*/ | ||
class Middleware { | ||
constructor () { | ||
this.view = null | ||
} | ||
class Middleware extends EventEmitter { | ||
description () { | ||
@@ -17,0 +13,0 @@ return '[italic]{<description required>}' |
@@ -16,5 +16,5 @@ module.exports = ServerFactory => class HttpsServerFactory extends ServerFactory { | ||
} | ||
this.view.write('server.config', serverOptions) | ||
this.emit('verbose', 'server.config', serverOptions) | ||
return https.createServer(serverOptions) | ||
} | ||
} |
const path = require('path') | ||
const EventEmitter = require('events') | ||
class ServerFactory { | ||
class ServerFactory extends EventEmitter { | ||
constructor (options) { | ||
super() | ||
options = options || {} | ||
} | ||
getDefaultKeyPath () { | ||
@@ -12,3 +17,3 @@ return path.resolve(__dirname, '..', 'ssl', 'private-key.pem') | ||
create () { | ||
this.view.write('server.config', {}) | ||
this.emit('verbose', 'server.config', {}) | ||
return require('http').createServer() | ||
@@ -15,0 +20,0 @@ } |
'use strict' | ||
const ArrayBase = require('array-base') | ||
const flatten = require('reduce-flatten') | ||
const EventEmitter = require('events') | ||
/** | ||
* Array of Middleware instances | ||
* @module stack | ||
*/ | ||
class Stack extends ArrayBase { | ||
attachView (view) { | ||
for (const mw of this) { | ||
mw.view = view | ||
} | ||
} | ||
class EmittingArray extends Array {} | ||
Object.assign(EmittingArray.prototype, EventEmitter.prototype) | ||
class Stack extends EmittingArray { | ||
/** | ||
@@ -37,15 +38,10 @@ * Returns and array of middleware functions | ||
static create (middlewares = [], options) { | ||
const stack = new this() | ||
loadMiddlewareModules(middlewares, options) | ||
static create (mwModules = [], options) { | ||
loadMiddlewareModules(mwModules, options) | ||
const MiddlewareBase = require('./middleware') | ||
const t = require('typical') | ||
stack.load(middlewares.map(mw => { | ||
if (t.isClass(mw)) { | ||
return new mw() | ||
} else { | ||
const Middleware = mw(MiddlewareBase) | ||
return new Middleware() | ||
} | ||
const stack = this.from(mwModules.map(mwModule => { | ||
const Middleware = mwModule(MiddlewareBase) | ||
return new Middleware() | ||
})) | ||
stack.forEach(mw => mw.on('verbose', (key, value) => stack.emit('verbose', key, value))) | ||
return stack | ||
@@ -52,0 +48,0 @@ } |
{ | ||
"name": "lws", | ||
"author": "Lloyd Brookes <75pound@gmail.com>", | ||
"version": "1.0.0-pre.8", | ||
"version": "1.0.0-pre2.0", | ||
"description": "A modular, server application shell for creating a personalised local web server to support productive full-stack Javascript development.", | ||
@@ -6,0 +6,0 @@ "repository": "https://github.com/lwsjs/lws.git", |
@@ -1,2 +0,2 @@ | ||
class Two { | ||
module.exports = Base => class extends Base { | ||
middleware (options) { | ||
@@ -11,3 +11,1 @@ return (ctx, next) => { | ||
} | ||
module.exports = Two |
@@ -11,3 +11,3 @@ 'use strict' | ||
const port = 9200 + this.index | ||
class One { | ||
const One = Base => class extends Base { | ||
middleware (options) { | ||
@@ -20,3 +20,4 @@ return (ctx, next) => { | ||
} | ||
const lws = new Lws({ | ||
const lws = new Lws() | ||
const server = lws.create({ | ||
stack: [ One ], | ||
@@ -26,3 +27,2 @@ https: true, | ||
}) | ||
lws.launch() | ||
const url = require('url') | ||
@@ -32,5 +32,5 @@ const reqOptions = url.parse(`https://127.0.0.1:${port}`) | ||
const response = await request(reqOptions) | ||
lws.server.close() | ||
server.close() | ||
a.strictEqual(response.res.statusCode, 200) | ||
a.strictEqual(response.data.toString(), 'one') | ||
}) |
@@ -9,5 +9,5 @@ 'use strict' | ||
runner.test('http', async function () { | ||
runner.test('lws: simple http', async function () { | ||
const port = 9100 + this.index | ||
class One { | ||
const One = Base => class extends Base { | ||
middleware (options) { | ||
@@ -20,12 +20,12 @@ return (ctx, next) => { | ||
} | ||
const lws = new Lws({ | ||
const lws = new Lws() | ||
const server = lws.create({ | ||
stack: [ One ], | ||
port: port | ||
}) | ||
lws.launch() | ||
const url = require('url') | ||
const response = await request(`http://127.0.0.1:${port}`) | ||
lws.server.close() | ||
server.close() | ||
a.strictEqual(response.res.statusCode, 200) | ||
a.strictEqual(response.data.toString(), 'one') | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
126996
1040