| 
									
										
										
										
											2014-02-05 15:28:23 +01:00
										 |  |  | #!/usr/bin/env node
 | 
					
						
							| 
									
										
										
										
											2015-10-30 11:31:59 +00:00
										 |  |  | 'use strict' | 
					
						
							| 
									
										
										
										
											2015-11-08 22:09:07 +00:00
										 |  |  | const localWebServer = require('../') | 
					
						
							| 
									
										
										
										
											2015-11-16 23:02:27 +00:00
										 |  |  | const cliOptions = require('../lib/cli-options') | 
					
						
							| 
									
										
										
										
											2015-11-11 17:53:01 +00:00
										 |  |  | const commandLineArgs = require('command-line-args') | 
					
						
							|  |  |  | const ansi = require('ansi-escape-sequences') | 
					
						
							|  |  |  | const loadConfig = require('config-master') | 
					
						
							|  |  |  | const path = require('path') | 
					
						
							| 
									
										
										
										
											2015-11-17 17:50:37 +00:00
										 |  |  | const s = require('string-tools') | 
					
						
							| 
									
										
										
										
											2015-11-23 10:26:12 +00:00
										 |  |  | const os = require('os') | 
					
						
							| 
									
										
										
										
											2015-11-24 11:46:47 +00:00
										 |  |  | const arrayify = require('array-back') | 
					
						
							| 
									
										
										
										
											2015-11-30 11:06:22 +00:00
										 |  |  | const t = require('typical') | 
					
						
							| 
									
										
										
										
											2014-06-17 00:40:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-11 17:53:01 +00:00
										 |  |  | const cli = commandLineArgs(cliOptions.definitions) | 
					
						
							|  |  |  | const usage = cli.getUsage(cliOptions.usageData) | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  | const stored = loadConfig('local-web-server') | 
					
						
							|  |  |  | const options = collectOptions() | 
					
						
							| 
									
										
										
										
											2015-11-11 17:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-24 11:46:47 +00:00
										 |  |  | if (options.misc.help) stop(usage, 0) | 
					
						
							|  |  |  | if (options.misc.config) stop(JSON.stringify(options.server, null, '  '), 0) | 
					
						
							| 
									
										
										
										
											2015-11-11 17:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-30 11:06:22 +00:00
										 |  |  | validateOptions(options) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-17 17:50:37 +00:00
										 |  |  | const app = localWebServer({ | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  |   static: { | 
					
						
							|  |  |  |     root: options.server.directory, | 
					
						
							|  |  |  |     options: { | 
					
						
							|  |  |  |       hidden: true | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   serveIndex: { | 
					
						
							|  |  |  |     path: options.server.directory, | 
					
						
							|  |  |  |     options: { | 
					
						
							|  |  |  |       icons: true, | 
					
						
							|  |  |  |       hidden: true | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2015-11-16 23:02:27 +00:00
										 |  |  |   log: { | 
					
						
							|  |  |  |     format: options.server['log-format'] | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  |   compress: options.server.compress, | 
					
						
							|  |  |  |   mime: options.server.mime, | 
					
						
							| 
									
										
										
										
											2015-11-17 11:18:25 +00:00
										 |  |  |   forbid: options.server.forbid, | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  |   spa: options.server.spa, | 
					
						
							| 
									
										
										
										
											2015-11-16 13:22:51 +00:00
										 |  |  |   'no-cache': options.server['no-cache'], | 
					
						
							| 
									
										
										
										
											2015-11-17 17:50:37 +00:00
										 |  |  |   rewrite: options.server.rewrite, | 
					
						
							| 
									
										
										
										
											2015-11-24 11:46:47 +00:00
										 |  |  |   verbose: options.server.verbose, | 
					
						
							|  |  |  |   mocks: options.server.mocks | 
					
						
							| 
									
										
										
										
											2015-11-17 17:50:37 +00:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-30 11:06:22 +00:00
										 |  |  | let isHttps = false | 
					
						
							|  |  |  | if (options.server.key && options.server.cert) { | 
					
						
							|  |  |  |   const https = require('https') | 
					
						
							|  |  |  |   const fs = require('fs') | 
					
						
							|  |  |  |   isHttps = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const serverOptions = { | 
					
						
							|  |  |  |     key: fs.readFileSync(options.server.key), | 
					
						
							|  |  |  |     cert: fs.readFileSync(options.server.cert) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const server = https.createServer(serverOptions, app.callback()) | 
					
						
							|  |  |  |   server.listen(options.server.port, onServerUp) | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  |   app.listen(options.server.port, onServerUp) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-11 17:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-24 11:46:47 +00:00
										 |  |  | function stop (msgs, exitCode) { | 
					
						
							|  |  |  |   arrayify(msgs).forEach(msg => console.error(ansi.format(msg))) | 
					
						
							|  |  |  |   process.exit(exitCode) | 
					
						
							| 
									
										
										
										
											2015-11-10 21:50:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-13 11:26:02 +00:00
										 |  |  | function onServerUp () { | 
					
						
							| 
									
										
										
										
											2015-11-23 10:26:12 +00:00
										 |  |  |   const ipList = Object.keys(os.networkInterfaces()) | 
					
						
							|  |  |  |     .map(key => os.networkInterfaces()[key]) | 
					
						
							|  |  |  |     .reduce((prev, curr) => prev = prev.concat(curr), []) | 
					
						
							|  |  |  |     .filter(iface => iface.family === 'IPv4') | 
					
						
							| 
									
										
										
										
											2015-11-30 11:06:22 +00:00
										 |  |  |     .map(iface => `[underline]{${isHttps ? 'https' : 'http'}://${iface.address}:${options.server.port}}`) | 
					
						
							| 
									
										
										
										
											2015-11-23 10:26:12 +00:00
										 |  |  |     .join(', ') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-13 11:26:02 +00:00
										 |  |  |   console.error(ansi.format( | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  |     path.resolve(options.server.directory) === process.cwd() | 
					
						
							| 
									
										
										
										
											2015-11-23 10:27:26 +00:00
										 |  |  |       ? `serving at ${ipList}` | 
					
						
							| 
									
										
										
										
											2015-11-23 10:26:12 +00:00
										 |  |  |       : `serving [underline]{${options.server.directory}} at ${ipList}` | 
					
						
							| 
									
										
										
										
											2015-11-13 11:26:02 +00:00
										 |  |  |   )) | 
					
						
							| 
									
										
										
										
											2015-11-11 17:53:01 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | function collectOptions () { | 
					
						
							|  |  |  |   let options = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* parse command line args */ | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     options = cli.parse() | 
					
						
							|  |  |  |   } catch (err) { | 
					
						
							| 
									
										
										
										
											2015-11-24 11:46:47 +00:00
										 |  |  |     stop([ `[red]{Error}: ${err.message}`, usage ], 1) | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const builtIn = { | 
					
						
							|  |  |  |     port: 8000, | 
					
						
							|  |  |  |     directory: process.cwd(), | 
					
						
							| 
									
										
										
										
											2015-11-16 13:22:51 +00:00
										 |  |  |     forbid: [], | 
					
						
							| 
									
										
										
										
											2015-11-17 11:18:25 +00:00
										 |  |  |     rewrite: [] | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (options.server.rewrite) { | 
					
						
							|  |  |  |     options.server.rewrite = parseRewriteRules(options.server.rewrite) | 
					
						
							| 
									
										
										
										
											2015-11-15 21:15:25 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* override built-in defaults with stored config and then command line args */ | 
					
						
							|  |  |  |   options.server = Object.assign(builtIn, stored, options.server) | 
					
						
							|  |  |  |   return options | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-16 23:02:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | function parseRewriteRules (rules) { | 
					
						
							| 
									
										
										
										
											2015-11-17 11:18:25 +00:00
										 |  |  |   return rules && rules.map(rule => { | 
					
						
							| 
									
										
										
										
											2015-11-16 23:02:27 +00:00
										 |  |  |     const matches = rule.match(/(\S*)\s*->\s*(\S*)/) | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       from: matches[1], | 
					
						
							|  |  |  |       to: matches[2] | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-30 11:06:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | function validateOptions (options) { | 
					
						
							|  |  |  |   function invalid (msg) { | 
					
						
							|  |  |  |     return `[red underline]{Invalid:} [bold]{${msg}}` | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!t.isNumber(options.server.port)) { | 
					
						
							|  |  |  |     stop([ invalid(`--port must be numeric [value=${options.server.port}]`), usage ], 1) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |