Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lws

Package Overview
Dependencies
Maintainers
1
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lws - npm Package Compare versions

Comparing version 1.0.0-pre.4 to 1.0.0-pre.5

.npmignore

5

bin/cli.js
#!/usr/bin/env node
'use strict'
const Lws = require('../')
const lws = new Lws()
lws.start()
require('../lib/cli-app').run()

33

lib/cli-view.js
'use strict'
const ansi = require('ansi-escape-sequences')
const t = require('typical')
class CliView {
log (msg) {
process.stdout.write(msg)
constructor (options) {
this.options = options
}
start (config) {
// console.error(`START: ${this.constructor.name}`)
// console.error(require('util').inspect(config, { depth: 1, colors: true }))
write (name, value) {
if (this.options.verbose) {
const output = { name }
if (t.isDefined(value)) output.value = value
console.log(output)
} else {
if (name === 'log') {
console.log(value.trim())
} 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}`)
}
}
}
verbose (title, msg) {
msg = require('util').inspect(msg, { depth: 1, colors: true })
console.error(`${title} ${msg}`)
}
end () {}
error (err) {
console.error(ansi.format(`Error: ${err.message}`, 'red'))
}
}
module.exports = CliView

@@ -1,26 +0,31 @@

'use strict'
const path = require('path')
const arrayify = require('array-back')
const ansi = require('ansi-escape-sequences')
const util = require('./util')
const t = require('typical')
/**
*Creating command-line web servers suitable for full-stack javascript development.
* @module lws
*/
class Lws {
constructor (options) {
this.options = options
/**
* @alias module:lws
* @example
* const Lws = require('lws')
* const lws = new Lws()
* lws.start({ https: true})
*/
class Lws {
/* validate stack */
const Stack = require('./stack')
if (!(options.stack instanceof Stack)) {
options.stack = Stack.create(options.stack)
}
/* create server */
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()
}
/**
* Create server,
* @param [options] {object} - Server options
* @param [options.port] {number} - Port
* @param [options.hostname] {string} -The hostname (or IP address) to listen on. Defaults to 0.0.0.0.
* @param [options.config-file] {string} - Config file, defaults to 'lws.config.js'.
* @param [options.configFile] {string} - Config file, defaults to 'lws.config.js'.
* @param [options.stack] {string[]|Features[]} - Array of feature classes, or filenames of modules exporting a feature class.
* @param [options.moduleDir] {string[]} - One or more directories to search for feature modules.
* @param [options.https] {boolean} - Enable HTTPS using a built-in key and cert, registered to the domain 127.0.0.1.

@@ -30,211 +35,109 @@ * @param [options.key] {string} - SSL key. Supply along with --cert to launch a https server.

*/
constructor (options) {
this.options = Object.assign({}, options)
if (this.options.stack) this.options.stack = arrayify(this.options.stack)
launch () {
this.attachView()
const options = this.options
/**
* The [Koa application](https://github.com/koajs/koa/blob/master/docs/api/index.md#application) instance in use.
* @type {Koa}
*/
this.app = null
/* build Koa application, add it to server */
const middlewares = options.stack.getMiddlewareFunctions(options)
middlewares.forEach(middleware => this.app.use(middleware))
this.server.on('request', this.app.callback())
/**
* The node server in use, an instance of either [http.Server](https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_server) or [https.Server](https://nodejs.org/dist/latest-v7.x/docs/api/https.html#https_class_https_server).
* @type {http.Server|https.Server}
*/
this.server = null
/**
* Feature instances
* @type {Feature[]}
*/
this.features = null
/* start server */
this.server.listen(options.port, options.hostname)
}
/**
* Start the app.
*/
start () {
this.options.stack = util.expandStack(this.options.stack)
let cli
try {
cli = util.parseCommandLineOptions(util.getOptionDefinitions(this.options.stack))
} catch (err) {
if (err.name === 'UNKNOWN_OPTION') {
halt(`${err.message}. Use --help/-h to see all options.`)
} else {
halt(err.stack)
}
}
const builtInDefaults = { port: 8000 }
const optionsSoFar = util.deepMerge({}, builtInDefaults, this.options, cli.options._all)
attachView () {
const options = this.options
/* load view */
const View = require('./view')
let ActiveView = View.load(options.view) || require('./cli-view')
this.view = new ActiveView(options)
const storedOptions = this.getStoredConfig(optionsSoFar['config-file'])
storedOptions.stack = util.expandStack(storedOptions.stack)
this.options = util.deepMerge({}, builtInDefaults, this.options, storedOptions, cli.options._all)
/* attach view to middlewares */
options.stack.attachView(this.view)
/* --config */
if (this.options.config) {
console.error(require('util').inspect(this.options, { depth: 6, colors: true }))
process.exit(0)
/* attach view to Koa */
this.app.on('error', err => {
this.view.write('koa-error', err.stack)
util.printError(err, 'Middleware error')
})
/* --version */
} else if (this.options.version) {
console.error(this.getVersion())
process.exit(0)
/* --help */
} else if (this.options.help) {
console.error(this.getUsage())
process.exit(0)
/* launch server and listen */
} else {
const Koa = require('koa')
this.app = new Koa()
this.server = this.getServer()
/* Features should be a collection class with `getMiddlewares`, `expandStack`,
getOptionDefinitions etc on it */
this.features = this.options.stack.map(Feature => new Feature(this))
this.attachView()
const middlewares = this.getMiddlewares(this.features)
middlewares.forEach(middleware => this.app.use(middleware))
this.server.on('request', this.app.callback())
this.server.listen(this.options.port, this.options.hostname)
for (const feature of this.features) {
if (feature.ready) {
feature.ready(this)
}
}
}
/* attach to view to server */
attachServerToView(this.server, this.view, options)
}
/**
* Returns and array of middleware functions from a given stack.
* @returns {middleware[]}
* @ignore
*/
getMiddlewares (features) {
const flatten = require('reduce-flatten')
return features
.filter(feature => feature.middleware)
.map(feature => feature.middleware(Object.assign({}, this.options)))
.reduce(flatten, [])
.filter(mw => mw)
}
/**
* Returns a listening server which processes requests using the middleware supplied.
* Returns a nodejs Server instance.
* @returns {Server}
* @ignore
*/
getServer () {
const options = this.options
let key = options.key
let cert = options.cert
if (options.https && !(key && cert)) {
key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key')
cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt')
createServer (options) {
let ServerFactory = require('./server-factory')
const loadModule = require('load-module')
if (options.https) {
ServerFactory = require('./server-factory-https')(ServerFactory)
} else if (options.server) {
ServerFactory = loadModule(options.server)(ServerFactory)
}
let server = null
if (key && cert) {
const fs = require('fs')
const serverOptions = {
key: fs.readFileSync(key),
cert: fs.readFileSync(cert)
}
const https = require('https')
server = https.createServer(serverOptions)
server.isHttps = true
} else {
const http = require('http')
server = http.createServer()
}
/* on server-up message */
if (!options.testMode) {
server.on('listening', () => {
const ipList = util.getIPList()
.map(iface => `[underline]{${server.isHttps ? 'https' : 'http'}://${iface.address}:${options.port}}`)
.join(', ')
console.error('Serving at', ansi.format(ipList))
})
}
return server
const factory = new ServerFactory()
return factory.create(options)
}
}
/**
* Returns version number
* @returns {string}
* @ignore
*/
getVersion () {
const pkg = require(path.resolve(__dirname, '..', 'package.json'))
return pkg.version
}
attachView () {
const View = require('./cli-view')
const view = new View()
for (const feature of this.features) {
if (feature.on) {
feature.on('log', view.log)
feature.on('error', view.error)
if (this.options.verbose) {
feature.on('start', view.start)
feature.on('verbose', view.verbose)
}
}
function attachServerToView (server, view, options) {
function write (name, value) {
return function () {
view.write(name, value)
}
this.server.on('error', err => halt(`Failed to start server: ${err.message}`))
this.app.on('error', view.error)
}
/**
* Return stored config object.
* @return {object}
* @ignore
*/
getStoredConfig (configFilePath) {
const walkBack = require('walk-back')
const configFile = walkBack(process.cwd(), configFilePath || 'lws.config.js')
if (configFile) {
return require(configFile)
} else {
return {}
}
}
getUsage () {
const commandLineUsage = require('command-line-usage')
const optionDefinitions = util.getOptionDefinitions(this.options.stack)
const usageSections = require('./cli-data').usage(optionDefinitions)
usageSections.unshift(this.getUsageHeader())
usageSections.push(this.getUsageFooter())
return commandLineUsage(usageSections)
}
getUsageHeader () {
function socketProperties (socket) {
return {
header: 'lws',
content: 'A modular server application shell for creating a personalised local web server to support productive, full-stack Javascript development.'
id: socket.id,
bytesRead: socket.bytesRead,
bytesWritten: socket.bytesWritten
}
}
getUsageFooter () {
return {
content: 'Project home: [underline]{https://github.com/lwsjs/lws}'
}
}
}
let cId = 1
server.on('connection', (socket) => {
socket.id = cId++
view.write('socket-new', socketProperties(socket))
socket.on('connect', write('socket-connect', socketProperties(socket, cId)))
socket.on('data', function () {
view.write('socket-data', socketProperties(this))
})
socket.on('drain', function () {
view.write('socket-drain', socketProperties(this))
})
socket.on('timeout', function () {
view.write('socket-timeout', socketProperties(this))
})
socket.on('close', function () {
view.write('socket-close', socketProperties(this))
})
socket.on('end', write('socket-end', socketProperties(socket, cId)))
socket.on('lookup', write('socket-connect', socketProperties(socket, cId)))
})
server.on('close', write('server-close'))
server.on('error', err => {
view.write('server-error', err.stack)
util.printError(err, 'Server error')
})
server.on('request', write('server-request'))
server.on('checkContinue', write('server-checkContinue'))
server.on('checkExpectation', write('server-checkExpectation'))
server.on('clientError', write('server-clientError'))
server.on('connect', write('server-connect'))
server.on('upgrade', write('server-upgrade'))
function halt (msg) {
console.error(ansi.format(msg, 'red'))
process.exit(1)
/* on server-up message */
server.on('listening', () => {
const isSecure = t.isDefined(server.addContext)
const ipList = util.getIPList()
.map(iface => `${isSecure ? 'https' : 'http'}://${iface.address}:${options.port}`)
view.write('server-listening', ipList)
})
}
module.exports = Lws
'use strict'
const path = require('path')
const flatten = require('reduce-flatten')
const arrayify = require('array-back')

@@ -10,100 +7,49 @@ /**

exports.parseCommandLineOptions = parseCommandLineOptions
exports.loadFeature = loadFeature
exports.loadModule = loadModule
exports.deepMerge = deepMerge
exports.camelCaseObject = camelCaseObject
exports.printError = printError
exports.getIPList = getIPList
exports.getOptionDefinitions = getOptionDefinitions
exports.expandStack = expandStack
exports.deepMerge = deepMerge
/**
* Return commandLineArgs output. Expand stack too.
*/
function parseCommandLineOptions (defs) {
/* pass in the optionDefinitions supplied in the constructor options */
const commandLineArgs = require('command-line-args')
const cli = require('./cli-data')
let optionDefinitions = [ ...cli.optionDefinitions, ...defs || [] ]
let options = commandLineArgs(optionDefinitions, { partial: true })
if (options._all.stack && options._all.stack.length) {
options._all.stack = expandStack(options._all.stack)
const stackDefinitions = getOptionDefinitions(options._all.stack)
optionDefinitions = [ ...optionDefinitions, ...stackDefinitions ]
options = commandLineArgs(optionDefinitions)
options._all.stack = options._all.stack ? expandStack(options._all.stack) : []
} else {
options = commandLineArgs(optionDefinitions)
}
return { options, optionDefinitions }
}
function deepMerge (...args) {
const assignWith = require('lodash.assignwith')
const t = require('typical')
/**
* Load a module and verify it's of the correct type
* @returns {Feature}
*/
function loadFeature (modulePath) {
const isModule = module => module.prototype && (module.prototype.middleware || module.prototype.stack || module.prototype.ready || true)
if (isModule(modulePath)) return modulePath
const module = loadModule(modulePath)
if (module) {
if (!isModule(module)) {
const insp = require('util').inspect(module, { depth: 3, colors: true })
const msg = `Not valid Middleware at: ${insp}`
console.error(msg)
process.exit(1)
function customiser (previousValue, newValue, key, object, source) {
/* deep merge plain objects */
if (t.isPlainObject(previousValue) && t.isPlainObject(newValue)) {
return assignWith(previousValue, newValue, customiser)
/* overwrite arrays if the new array has items */
} else if (Array.isArray(previousValue) && Array.isArray(newValue) && newValue.length) {
return newValue.slice()
/* ignore incoming arrays if empty */
} else if (Array.isArray(newValue) && !newValue.length) {
return Array.isArray(previousValue) ? previousValue.slice() : previousValue
} else if (!t.isDefined(previousValue) && Array.isArray(newValue)) {
return newValue.slice()
}
} else {
const msg = `No module found for: ${modulePath}`
console.error(msg)
process.exit(1)
}
return module
return assignWith(...args, customiser)
}
/**
* Returns a module, loaded by the first to succeed from
* - direct path
* - 'node_modules/local-web-server-' + path, from current folder upward
* - 'node_modules/' + path, from current folder upward
* - also search local-web-server project node_modules? (e.g. to search for a feature module without need installing it locally)
* @returns {object}
*/
function loadModule (modulePath) {
let module
const tried = []
if (modulePath) {
try {
tried.push(path.resolve(modulePath))
module = require(path.resolve(modulePath))
} catch (err) {
if (!(err && err.code === 'MODULE_NOT_FOUND')) {
throw err
}
const walkBack = require('walk-back')
const foundPath = walkBack(process.cwd(), path.join('node_modules', 'local-web-server-' + modulePath))
tried.push('local-web-server-' + modulePath)
if (foundPath) {
module = require(foundPath)
} else {
const foundPath2 = walkBack(process.cwd(), path.join('node_modules', modulePath))
tried.push(modulePath)
if (foundPath2) {
module = require(foundPath2)
} else {
const foundPath3 = walkBack(path.resolve(__filename, '..'), path.join('node_modules', 'local-web-server-' + modulePath))
if (foundPath3) {
return require(foundPath3)
} else {
const foundPath4 = walkBack(path.resolve(__filename, '..'), path.join('node_modules', modulePath))
if (foundPath4) {
return require(foundPath4)
}
}
}
}
function camelCaseObject (object) {
const camelCase = require('lodash.camelcase')
for (const prop of Object.keys(object)) {
const converted = camelCase(prop)
if (converted !== prop) {
object[converted] = object[prop]
delete object[prop]
}
}
return module
return object
}
function printError (err, title) {
const ansi = require('ansi-escape-sequences')
const now = new Date()
const time = now.toLocaleTimeString()
if (title) console.error(ansi.format(`${time}: [underline red]{${title}}`))
console.error(ansi.format(err.stack, 'red'))
}
/**

@@ -126,2 +72,3 @@ * Returns an array of available IPv4 network interfaces

const os = require('os')
const flatten = require('reduce-flatten')

@@ -135,51 +82,1 @@ let ipList = Object.keys(os.networkInterfaces())

}
/**
* Grouped 'middleware'.
* @return {OptionDefinition[]}
*/
function getOptionDefinitions (stack) {
return arrayify(stack)
.map(Feature => new Feature(this))
.filter(feature => feature.optionDefinitions)
.map(feature => feature.optionDefinitions())
.reduce(flatten, [])
.filter(def => def)
.map(def => {
def.group = 'middleware'
return def
})
}
function expandStack (stack) {
if (stack && stack.length) {
stack.forEach((featurePath, index) => {
if (typeof featurePath === 'string') {
stack[index] = loadFeature(featurePath)
}
})
return stack
} else {
return []
}
}
function deepMerge (...args) {
const assignWith = require('lodash.assignwith')
const t = require('typical')
function customiser (objValue, srcValue, key, object, source) {
if (t.isPlainObject(objValue) && t.isPlainObject(srcValue)) {
return assignWith(objValue, srcValue, customiser)
} else if (Array.isArray(objValue) && Array.isArray(srcValue)) {
for (const value of srcValue) {
objValue.push(value)
}
return objValue
} else if (!t.isDefined(objValue) && Array.isArray(srcValue)) {
return srcValue.slice()
}
}
return assignWith(...args, customiser)
}
{
"name": "lws",
"author": "Lloyd Brookes <75pound@gmail.com>",
"version": "1.0.0-pre.4",
"version": "1.0.0-pre.5",
"description": "A modular, server application shell for creating a personalised local web server to support productive full-stack Javascript development.",

@@ -18,3 +18,4 @@ "repository": "https://github.com/lwsjs/lws.git",

"test": "test-runner test/*.js",
"docs": "jsdoc2md -t jsdoc2md/README.hbs lib/*.js > README.md; echo"
"docs": "jsdoc2md -t jsdoc2md/README.hbs lib/*.js > README.md; echo",
"cover": "istanbul cover ./node_modules/.bin/test-runner test/*.js || cat coverage/lcov.info | ./node_modules/.bin/coveralls"
},

@@ -24,14 +25,21 @@ "dependencies": {

"array-back": "^1.0.4",
"command-line-args": "^4.0.2",
"array-base": "^1.0.1",
"byte-size": "^3.0.0",
"cli-commands": "^0.3.2",
"command-line-args": "^4.0.6",
"command-line-usage": "^4.0.0",
"koa": "^2.2.0",
"load-module": "^0.2.3",
"lodash.assignwith": "^4.2.0",
"lodash.camelcase": "^4.3.0",
"readable-stream": "^2.2.11",
"reduce-flatten": "^1.0.1",
"typical": "^2.6.0",
"typical": "^2.6.1",
"walk-back": "^3.0.0"
},
"devDependencies": {
"coveralls": "^2.13.1",
"req-then": "^0.6.1",
"test-runner": "^0.3.0"
"test-runner": "^0.4.0"
}
}

@@ -1,5 +0,6 @@

[![view on npm](http://img.shields.io/npm/v/lws.svg)](https://www.npmjs.org/package/lws)
[![npm module downloads](http://img.shields.io/npm/dt/lws.svg)](https://www.npmjs.org/package/lws)
[![view on npm](https://img.shields.io/npm/v/lws.svg)](https://www.npmjs.org/package/lws)
[![npm module downloads](https://img.shields.io/npm/dt/lws.svg)](https://www.npmjs.org/package/lws)
[![Build Status](https://travis-ci.org/lwsjs/lws.svg?branch=master)](https://travis-ci.org/lwsjs/lws)
[![Dependency Status](https://david-dm.org/lwsjs/lws.svg)](https://david-dm.org/lwsjs/lws)
[![Coverage Status](https://coveralls.io/repos/github/lwsjs/lws/badge.svg)](https://coveralls.io/github/lwsjs/lws)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://github.com/feross/standard)

@@ -9,259 +10,6 @@

A modular server application shell for creating a personalised local web server to support productive, full-stack Javascript development.
**Documentation work in progress.**
## Synopsis
`lws` is a command-line tool, install it by running `npm install -g lws`. Here's a quick look at the usage:
```
$ lws --help
lws
A modular server application shell for creating a personalised local web server to support productive, full-stack Javascript development.
Synopsis
$ ws [--verbose] [--config-file file] [<server options>] [<middleware options>]
$ ws --config
$ ws --help
$ ws --version
General
-h, --help Print these usage instructions.
--config Print the active config.
-c, --config-file file Config filename to use, defaults to "lws.config.js".
-v, --verbose Verbose output.
--version Print the version number.
Server
-p, --port number Web server port.
--hostname string The hostname (or IP address) to listen on. Defaults to 0.0.0.0.
--stack feature ... Feature stack.
--key file SSL key. Supply along with --cert to launch a https server.
--cert file SSL cert. Supply along with --key to launch a https server.
--https Enable HTTPS using a built-in key and cert, registered to the domain
127.0.0.1.
Middleware
No middleware specified.
Project home: https://github.com/lwsjs/lws
```
Running `lws` launches a web server.
```
$ lws
Serving at http://mbp.local:8000, http://127.0.0.1:8000, http://192.168.0.32:8000
```
However, by default it's empty. Any resource requested will return `404 Not Found`.
```
$ curl -I http://127.0.0.1:8000/README.md
HTTP/1.1 404 Not Found
Date: Wed, 22 Mar 2017 20:41:07 GMT
Connection: keep-alive
```
So, install one or more features and pass their names to `--stack`. Notice the "Middleware" section of the usage guide now contains additional options added by the `lws-static` feature:
```
$ npm install lws-static
$ npm --stack lws-static --help
...
Middleware
-d, --directory path Root directory, defaults to the current directory.
--static.maxage number Browser cache max-age in milliseconds.
--static.defer If true, serves after `yield next`, allowing any downstream middleware to
respond first.
--static.index path Default file name, defaults to `index.html`.
```
By launching `lws` with this feature we're now able to serve static files.
```
$ lws --stack lws-static
Serving at http://mbp.local:8000, http://127.0.0.1:8000, http://192.168.0.32:8000
$ curl -I http://127.0.0.1:8000/README.md
HTTP/1.1 200 OK
Content-Length: 3286
Last-Modified: Wed, 22 Mar 2017 00:22:21 GMT
Cache-Control: max-age=0
Content-Type: text/x-markdown; charset=utf-8
Date: Wed, 22 Mar 2017 20:39:18 GMT
Connection: keep-alive
```
You can use pre-built features or make your own.
```js
class Feature {
optionDefinitions () {
return [
{ name: 'team', type: String }
]
}
middleware (options) {
return (ctx, next) => {
ctx.body = `Your team: ${options.team}`
await next()
}
}
}
module.exports = Feature
```
If you want a server with all the common features pre-installed, look at [local-web-server](https://github.com/75lb/local-web-server).
## Install
Command-line tool:
```
$ npm install -g lws
```
Install the API for use in nodejs:
```
$ npm install lws --save
```
# API Reference
<a name="module_lws"></a>
## lws
Creating command-line web servers suitable for full-stack javascript development.
* [lws](#module_lws)
* [Lws](#exp_module_lws--Lws) ⏏
* [new Lws([options])](#new_module_lws--Lws_new)
* [.app](#module_lws--Lws.Lws+app) : <code>Koa</code>
* [.server](#module_lws--Lws.Lws+server) : <code>http.Server</code> \| <code>https.Server</code>
* [.features](#module_lws--Lws.Lws+features) : <code>Array.&lt;Feature&gt;</code>
* [.start()](#module_lws--Lws+start)
<a name="exp_module_lws--Lws"></a>
### Lws ⏏
**Kind**: Exported class
<a name="new_module_lws--Lws_new"></a>
#### new Lws([options])
| Param | Type | Description |
| --- | --- | --- |
| [options] | <code>object</code> | Server options |
| [options.port] | <code>number</code> | Port |
| [options.hostname] | <code>string</code> | The hostname (or IP address) to listen on. Defaults to 0.0.0.0. |
| [options.config-file] | <code>string</code> | Config file, defaults to 'lws.config.js'. |
| [options.stack] | <code>Array.&lt;string&gt;</code> \| <code>Array.&lt;Features&gt;</code> | Array of feature classes, or filenames of modules exporting a feature class. |
| [options.https] | <code>boolean</code> | Enable HTTPS using a built-in key and cert, registered to the domain 127.0.0.1. |
| [options.key] | <code>string</code> | SSL key. Supply along with --cert to launch a https server. |
| [options.cert] | <code>string</code> | SSL cert. Supply along with --key to launch a https server. |
**Example**
```js
const Lws = require('lws')
const lws = new Lws()
lws.start({ https: true})
```
<a name="module_lws--Lws.Lws+app"></a>
#### lws.app : <code>Koa</code>
The [Koa application](https://github.com/koajs/koa/blob/master/docs/api/index.md#application) instance in use.
**Kind**: instance property of <code>[Lws](#exp_module_lws--Lws)</code>
<a name="module_lws--Lws.Lws+server"></a>
#### lws.server : <code>http.Server</code> \| <code>https.Server</code>
The node server in use, an instance of either [http.Server](https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_server) or [https.Server](https://nodejs.org/dist/latest-v7.x/docs/api/https.html#https_class_https_server).
**Kind**: instance property of <code>[Lws](#exp_module_lws--Lws)</code>
<a name="module_lws--Lws.Lws+features"></a>
#### lws.features : <code>Array.&lt;Feature&gt;</code>
Feature instances
**Kind**: instance property of <code>[Lws](#exp_module_lws--Lws)</code>
<a name="module_lws--Lws+start"></a>
#### lws.start()
Start the app.
**Kind**: instance method of <code>[Lws](#exp_module_lws--Lws)</code>
# Feature interface
<a name="module_feature"></a>
## feature
* [feature](#module_feature)
* [Feature](#exp_module_feature--Feature) ⏏
* [new Feature(lws)](#new_module_feature--Feature_new)
* [.optionDefinitions()](#module_feature--Feature+optionDefinitions) ⇒ <code>OptionDefinition</code> \| <code>Array.&lt;OptionDefinition&gt;</code>
* [.middleware()](#module_feature--Feature+middleware) ⇒ <code>KoaMiddleware</code>
* [.ready(lws)](#module_feature--Feature+ready)
<a name="exp_module_feature--Feature"></a>
### Feature ⏏
Feature interface.
**Kind**: Exported class
<a name="new_module_feature--Feature_new"></a>
#### new Feature(lws)
localWebServer instance passed to constructor in case feature needs access to http server instance.
| Param | Type |
| --- | --- |
| lws | <code>Lws</code> |
<a name="module_feature--Feature+optionDefinitions"></a>
#### feature.optionDefinitions() ⇒ <code>OptionDefinition</code> \| <code>Array.&lt;OptionDefinition&gt;</code>
Return one or more options definitions to collect command-line input
**Kind**: instance method of <code>[Feature](#exp_module_feature--Feature)</code>
<a name="module_feature--Feature+middleware"></a>
#### feature.middleware() ⇒ <code>KoaMiddleware</code>
Return one of more middleware functions with three args (req, res and next). Can be created by express, Koa or hand-rolled.
**Kind**: instance method of <code>[Feature](#exp_module_feature--Feature)</code>
<a name="module_feature--Feature+ready"></a>
#### feature.ready(lws)
Called once the server is launched and ready to accept connections.
**Kind**: instance method of <code>[Feature](#exp_module_feature--Feature)</code>
| Param | Type |
| --- | --- |
| lws | <code>Lws</code> |
* * *
&copy; 2016-17 Lloyd Brookes \<75pound@gmail.com\>. Documented by [jsdoc-to-markdown](https://github.com/jsdoc2md/jsdoc-to-markdown).

@@ -5,4 +5,5 @@ class Feature {

}
ready () {}
}
module.exports = Feature

@@ -1,9 +0,12 @@

class Feature {
class Two {
middleware (options) {
return (ctx, next) => {
ctx.body += 'two'
ctx.body = (ctx.body || '') + 'two'
}
}
optionDefinitions () {
return [ { name: 'something' }]
}
}
module.exports = Feature
module.exports = Two

@@ -9,28 +9,8 @@ 'use strict'

runner.test('stack: one feature', async function () {
const port = 9000 + this.index
class Feature {
runner.test('http', async function () {
const port = 9100 + this.index
class One {
middleware (options) {
return (ctx, next) => {
ctx.body = 'one'
}
}
}
const lws = new Lws({
stack: Feature,
port: port
})
lws.start()
const response = await request(`http://localhost:${port}`)
lws.server.close()
a.strictEqual(response.data.toString(), 'one')
a.strictEqual(lws.options.stack.length, 1)
})
runner.test('stack: one feature, one feature path', async function () {
const port = 9000 + this.index
class Feature {
middleware (options) {
return (ctx, next) => {
ctx.body = 'one'
next()

@@ -41,90 +21,8 @@ }

const lws = new Lws({
stack: [ Feature, 'test/fixture/two.js' ],
stack: [ One ],
port: port
})
lws.start()
const response = await request(`http://localhost:${port}`)
lws.server.close()
a.strictEqual(response.data.toString(), 'onetwo')
a.strictEqual(lws.options.stack.length, 2)
})
runner.test('stack: one feature, one cli feature path', async function () {
const port = 9000 + this.index
class Feature {
middleware (options) {
return (ctx, next) => {
ctx.body = 'one'
next()
}
}
}
const lws = new Lws({
stack: [ Feature ],
port: port
})
process.argv = [ 'node', 'example.js', '--stack', 'test/fixture/two.js' ]
lws.start()
process.argv = [ 'node', 'example.js' ] // reset as process.argv is global
const response = await request(`http://localhost:${port}`)
lws.server.close()
a.strictEqual(lws.options.stack.length, 2)
a.strictEqual(response.data.toString(), 'onetwo')
})
runner.test('stack: Two features', async function () {
const port = 9000 + this.index
class Feature {
middleware (options) {
return (ctx, next) => {
ctx.body = 'one'
next()
}
}
}
class Feature2 {
middleware (options) {
return (ctx, next) => {
ctx.body += 'two'
next()
}
}
}
const lws = new Lws({
stack: [ Feature, Feature2 ],
port: port
})
lws.start()
const response = await request(`http://localhost:${port}`)
lws.server.close()
a.strictEqual(response.data.toString(), 'onetwo')
a.strictEqual(lws.options.stack.length, 2)
})
runner.skip('--help', function () {
const lws = new Lws()
process.argv = [ 'node', 'script.js', '--help' ]
// need to be able to pass in the output stream in order to test it
})
runner.test('https', async function () {
const port = 9000 + this.index
class Feature {
middleware (options) {
return (ctx, next) => {
ctx.body = 'one'
next()
}
}
}
const lws = new Lws({
stack: [ Feature ],
https: true,
port: port
})
lws.start()
lws.launch()
const url = require('url')
const reqOptions = url.parse(`https://127.0.0.1:${port}`)
reqOptions.rejectUnauthorized = false
const response = await request(reqOptions)
const response = await request(`http://127.0.0.1:${port}`)
lws.server.close()

@@ -131,0 +29,0 @@ a.strictEqual(response.res.statusCode, 200)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc