فهرست منبع

Merge branch 'express' into static

Alan Colon 7 سال پیش
والد
کامیت
49bbba7b4d
9فایلهای تغییر یافته به همراه186 افزوده شده و 6 حذف شده
  1. 3 0
      .dockerignore
  2. 19 0
      Dockerfile
  3. 3 0
      config.js
  4. 39 0
      lib/app.js
  5. 22 0
      lib/server.js
  6. 10 3
      package.json
  7. 41 0
      src/client.js
  8. 8 1
      src/index.js
  9. 41 2
      yarn.lock

+ 3 - 0
.dockerignore

@@ -0,0 +1,3 @@
+.git/
+dist/
+node_modules/

+ 19 - 0
Dockerfile

@@ -0,0 +1,19 @@
+FROM node
+
+RUN npm install -g yarn
+
+EXPOSE 80
+
+ENV NODE_PORT=80 NODE_ENV=production
+
+WORKDIR /app/
+
+COPY package.json /app/
+
+RUN NODE_ENV=development yarn
+
+ADD . /app/
+
+RUN yarn build && yarn
+
+CMD yarn server

+ 3 - 0
config.js

@@ -0,0 +1,3 @@
+module.exports = {
+  port: process.env.NODE_PORT
+}

+ 39 - 0
lib/app.js

@@ -0,0 +1,39 @@
+const http = require('http')
+const express = require('express')
+const morgan = require('morgan')
+const bodyParser = require('body-parser')
+const WebSocket = require('ws')
+const EventEmitter = require('events')
+const chalk = require('chalk')
+const config = require('../config')
+
+const app = module.exports = express()
+
+app.use(morgan('combined'))
+app.use(bodyParser.json())
+app.use(express.static('dist'))
+
+app.ws = new EventEmitter()
+app.listen = (port = config.port || (app.settings.env === 'production' ? 80 : 3000)) => new Promise((resolve, reject) => {
+  app.server = http.createServer(app)
+  app.server.once('error', (err) => {
+    if (err.message.includes('EADDRINUSE') && app.settings.env === 'development' && port < 3999) {
+      console.warn(err.message)
+      resolve(app.listen(port + 1))
+    } else {
+      reject(err)
+    }
+  })
+  app.server.listen(port, () => {
+    app.wss = new WebSocket.Server({ server: app.server })
+    app.wss.on('connection', (...args) => app.ws.emit('connection', ...args))
+    app.wss.on('message', (...args) => app.ws.emit('message', ...args))
+    app.wss.on('close', (...args) => app.ws.emit('close', ...args))
+    app.wss.on('error', (...args) => app.ws.emit('error', ...args))
+    app.server.port = app.server.address().port
+    console.log(`Server running at ${chalk.underline(chalk.blueBright(`http://localhost:${app.server.port}`))}`)
+    resolve()
+  })
+})
+
+module.exports = app

+ 22 - 0
lib/server.js

@@ -0,0 +1,22 @@
+const app = require('./app')
+
+/* TODO: Add handlers */
+
+const connections = []
+
+app.ws.on('connection', ws => {
+  connections.push(ws)
+  ws.on('close', () => {
+    connections.splice(connections.indexOf(ws), 1)
+  })
+  ws.on('message', message => {
+    console.log(message)
+    /* TODO: Add logic */
+  })
+  ws.send('Hello Client')
+})
+
+app.listen().catch((err) => {
+  console.log(err.toString())
+  process.exit(1)
+})

+ 10 - 3
package.json

@@ -6,11 +6,11 @@
   "scripts": {
     "build": "webpack",
     "build:dev": "webpack --watch",
-    "server": "http-server dist",
-    "server:dev": "webpack-dev-server",
+    "server": "node lib/server.js",
+    "server:dev": "nodemon --watch lib lib/server.js",
     "test": "mocha",
     "test:dev": "mocha --watch",
-    "dev": "npm-run-all -p server:dev test:dev"
+    "dev": "npm-run-all -p build:dev server:dev test:dev"
   },
   "author": "",
   "license": "ISC",
@@ -32,5 +32,12 @@
     "webpack-cli": "^3.1.2",
     "webpack-dev-server": "^3.1.14",
     "webpack-livereload-plugin": "^2.2.0"
+  },
+  "dependencies": {
+    "body-parser": "^1.18.3",
+    "chalk": "^2.4.2",
+    "express": "^4.16.4",
+    "morgan": "^1.9.1",
+    "ws": "^6.1.2"
   }
 }

