mirror of
https://github.com/roleypoly/roleypoly-v1.git
synced 2025-04-26 04:29:11 +00:00
backend: router hot-reloading
This commit is contained in:
parent
11cf1d4805
commit
959a2eb46f
4 changed files with 53 additions and 20 deletions
40
Roleypoly.js
40
Roleypoly.js
|
@ -3,16 +3,17 @@ const Sequelize = require('sequelize')
|
||||||
const fetchModels = require('./models')
|
const fetchModels = require('./models')
|
||||||
const fetchApis = require('./api')
|
const fetchApis = require('./api')
|
||||||
const Next = require('next')
|
const Next = require('next')
|
||||||
|
const betterRouter = require('koa-better-router')
|
||||||
|
|
||||||
class Roleypoly {
|
class Roleypoly {
|
||||||
constructor (router, io, app) {
|
constructor (io, app) {
|
||||||
this.router = router
|
|
||||||
this.io = io
|
this.io = io
|
||||||
this.ctx = {}
|
this.ctx = {}
|
||||||
|
|
||||||
this.ctx.config = {
|
this.ctx.config = {
|
||||||
appUrl: process.env.APP_URL
|
appUrl: process.env.APP_URL,
|
||||||
|
dev: process.env.NODE_ENV !== 'production',
|
||||||
|
hotReload: process.env.NO_HOT_RELOAD !== '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ctx.io = io
|
this.ctx.io = io
|
||||||
|
@ -52,10 +53,11 @@ class Roleypoly {
|
||||||
this.ctx.P = new (require('./services/presentation'))(this.ctx)
|
this.ctx.P = new (require('./services/presentation'))(this.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
async mountRoutes () {
|
async loadRoutes (forceClear = false) {
|
||||||
await this.ctx.ui.prepare()
|
await this.ctx.ui.prepare()
|
||||||
|
|
||||||
fetchApis(this.router, this.ctx)
|
this.router = betterRouter().loadMethods()
|
||||||
|
fetchApis(this.router, this.ctx, { forceClear })
|
||||||
|
|
||||||
// after routing, add the * for ui handler
|
// after routing, add the * for ui handler
|
||||||
this.router.get('*', async ctx => {
|
this.router.get('*', async ctx => {
|
||||||
|
@ -63,7 +65,31 @@ class Roleypoly {
|
||||||
ctx.respond = false
|
ctx.respond = false
|
||||||
})
|
})
|
||||||
|
|
||||||
this.__app.use(this.router.middleware())
|
return this.router.middleware()
|
||||||
|
}
|
||||||
|
|
||||||
|
async mountRoutes () {
|
||||||
|
let mw = await this.loadRoutes()
|
||||||
|
|
||||||
|
if (this.ctx.config.dev && this.ctx.config.hotReload) {
|
||||||
|
// hot-reloading system
|
||||||
|
log.info('API hot-reloading is active.')
|
||||||
|
const chokidar = require('chokidar')
|
||||||
|
let hotMiddleware = mw
|
||||||
|
|
||||||
|
this.__apiWatcher = chokidar.watch('api/**')
|
||||||
|
this.__apiWatcher.on('all', async (path) => {
|
||||||
|
log.info('reloading APIs...', path)
|
||||||
|
hotMiddleware = await this.loadRoutes(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// custom passthrough so we use a specially scoped middleware.
|
||||||
|
mw = (ctx, next) => {
|
||||||
|
return hotMiddleware(ctx, next)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__app.use(mw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ const glob = require('glob')
|
||||||
|
|
||||||
const PROD = process.env.NODE_ENV === 'production'
|
const PROD = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
module.exports = async (router, ctx) => {
|
module.exports = async (router, ctx, { forceClear = false } = {}) => {
|
||||||
const apis = glob.sync(`./api/**/!(index).js`)
|
const apis = glob.sync(`./api/**/!(index).js`)
|
||||||
log.debug('found apis', apis)
|
log.debug('found apis', apis)
|
||||||
|
|
||||||
|
@ -14,7 +14,11 @@ module.exports = async (router, ctx) => {
|
||||||
}
|
}
|
||||||
log.debug(`mounting ${a}`)
|
log.debug(`mounting ${a}`)
|
||||||
try {
|
try {
|
||||||
require(a.replace('api/', ''))(router, ctx)
|
const pathname = a.replace('api/', '')
|
||||||
|
if (forceClear) {
|
||||||
|
delete require.cache[require.resolve(pathname)]
|
||||||
|
}
|
||||||
|
require(pathname)(router, ctx)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error(`couldn't mount ${a}`, e)
|
log.error(`couldn't mount ${a}`, e)
|
||||||
}
|
}
|
||||||
|
|
11
index.js
11
index.js
|
@ -1,13 +1,10 @@
|
||||||
require('dotenv').config({silent: true})
|
require('dotenv').config({ silent: true })
|
||||||
const log = new (require('./logger'))('index')
|
const log = new (require('./logger'))('index')
|
||||||
|
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const Koa = require('koa')
|
const Koa = require('koa')
|
||||||
const app = new Koa()
|
const app = new Koa()
|
||||||
const _io = require('socket.io')
|
const _io = require('socket.io')
|
||||||
const fs = require('fs')
|
|
||||||
const path = require('path')
|
|
||||||
const router = require('koa-better-router')().loadMethods()
|
|
||||||
const Roleypoly = require('./Roleypoly')
|
const Roleypoly = require('./Roleypoly')
|
||||||
const ksuid = require('ksuid')
|
const ksuid = require('ksuid')
|
||||||
|
|
||||||
|
@ -20,7 +17,7 @@ Array.prototype.areduce = async function (predicate, acc = []) { // eslint-disab
|
||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.prototype.filterNot = Array.prototype.filterNot || function (predicate) {
|
Array.prototype.filterNot = Array.prototype.filterNot || function (predicate) { // eslint-disable-line
|
||||||
return this.filter(v => !predicate(v))
|
return this.filter(v => !predicate(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,9 +25,7 @@ Array.prototype.filterNot = Array.prototype.filterNot || function (predicate) {
|
||||||
const server = http.createServer(app.callback())
|
const server = http.createServer(app.callback())
|
||||||
const io = _io(server, { transports: ['websocket'], path: '/api/socket.io' })
|
const io = _io(server, { transports: ['websocket'], path: '/api/socket.io' })
|
||||||
|
|
||||||
|
const M = new Roleypoly(io, app) // eslint-disable-line no-unused-vars
|
||||||
|
|
||||||
const M = new Roleypoly(router, io, app) // eslint-disable-line no-unused-vars
|
|
||||||
|
|
||||||
app.keys = [ process.env.APP_KEY ]
|
app.keys = [ process.env.APP_KEY ]
|
||||||
|
|
||||||
|
|
14
package.json
14
package.json
|
@ -3,12 +3,13 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "pm2 start index.js",
|
"start": "node index.js",
|
||||||
"dev": "pm2 start index.js --watch",
|
"dev": "node index.js",
|
||||||
"build": "next build"
|
"build": "next build ui"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/uws": "^11.149.1",
|
"@discordjs/uws": "^11.149.1",
|
||||||
|
"@primer/components": "^10.0.1",
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"discord.js": "^11.4.2",
|
"discord.js": "^11.4.2",
|
||||||
"dotenv": "^6.2.0",
|
"dotenv": "^6.2.0",
|
||||||
|
@ -32,5 +33,12 @@
|
||||||
"socket.io": "^2.2.0",
|
"socket.io": "^2.2.0",
|
||||||
"superagent": "^4.1.0",
|
"superagent": "^4.1.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-eslint": "^10.0.1",
|
||||||
|
"babel-plugin-transform-flow-strip-types": "^6.22.0",
|
||||||
|
"chokidar": "^2.1.2",
|
||||||
|
"flow-type": "^1.0.1",
|
||||||
|
"standard": "^12.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue