refactor.. feature.ready() method.. --stack paths now scan ws modules
This commit is contained in:
44
lib/feature.js
Normal file
44
lib/feature.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feature interface.
|
||||||
|
*/
|
||||||
|
class Feature {
|
||||||
|
constructor (localWebServer) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return one or more options definitions to collect command-line input
|
||||||
|
* @returns {OptionDefinition|OptionDefinition[]}
|
||||||
|
*/
|
||||||
|
optionDefinitions () {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return one of more middleware functions with three args (req, res and next). Can be created by express, Koa or hand-rolled.
|
||||||
|
*/
|
||||||
|
middleware (options) {}
|
||||||
|
|
||||||
|
expandStack () {
|
||||||
|
const flatten = require('reduce-flatten')
|
||||||
|
|
||||||
|
if (this.stack) {
|
||||||
|
const featureStack = this.stack()
|
||||||
|
.map(Feature => new Feature())
|
||||||
|
|
||||||
|
this.optionDefinitions = function () {
|
||||||
|
return featureStack
|
||||||
|
.map(feature => feature.optionDefinitions && feature.optionDefinitions())
|
||||||
|
.filter(definitions => definitions)
|
||||||
|
.reduce(flatten, [])
|
||||||
|
}
|
||||||
|
this.middleware = function (options, view) {
|
||||||
|
return featureStack
|
||||||
|
.map(feature => feature.middleware(options, view))
|
||||||
|
.reduce(flatten, [])
|
||||||
|
.filter(mw => mw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Feature
|
@ -1,22 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
// /Users/lloydb/Documents/lws/local-web-server/lib/local-web-server.js:307
|
|
||||||
// console.error(usage)
|
|
||||||
// ^
|
|
||||||
//
|
|
||||||
// ReferenceError: usage is not defined
|
|
||||||
// at parseCommandLineOptions (/Users/lloydb/Documents/lws/local-web-server/lib/local-web-server.js:307:19)
|
|
||||||
// at new LocalWebServer (/Users/lloydb/Documents/lws/local-web-server/lib/local-web-server.js:46:47)
|
|
||||||
// at Object.<anonymous> (/Users/lloydb/Documents/lws/local-web-server/bin/cli.js:4:1)
|
|
||||||
// at Module._compile (module.js:556:32)
|
|
||||||
// at Object.Module._extensions..js (module.js:565:10)
|
|
||||||
// at Module.load (module.js:473:32)
|
|
||||||
// at tryModuleLoad (module.js:432:12)
|
|
||||||
// at Function.Module._load (module.js:424:3)
|
|
||||||
// at Module.runMain (module.js:590:10)
|
|
||||||
// at run (bootstrap_node.js:394:7)
|
|
||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const flatten = require('reduce-flatten')
|
const flatten = require('reduce-flatten')
|
||||||
const arrayify = require('array-back')
|
const arrayify = require('array-back')
|
||||||
@ -113,6 +97,12 @@ class LocalWebServer {
|
|||||||
} else {
|
} else {
|
||||||
this.view = new CliView(this)
|
this.view = new CliView(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const feature of this.features) {
|
||||||
|
if (feature.ready) {
|
||||||
|
feature.ready(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,39 +178,25 @@ class LocalWebServer {
|
|||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of Feature instances, given their module paths/names.
|
||||||
|
* @return {feature[]}
|
||||||
|
*/
|
||||||
_buildFeatureStack (featurePaths) {
|
_buildFeatureStack (featurePaths) {
|
||||||
|
const FeatureBase = require('./feature')
|
||||||
return featurePaths
|
return featurePaths
|
||||||
.map(featurePath => loadStack(featurePath))
|
.map(featurePath => loadFeature(featurePath))
|
||||||
.map(Feature => new Feature())
|
.map(Feature => new Feature(this))
|
||||||
.map(feature => {
|
.map(feature => FeatureBase.prototype.expandStack.call(feature))
|
||||||
if (feature.stack) {
|
|
||||||
const featureStack = feature.stack()
|
|
||||||
.map(Feature => new Feature())
|
|
||||||
|
|
||||||
feature.optionDefinitions = function () {
|
|
||||||
return featureStack
|
|
||||||
.map(feature => feature.optionDefinitions && feature.optionDefinitions())
|
|
||||||
.filter(definitions => definitions)
|
|
||||||
.reduce(flatten, [])
|
|
||||||
}
|
|
||||||
feature.middleware = function (options, view) {
|
|
||||||
return featureStack
|
|
||||||
.map(feature => feature.middleware(options, view))
|
|
||||||
.reduce(flatten, [])
|
|
||||||
.filter(mw => mw)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return feature
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a module by either path or name.
|
* Load a module and verify it's of the correct type
|
||||||
* @returns {object}
|
* @returns {Feature}
|
||||||
*/
|
*/
|
||||||
function loadStack (modulePath) {
|
function loadFeature (modulePath) {
|
||||||
const isModule = module => module.prototype && (module.prototype.middleware || module.prototype.stack)
|
const isModule = module => module.prototype && (module.prototype.middleware || module.prototype.stack || module.prototype.ready)
|
||||||
if (isModule(modulePath)) return modulePath
|
if (isModule(modulePath)) return modulePath
|
||||||
const module = loadModule(modulePath)
|
const module = loadModule(modulePath)
|
||||||
if (module) {
|
if (module) {
|
||||||
@ -238,6 +214,14 @@ function loadStack (modulePath) {
|
|||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
function loadModule (modulePath) {
|
||||||
let module
|
let module
|
||||||
const tried = []
|
const tried = []
|
||||||
@ -256,6 +240,16 @@ function loadModule (modulePath) {
|
|||||||
tried.push(modulePath)
|
tried.push(modulePath)
|
||||||
if (foundPath2) {
|
if (foundPath2) {
|
||||||
module = require(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,6 +257,21 @@ function loadModule (modulePath) {
|
|||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of available IPv4 network interfaces
|
||||||
|
* @example
|
||||||
|
* [ { address: 'mbp.local' },
|
||||||
|
* { address: '127.0.0.1',
|
||||||
|
* netmask: '255.0.0.0',
|
||||||
|
* family: 'IPv4',
|
||||||
|
* mac: '00:00:00:00:00:00',
|
||||||
|
* internal: true },
|
||||||
|
* { address: '192.168.1.86',
|
||||||
|
* netmask: '255.255.255.0',
|
||||||
|
* family: 'IPv4',
|
||||||
|
* mac: 'd0:a6:37:e9:86:49',
|
||||||
|
* internal: false } ]
|
||||||
|
*/
|
||||||
function getIPList () {
|
function getIPList () {
|
||||||
const flatten = require('reduce-flatten')
|
const flatten = require('reduce-flatten')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
class Middleware {
|
|
||||||
/**
|
|
||||||
* Return one or more options definitions to collect command-line input
|
|
||||||
* @returns {OptionDefinition|OptionDefinition[]}
|
|
||||||
*/
|
|
||||||
optionDefinitions () {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return one of more middleware functions with three args (req, res and next). Can be created by express, Koa or hand-rolled.
|
|
||||||
*/
|
|
||||||
middleware (localWebServer) {}
|
|
||||||
}
|
|
10
package.json
10
package.json
@ -38,16 +38,16 @@
|
|||||||
"author": "Lloyd Brookes <75pound@gmail.com>",
|
"author": "Lloyd Brookes <75pound@gmail.com>",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-escape-sequences": "^3.0.0",
|
"ansi-escape-sequences": "^3.0.0",
|
||||||
"array-back": "^1.0.3",
|
"array-back": "^1.0.4",
|
||||||
"command-line-args": "^3.0.2",
|
"command-line-args": "^3.0.5",
|
||||||
"command-line-usage": "^3.0.5",
|
"command-line-usage": "^4.0.0",
|
||||||
"config-master": "^2.1.0-0",
|
"config-master": "^2.1.0-0",
|
||||||
"koa": "next",
|
"koa": "next",
|
||||||
"koa-compose": "^3.1.0",
|
"koa-compose": "^3.1.0",
|
||||||
"koa-convert": "^1.2.0",
|
"koa-convert": "^1.2.0",
|
||||||
"local-web-server-default-stack": "github:local-web-server/default-stack",
|
"local-web-server-default-stack": "github:local-web-server/default-stack",
|
||||||
"reduce-flatten": "^1.0.1",
|
"reduce-flatten": "^1.0.1",
|
||||||
"table-layout": "~0.2.3",
|
"table-layout": "~0.4.0",
|
||||||
"typical": "^2.6.0",
|
"typical": "^2.6.0",
|
||||||
"walk-back": "^2.0.1"
|
"walk-back": "^2.0.1"
|
||||||
},
|
},
|
||||||
@ -56,6 +56,6 @@
|
|||||||
"koa-cache-control": "^1.0.0",
|
"koa-cache-control": "^1.0.0",
|
||||||
"koa-livereload": "~0.2.0",
|
"koa-livereload": "~0.2.0",
|
||||||
"req-then": "~0.5.1",
|
"req-then": "~0.5.1",
|
||||||
"tape": "^4.6.2"
|
"tape": "^4.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user