flowtyped everything, some functional, safety, and structural changes

This commit is contained in:
41666 2019-03-10 03:18:11 -05:00
parent 6f3eca7a64
commit d2aecb38ca
92 changed files with 17554 additions and 1440 deletions

View file

@ -1,29 +1,94 @@
const log = new (require('./logger'))('Roleypoly')
const Sequelize = require('sequelize')
const fetchModels = require('./models')
const fetchApis = require('./api')
const Next = require('next')
const betterRouter = require('koa-better-router')
// @flow
import Sequelize from 'sequelize'
import Next from 'next'
import betterRouter from 'koa-better-router'
import EventEmitter from 'events'
import fs from 'fs'
import logger from './logger'
import ServerService from './services/server'
import DiscordService from './services/discord'
import SessionService from './services/sessions'
import PresentationService from './services/presentation'
import RPCServer from './rpc'
import fetchModels, { type Models } from './models'
import fetchApis from './api'
import type SocketIO from 'socket.io'
import type KoaApp, { Context } from 'koa'
const log = logger(__filename)
type HTTPHandler = (path: string, handler: (ctx: Context, next: () => void) => any) => void
export type Router = {
get: HTTPHandler,
post: HTTPHandler,
patch: HTTPHandler,
delete: HTTPHandler,
put: HTTPHandler,
middleware: () => any
}
export type AppContext = {
config: {
appUrl: string,
dev: boolean,
hotReload: boolean
},
ui: Next,
uiHandler: Next.Handler,
io: SocketIO,
server: ServerService,
discord: DiscordService,
sessions: SessionService,
P: PresentationService,
RPC: RPCServer,
M: Models,
sql: Sequelize
}
class Roleypoly {
constructor (io, app) {
ctx: AppContext|any
io: SocketIO
router: Router
M: Models
__app: KoaApp
__initialized: Promise<void>
__apiWatcher: EventEmitter
__rpcWatcher: EventEmitter
constructor (io: SocketIO, app: KoaApp) {
this.io = io
this.ctx = {}
this.ctx.config = {
appUrl: process.env.APP_URL,
dev: process.env.NODE_ENV !== 'production',
hotReload: process.env.NO_HOT_RELOAD !== '1'
}
this.ctx.io = io
this.__app = app
if (log.debugOn) log.warn('debug mode is on')
const dev = process.env.NODE_ENV !== 'production'
this.ctx.ui = Next({ dev, dir: './ui' })
this.ctx.uiHandler = this.ctx.ui.getRequestHandler()
// simple check if we're in a compiled situation or not.
let uiDir = './ui'
if (!fs.existsSync(uiDir) && fs.existsSync('../ui')) {
uiDir = '../ui'
}
const ui = Next({ dev, dir: uiDir })
const uiHandler = ui.getRequestHandler()
const appUrl = process.env.APP_URL
if (appUrl == null) {
throw new Error('APP_URL was unset.')
}
this.ctx = {
config: {
appUrl,
dev,
hotReload: process.env.NO_HOT_RELOAD !== '1'
},
io,
ui,
uiHandler
}
this.__initialized = this._mountServices()
}
@ -33,31 +98,30 @@ class Roleypoly {
}
async _mountServices () {
const sequelize = new Sequelize(process.env.DB_URL, { logging: log.sql.bind(log, log) })
const dbUrl: ?string = process.env.DB_URL
if (dbUrl == null) {
throw log.fatal('DB_URL not set.')
}
const sequelize = new Sequelize(dbUrl, { logging: log.sql.bind(log, log) })
this.ctx.sql = sequelize
this.M = fetchModels(sequelize)
this.ctx.M = this.M
await sequelize.sync()
// this.ctx.redis = new (require('ioredis'))({
// port: process.env.REDIS_PORT || '6379',
// host: process.env.REDIS_HOST || 'localhost',
// parser: 'hiredis',
// dropBufferSupport: true,
// enableReadyCheck: true,
// enableOfflineQueue: true
// })
this.ctx.server = new (require('./services/server'))(this.ctx)
this.ctx.discord = new (require('./services/discord'))(this.ctx)
this.ctx.sessions = new (require('./services/sessions'))(this.ctx)
this.ctx.P = new (require('./services/presentation'))(this.ctx)
this.ctx.server = new ServerService(this.ctx)
this.ctx.discord = new DiscordService(this.ctx)
this.ctx.sessions = new SessionService(this.ctx)
this.ctx.P = new PresentationService(this.ctx)
this.ctx.RPC = new RPCServer(this)
}
async loadRoutes (forceClear = false) {
async loadRoutes (forceClear: boolean = false) {
await this.ctx.ui.prepare()
this.router = betterRouter().loadMethods()
fetchApis(this.router, this.ctx, { forceClear })
this.ctx.RPC.hookRoutes(this.router)
// after routing, add the * for ui handler
this.router.get('*', async ctx => {
@ -83,6 +147,12 @@ class Roleypoly {
hotMiddleware = await this.loadRoutes(true)
})
this.__rpcWatcher = chokidar.watch('rpc/**')
this.__rpcWatcher.on('all', (path) => {
log.info('reloading RPCs...', path)
this.ctx.RPC.reload()
})
// custom passthrough so we use a specially scoped middleware.
mw = (ctx, next) => {
return hotMiddleware(ctx, next)