| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- 'use strict'
-
- import { getLogger } from 'frontblock-generic/Types';
- import { promises as fs, mkdirSync } from "fs"
- import { RPCServer } from 'rpclibrary'
- import * as Path from 'path'
- import * as Knex from 'knex';
- import * as http from 'http';
- import * as express from 'express';
- import { GuildManager } from '../Components/Guild/GuildManager';
- import { ItemManager } from '../Components/Item/ItemManager';
- import { RaidManager } from '../Components/Raid/RaidManager';
- import { CharacterManager } from '../Components/Character/CharacterManager';
- import { UserManager } from '../Components/User/UserManager';
- import { RootComponent } from '../Injector/ServiceDecorator';
- import { TableDefinitionExporter } from '../Types/Interfaces';
- import { AdminConf, TableDefiniton } from '../Types/Types';
- import { RPCConfigLoader } from '../Components/RPCConfigLoader';
- import { FrontworkComponent } from '../Types/FrontworkComponent';
- import { IAdmin } from './Interface';
- import { Injector } from '../Injector/Injector';
- import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
- import { PubSub } from '../Components/PubSub/PubSub';
-
-
- const logger = getLogger("admin", 'debug')
-
- @RootComponent({
- injectable: IAdmin,
- injects: [
- GuildManager,
- ItemManager,
- RaidManager,
- CharacterManager,
- UserManager,
- Shoutbox,
- PubSub
- ]
- })
- export class FrontworkAdmin
- implements TableDefinitionExporter, IAdmin {
- knex:Knex
- config: RPCConfigLoader<AdminConf>
- rpcServer: RPCServer
-
- private express
- private httpServer
-
- constructor(private frontworkComponents: FrontworkComponent[] = []){
- this.config = new RPCConfigLoader<AdminConf>({
- name: "FrontworkAdminConf",
- getDefaultConfig: () => {
- return {
- httpPort: 8080,
- eventBusConf: {},
- dbConf: {
- client: 'sqlite3',
- connection: {
- filename: Path.resolve(__dirname, '../../../..', "data/frontworkAdmin.sqlite")
- },
- useNullAsDefault: true,
- }
- }
- }
- }, './config', this.configChangeHandler)
- }
-
- async start(){
- await this.makeKnex()
- this.startWebsocket()
- await Promise.all( this.frontworkComponents.map(c => c.initialize?c.initialize():undefined ))
- logger.debug(this.frontworkComponents.length+" components initialized")
- this.startWebserver()
- }
-
- stop(){
- Promise.all([
- ...this.frontworkComponents.map(c => c.stop?c.stop():undefined ),
- ])
- .catch(e => logger.warn(e))
- .finally(() => {
- this.rpcServer.destroy()
- process.exit(0)
- })
- }
-
- protected configChangeHandler = (conf:AdminConf, key?:string) => {
- if(key === 'dbConf'){
- this.makeKnex()
- }
- }
-
- getConfigKey(key:string){
- return this.config.getConfigKey(key)
- }
-
- setConfigKey(key:string, value:any){
- return this.config.setConfigKey(key, value)
- }
-
- getTableDefinitions(): TableDefiniton[]{
- return [
- ...this.frontworkComponents
- ]
- .filter(exp => exp.getTableDefinitions != null)
- .flatMap(exp => exp.getTableDefinitions())
- }
-
- private startWebsocket(){
- this.rpcServer = new RPCServer(20000, [
- ...this.frontworkComponents,
- {
- name: "debug",
- exportRPCs: () => [{
- name: 'dumpDb',
- call: async (table) => await this.knex(table).select('*')
- }]
- }
- ], {
- visibility: '0.0.0.0'
- })
- logger.debug("Websocket up on", 20000)
- }
-
- private startWebserver(){
- if(this.httpServer != null || this.express != null){
- logger.warn("Webserver is already running")
- return
- }
-
- let port:number = this.config.getConfig().httpPort
- this.express = express()
- this.express.use('/', express.static('static'))
-
- /**
- * get the compiled FrontendPlugins.js
- */
- this.express.get('/plugins/:id'+".js", async (request, response) => {
- const pth = Path.resolve("plugins/"+request.params.id, "FrontendPlugin.js");
- const file = await fs.readFile(pth)
- const frontend = file.toString()
-
- response.status(200)
- response.set('Content-Type', 'application/javascript')
- response.send(frontend)
- })
-
- /**
- * serve the index.html from the static folder
- */
- this.express.get("/", (request, response) => {
- response.status(200)
- response.sendFile('index.html');
- })
-
- /**
- * redirect all the other traffic to the single page app
- */
- this.express.get("*", (request, response) => {
- response.status(301)
- response.redirect('/')
- })
-
- this.httpServer = new http.Server(this.express)
- this.httpServer.listen(port, () => {
- logger.info('Admin panel listening for HTTP on *'+port)
- })
- }
-
- private stopWebserver(){
- if(this.httpServer == null || this.express == null){
- logger.warn("Webserver is not running")
- return
- }
- this.httpServer.close()
- this.httpServer = null
- this.express = null
- logger.info("Webserver stopped")
- }
-
- async makeKnex():Promise<Knex>{
- const conf:Knex.Config = this.config.getConfigKey("dbConf")
-
- logger.debug("Making new knex:", conf)
- if(conf.client === 'sqlite3'){
- mkdirSync(Path.dirname((<any>conf.connection).filename), {recursive: true})
- }
-
- this.knex = Knex(conf)
- if(conf.client === 'sqlite3'){
- await this.knex.raw('PRAGMA foreign_keys = ON');
-
- }
-
- await Promise.all(
- this.getTableDefinitions()
- //make unique by name
- .filter((other, index, self) => index === self.findIndex(
- (self) => self.name === other.name)
- )
- //create table if not exists
- .map(async (def)=> {
- const hasTable = await this.knex.schema.hasTable(def.name)
- if(!hasTable)
- return await this.knex.schema.createTable(def.name, def.tableBuilder)
- })
- )
- return this.knex
- }
- }
-
- process.on( 'SIGINT', function() {
- logger.info("Shutting down from SIGINT (Ctrl-C)" );
- Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop()
- })
|