+ 41 - 0
src/client.js

@@ -0,0 +1,41 @@
+const client = new EventTarget()
+const delay = 1000
+const protocol = `ws${location.protocol.substr(4)}`
+const path = location.pathname.split('/').slice(0, -1).join('/')
+const url = `${protocol}//${location.host}${path}`
+
+let _connect = null
+
+const connect = () => {
+  if (_connect == null) {
+    _connect = new Promise(resolve => {
+      const ws = new WebSocket(url)
+      window.ws = ws
+      let connected = false
+      const retry = () => resolve(new Promise(resolve => setTimeout(resolve, delay)).then(connect))
+      const dispatch = evt => client.dispatchEvent(new evt.constructor(evt.type, evt))
+      ws.addEventListener('open', evt => {
+        connected = true
+        dispatch(evt)
+        resolve(ws)
+      })
+      ws.addEventListener('close', evt => {
+        _connect = null
+        dispatch(evt)
+        retry()
+      })
+      ws.addEventListener('message', evt => dispatch(evt))
+      ws.addEventListener('error', evt => {
+        if (!connected) retry()
+        dispatch(evt)
+      })
+    })
+  }
+  return _connect
+}
+
+const send = message => connect().then(ws => ws.send(message))
+
+client.connect = connect
+client.send = send
+module.exports = client

+ 8 - 1
src/index.js

@@ -1,4 +1,11 @@
 require('./index.css')
+const client = require('./client')
 document.addEventListener('DOMContentLoaded', () => {
-  console.log(roboto)
+  client.connect()
+  client.addEventListener('open', () => {
+    client.send('Hello Server')
+  })
+  client.addEventListener('message', evt => {
+    console.log(evt.data)
+  })
 })

+ 41 - 2
yarn.lock

@@ -358,6 +358,11 @@ async-each@^1.0.0:
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
   integrity sha1-GdOGodntxufByF04iu28xW0zYC0=
 
+async-limiter@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
+  integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
+
 async@^1.5.2:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
@@ -406,6 +411,13 @@ base@^0.11.1:
     mixin-deep "^1.2.0"
     pascalcase "^0.1.1"
 
+basic-auth@~2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
+  integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
+  dependencies:
+    safe-buffer "5.1.2"
+
 batch@0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
@@ -443,7 +455,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
   integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
 
-body-parser@1.18.3:
+body-parser@1.18.3, body-parser@^1.18.3:
   version "1.18.3"
   resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
   integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=
@@ -702,6 +714,15 @@ chalk@^2.4.1:
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
+chalk@^2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
 check-error@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
@@ -1531,7 +1552,7 @@ expand-brackets@^2.1.4:
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
-express@^4.16.2:
+express@^4.16.2, express@^4.16.4:
   version "4.16.4"
   resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
   integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
@@ -2911,6 +2932,17 @@ mocha@^5.2.0:
     mkdirp "0.5.1"
     supports-color "5.4.0"
 
+morgan@^1.9.1:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59"
+  integrity sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==
+  dependencies:
+    basic-auth "~2.0.0"
+    debug "2.6.9"
+    depd "~1.1.2"
+    on-finished "~2.3.0"
+    on-headers "~1.0.1"
+
 move-concurrently@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@@ -4935,6 +4967,13 @@ wrappy@1:
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
   integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
 
+ws@^6.1.2:
+  version "6.1.2"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.2.tgz#3cc7462e98792f0ac679424148903ded3b9c3ad8"
+  integrity sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==
+  dependencies:
+    async-limiter "~1.0.0"
+
 xregexp@4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"