diff --git a/.gitignore b/.gitignore index 3c3629e..6cb772b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +tmp diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 0a54ccb..0000000 --- a/.jshintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "eqeqeq": true, - "globals": { "describe" : false, "it": false, "beforeEach": false }, - "globalstrict": false, - "indent": 4, - "latedef": true, - "laxbreak": true, - "maxparams": 3, - "multistr": true, - "newcap": true, - "node": true, - "quotmark": "double", - "trailing": true, - "undef": true, - "unused": true -} diff --git a/README.md b/README.md index 0ba3ce2..d5b9685 100644 --- a/README.md +++ b/README.md @@ -190,4 +190,6 @@ servers: color: 0.2, 0.2, 1.0, 1.0 ``` +* * * + © 2015 Lloyd Brookes <75pound@gmail.com> diff --git a/bin/ws.js b/bin/ws.js index d2bf914..b424c1e 100755 --- a/bin/ws.js +++ b/bin/ws.js @@ -1,155 +1,8 @@ #!/usr/bin/env node 'use strict' -var dope = require('console-dope') -var http = require('http') -var cliArgs = require('command-line-args') -var o = require('object-tools') -var t = require('typical') -var path = require('path') -var loadConfig = require('config-master') -var homePath = require('home-path') -var logStats = require('stream-log-stats') -var connect = require('connect') -var morgan = require('morgan') -var serveStatic = require('serve-static') -var directory = require('serve-index') -var compress = require('compression') -var cliOptions = require('../lib/cli-options') +const localWebServer = require('../') -/* specify the command line arg definitions and usage forms */ -var cli = cliArgs(cliOptions) -var usage = cli.getUsage({ - title: 'local-web-server', - description: 'Lightweight static web server, zero configuration.', - footer: 'Project home: [underline]{https://github.com/75lb/local-web-server}', - usage: { - forms: [ - '$ ws ', - '$ ws --config', - '$ ws --help' - ] - }, - groups: { - server: 'Server', - misc: 'Misc' - } -}) - -/* parse command line args */ -try { - var wsOptions = cli.parse() -} catch (err) { - halt(err.message) -} - -/* Load and merge together options from -- ~/.local-web-server.json -- {cwd}/.local-web-server.json -- the `local-web-server` property of {cwd}/package.json -*/ -var storedConfig = loadConfig( - path.join(homePath(), '.local-web-server.json'), - path.join(process.cwd(), '.local-web-server.json'), - { jsonPath: path.join(process.cwd(), 'package.json'), configProperty: 'local-web-server' } -) - -var builtInDefaults = { - port: 8000, - directory: process.cwd(), - 'refresh-rate': 500, - mime: {} -} - -/* override built-in defaults with stored config and then command line args */ -wsOptions.server = o.extend(builtInDefaults, storedConfig, wsOptions.server) - -/* user input validation */ -if (!t.isNumber(wsOptions.server.port)) { - halt('please supply a numeric port value') -} - -if (wsOptions.misc.config) { - dope.log('Stored config: ') - dope.log(storedConfig) - process.exit(0) -} else if (wsOptions.misc.help) { - dope.log(usage) -} else { - process.on('SIGINT', function () { - dope.showCursor() - dope.log() - process.exit(0) - }) - - dope.hideCursor() - launchServer() - - /* write launch information to stderr (stdout is reserved for web log output) */ - if (path.resolve(wsOptions.server.directory) === process.cwd()) { - dope.error('serving at %underline{%s}', 'http://localhost:' + wsOptions.server.port) - } else { - dope.error('serving %underline{%s} at %underline{%s}', wsOptions.server.directory, 'http://localhost:' + wsOptions.server.port) - } -} - -function halt (message) { - dope.red.log('Error: %s', message) - dope.log(usage) - process.exit(1) -} - -function launchServer () { - var app = connect() - - /* enable cross-origin requests on all resources */ - app.use(function (req, res, next) { - res.setHeader('Access-Control-Allow-Origin', '*') - next() +localWebServer() + .listen(8000, () => { + console.log(`listening`) }) - - if (wsOptions.server['log-format'] !== 'none') app.use(getLogger()) - - /* --compress enables compression */ - if (wsOptions.server.compress) app.use(compress()) - - /* set the mime-type overrides specified in the config */ - serveStatic.mime.define(wsOptions.server.mime) - - /* enable static file server, including directory browsing support */ - app.use(serveStatic(path.resolve(wsOptions.server.directory))) - .use(directory(path.resolve(wsOptions.server.directory), { icons: true })) - - /* launch server */ - http.createServer(app) - .on('error', function (err) { - if (err.code === 'EADDRINUSE') { - halt('port ' + wsOptions.server.port + ' is already is use') - } else { - halt(err.message) - } - }) - .listen(wsOptions.server.port) -} - -function getLogger () { - /* log using --log-format (if supplied) */ - var logFormat = wsOptions.server['log-format'] - if (logFormat) { - if (logFormat === 'logstalgia') { - /* customised logger :date token, purely to satisfy Logstalgia. */ - morgan.token('date', function () { - var d = new Date() - return (d.getDate() + '/' + d.getUTCMonth() + '/' + d.getFullYear() + ':' + d.toTimeString()) - .replace('GMT', '').replace(' (BST)', '') - }) - logFormat = 'combined' - } - - return morgan(logFormat) - - /* if no `--log-format` was specified, pipe the default format output - into `log-stats`, which prints statistics to the console */ - } else { - return morgan('common', { stream: logStats({ refreshRate: wsOptions.server['refresh-rate'] }) }) - } -} diff --git a/lib/local-web-server.js b/lib/local-web-server.js new file mode 100644 index 0000000..1b1f366 --- /dev/null +++ b/lib/local-web-server.js @@ -0,0 +1,28 @@ +'use strict' +const Koa = require('koa') +const serve = require('koa-static') +const convert = require('koa-convert') +const extend = require('deep-extend') +const serveIndex = require('koa-serve-index') + +/** + * @module local-web-server + */ +module.exports = getApp + +process.on('unhandledRejection', (reason, p) => { + throw reason +}) + +function getApp (options) { + options = extend({ + static: { root: '.' }, + serveIndex: { path: '.' } + }, options) + + const app = new Koa() + + app.use(convert(serve(options.static.root, options.static.options))) + app.use(convert(serveIndex(options.serveIndex.path, options.serveIndex.options))) + return app +} diff --git a/package.json b/package.json index 996f7e1..6dc7eab 100644 --- a/package.json +++ b/package.json @@ -5,25 +5,39 @@ "bin": { "ws": "./bin/ws.js" }, + "main": "lib/local-web-server.js", "license": "MIT", "engines": { "node": ">=0.10.0" }, "scripts": { - "lint": "jshint bin/ws.js; echo;" + "lint": "jshint bin/ws.js; echo;", + "test": "tape test/*.js" }, "repository": "https://github.com/75lb/local-web-server", "author": "Lloyd Brookes", "dependencies": { - "command-line-args": "^1.0.0", + "command-line-args": "^2.0.2", "compression": "^1.0.2", "config-master": "^1", - "connect": "^3.0.0", "console-dope": "~0.3.0", + "deep-extend": "^0.4.0", + "express": "^4.13.3", "home-path": "^1", + "kcors": "^1.0.1", + "koa": "^2.0.0-alpha.3", + "koa-charset": "^1.1.4", + "koa-convert": "^1.1.0", + "koa-json": "^1.1.1", + "koa-morgan": "^0.4.0", + "koa-rewrite": "^1.1.1", + "koa-route": "^2.4.2", + "koa-serve-index": "^1.1.0", + "koa-static": "^1.5.2", "morgan": "^1.0.0", "object-tools": "^2", - "proxy-middleware": "^0.13.0", + "proxy-middleware": "^0.13.1", + "req-then": "^0.2.2", "serve-index": "^1.6.3", "serve-static": "^1.8", "stream-log-stats": "^1", @@ -35,5 +49,8 @@ "php" ] } + }, + "devDependencies": { + "tape": "^4.2.2" } } diff --git a/test/static/file.txt b/test/static/file.txt new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/test/static/file.txt @@ -0,0 +1 @@ +test diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..6bbeeb5 --- /dev/null +++ b/test/test.js @@ -0,0 +1,44 @@ +'use strict' +const test = require('tape') +const request = require('req-then') +const localWebServer = require('../') +const http = require('http') + +test('static', function (t) { + t.plan(1) + const app = localWebServer({ + static: { + root: __dirname + '/static', + options: { + index: 'file.txt' + } + } + }) + const server = http.createServer(app.callback()) + server.listen(8100) + request('http://localhost:8100') + .then(response => { + t.strictEqual(response.data, 'test\n') + }) + .then(() => server.close()) +}) + +test('serve-index', function (t) { + t.plan(2) + const app = localWebServer({ + serveIndex: { + path: __dirname + '/static', + options: { + icons: true + } + } + }) + const server = http.createServer(app.callback()) + server.listen(8100) + request('http://localhost:8100/') + .then(response => { + t.ok(/listing directory/.test(response.data)) + t.ok(/class="icon/.test(response.data)) + }) + .then(() => server.close()) +})