You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.8 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. #!/usr/bin/env node
  2. 'use strict'
  3. const ansi = require('ansi-escape-sequences')
  4. const path = require('path')
  5. const arrayify = require('array-back')
  6. const t = require('typical')
  7. const Tool = require('command-line-tool')
  8. const tool = new Tool()
  9. class Cli {
  10. constructor (options) {
  11. this.options = null
  12. this.app = null
  13. this.middleware = null
  14. options = collectOptions()
  15. this.options = options
  16. if (options.misc.config) {
  17. tool.stop(JSON.stringify(options.server, null, ' '), 0)
  18. } else {
  19. const Koa = require('koa')
  20. const app = new Koa()
  21. this.app = app
  22. const MiddlewareStack = require('./middleware-stack')
  23. this.middleware = new MiddlewareStack(options)
  24. const a = {
  25. compress: options.server.compress,
  26. mime: options.server.mime,
  27. forbid: options.server.forbid,
  28. spa: options.server.spa,
  29. 'no-cache': options.server['no-cache'],
  30. rewrite: options.server.rewrite,
  31. verbose: options.server.verbose,
  32. mocks: options.server.mocks
  33. }
  34. app.on('error', err => {
  35. if (options.server['log-format']) {
  36. console.error(ansi.format(err.message, 'red'))
  37. }
  38. })
  39. }
  40. }
  41. listen () {
  42. this.app.use(this.middleware.getMiddleware())
  43. const options = this.options
  44. if (options.server.https) {
  45. options.server.key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key')
  46. options.server.cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt')
  47. }
  48. if (options.server.key && options.server.cert) {
  49. const https = require('https')
  50. const fs = require('fs')
  51. const serverOptions = {
  52. key: fs.readFileSync(options.server.key),
  53. cert: fs.readFileSync(options.server.cert)
  54. }
  55. const server = https.createServer(serverOptions, this.app.callback())
  56. server.listen(options.server.port, onServerUp.bind(null, options, true))
  57. } else {
  58. this.app.listen(options.server.port, onServerUp.bind(null, options))
  59. }
  60. }
  61. }
  62. function onServerUp (options, isHttps) {
  63. const ipList = getIPList(isHttps)
  64. .map(iface => `[underline]{${isHttps ? 'https' : 'http'}://${iface.address}:${options.server.port}}`)
  65. .join(', ')
  66. console.error(ansi.format(
  67. path.resolve(options.server.directory) === process.cwd()
  68. ? `serving at ${ipList}`
  69. : `serving [underline]{${options.server.directory}} at ${ipList}`
  70. ))
  71. }
  72. function getIPList (isHttps) {
  73. const flatten = require('reduce-flatten')
  74. const os = require('os')
  75. let ipList = Object.keys(os.networkInterfaces())
  76. .map(key => os.networkInterfaces()[key])
  77. .reduce(flatten, [])
  78. .filter(iface => iface.family === 'IPv4')
  79. ipList.unshift({ address: os.hostname() })
  80. return ipList
  81. }
  82. /**
  83. * Return default, stored and command-line options combined
  84. */
  85. function collectOptions () {
  86. const loadConfig = require('config-master')
  87. const stored = loadConfig('local-web-server')
  88. const cli = require('../lib/cli-data')
  89. /* parse command line args */
  90. let options = tool.getOptions(cli.optionDefinitions, cli.usage)
  91. const builtIn = {
  92. port: 8000,
  93. directory: process.cwd()
  94. }
  95. if (options.server.rewrite) {
  96. options.server.rewrite = parseRewriteRules(options.server.rewrite)
  97. }
  98. /* override built-in defaults with stored config and then command line args */
  99. options.server = Object.assign(builtIn, stored, options.server)
  100. validateOptions(options)
  101. return options
  102. }
  103. function parseRewriteRules (rules) {
  104. return rules && rules.map(rule => {
  105. const matches = rule.match(/(\S*)\s*->\s*(\S*)/)
  106. return {
  107. from: matches[1],
  108. to: matches[2]
  109. }
  110. })
  111. }
  112. function validateOptions (options) {
  113. if (!t.isNumber(options.server.port)) {
  114. tool.printError('--port must be numeric')
  115. console.error(tool.usage)
  116. tool.halt()
  117. }
  118. }
  119. module.exports = Cli