Added dependency injection

This commit is contained in:
peter
2020-01-23 14:57:30 +01:00
parent 7a0c88df11
commit 78ad241526
24 changed files with 356 additions and 176 deletions
+11 -5
View File
@@ -10,14 +10,15 @@ 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/User/CharacterManager';
import { LoginManager } from '../Components/User/LoginManager';
import { CharacterManager } from '../Components/Character/CharacterManager';
import { LoginManager } from '../Components/Login/LoginManager';
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';
const logger = getLogger("admin", 'debug')
@@ -64,11 +65,16 @@ implements TableDefinitionExporter, IAdmin {
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(){
process.exit(0);
Promise.race([
Promise.all( this.frontworkComponents.map(c => c.stop?c.stop():undefined )),
new Promise((res, rej) => { setTimeout(res, 250);})
]).catch(e => logger.warn(e))
.finally(() => { process.exit(0) })
}
protected configChangeHandler = (conf:AdminConf, key?:string) => {
@@ -95,6 +101,7 @@ implements TableDefinitionExporter, IAdmin {
this.rpcServer = new RPCServer(20000, [
...this.frontworkComponents,
])
logger.debug("Websocket up on", 20000)
}
private startWebserver(){
@@ -183,6 +190,5 @@ implements TableDefinitionExporter, IAdmin {
process.on( 'SIGINT', function() {
logger.info("Shutting down from SIGINT (Ctrl-C)" );
// some other closing procedures go here
process.exit(0);
Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop()
})
@@ -3,20 +3,22 @@ import { Inject, Module } from "../../Injector/ServiceDecorator";
import { TableDefiniton, Character } from "../../Types/Types";
import { CharacterManagerIfc } from "./RPCInterface";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { FrontworkAdmin } from "../../Admin/Admin";
import { LoginManager } from "./LoginManager";
import { getSpecTableData, SpecT } from "../../Types/PlayerSpecs";
import { IAdmin } from "../../Admin/Interface";
import { ILoginManager } from "../Login/Interface";
import { ICharacterManager } from "./Interface";
import { getLogger } from "log4js";
@Module()
@Module(ICharacterManager)
export class CharacterManager
implements FrontworkComponent<CharacterManagerIfc, RPCInterface>{
implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterManager{
name = "CharacterManager" as "CharacterManager";
@Inject(IAdmin)
private admin: IAdmin
private loginManager : LoginManager
@Inject(ILoginManager)
private loginManager : any
exportRPCs = () => [
{
@@ -60,17 +62,20 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>{
]
private initialized = false
initialize = async () => {
if(!this.initialized)
this.initialized = true
//initialize spec table
getLogger('CharacterManager').debug('inserting specs')
await this.admin.knex('specs').insert(getSpecTableData()).catch(e => { console.log("skipping spec insertion") })
}
createCharacter = async (userToken: string, character : Character) : Promise<Character> => {
try{
const user = this.loginManager.getUserRecordByToken(userToken)
await this.admin.knex('characters').insert(character)
const char : Character = await this.admin.knex.select('*').from('characters').where(character).first()
return char
@@ -0,0 +1,9 @@
import { Character } from "../../Types/Types"
import { SpecT } from "../../Types/PlayerSpecs"
export class ICharacterManager{
createCharacter: (usertoken: string, char : Character) => Promise<Character>
getSpecId: <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => Promise<number>
getCharacters: () => Promise<Character[]>
}
@@ -0,0 +1,15 @@
import { ICharacterManager } from "./Interface"
export type CharacterManagerIfc = {
CharacterManager: {
getSpecId : ICharacterManager['getSpecId']
getCharacters : ICharacterManager['getCharacters']
}
}
export type CharacterManagerFeatureIfc = {
createCharacter: {
createCharacter: ICharacterManager['createCharacter']
}
}
+23 -23
View File
@@ -1,10 +1,10 @@
import { ConfigLoader } from "loadson";
import { Inject, Module } from "../../Injector/ServiceDecorator";
import { GuildManagerFeatureIfc, GuildManagerIfc } from "./RPCInterface";
import { FrontworkAdmin } from "../../Admin/Admin";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { _Rank, Rank } from "../../Types/Types";
import { IAdmin } from "../../Admin/Interface";
import { IGuildManager } from "./Interface";
export type Guild = {
name: string
@@ -12,55 +12,51 @@ export type Guild = {
description: string
}
@Module()
@Module(IGuildManager)
export class GuildManager
implements FrontworkComponent<GuildManagerIfc, GuildManagerFeatureIfc>{
implements FrontworkComponent<GuildManagerIfc, GuildManagerFeatureIfc>, IGuildManager{
name = "GuildManager" as "GuildManager";
@Inject(IAdmin)
private admin
private admin : IAdmin
guild: ConfigLoader<Guild>
constructor(){
this.guild = new ConfigLoader({
name: "guild",
getDefaultConfig: () => {
return <Guild>{
name: "Tranquil",
realm: "Gandling EU",
description: "Wee woo"
}
guild: ConfigLoader<Guild> = new ConfigLoader({
name: "guild",
getDefaultConfig: () => {
return <Guild>{
name: "Tranquil",
realm: "Gandling EU",
description: "Wee woo"
}
}, "./config")
}
}
}, "./config")
exportRPCs = () => [{
name: 'getHeadCount' as 'getHeadCount',
call: this.headCount
call: this.getHeadCount
},{
name: 'getGuildInfo' as 'getGuildInfo',
call: async () => this.guild.getConfig()
call: this.getGuildInfo
}]
exportRPCFeatures = () => [{
name: 'manageGuild' as 'manageGuild',
exportRPCs: () => [{
name: 'setName' as 'setName',
call: async (name:string) => this.guild.setConfigKey('name', name)
call: this.setName
},{
name: 'setRealm' as 'setRealm',
call: async (realm:string) => this.guild.setConfigKey('realm', realm)
call: this.setRealm
}, {
name: 'setDescription' as 'setDescription',
call: async (description: string) => this.guild.setConfigKey('description', description)
call: this.setDescription
}]
}]
getTableDefinitions = () => []
headCount = async () => await Promise.all(
getHeadCount = async() : Promise<{ rank: Rank; count: number; }[]> => await Promise.all(
_Rank.map(async r => {
const res = await this.admin.knex
.select('*')
@@ -76,4 +72,8 @@ implements FrontworkComponent<GuildManagerIfc, GuildManagerFeatureIfc>{
})
)
getGuildInfo = async () => this.guild.getConfig()
setName = async (name:string) => this.guild.setConfigKey('name', name)
setDescription = async (description: string) => this.guild.setConfigKey('description', description)
setRealm = async (realm:string) => this.guild.setConfigKey('realm', realm)
}
+10
View File
@@ -0,0 +1,10 @@
import { Rank } from "../../Types/Types"
import { Guild } from "./GuildManager"
export class IGuildManager{
getHeadCount: () => Promise<{rank:Rank, count: number}[]>
getGuildInfo: () => Promise<Guild>
setName: (name:string) => Promise<Guild>
setRealm: (realm:string) => Promise<Guild>
setDescription: (description:string) => Promise<Guild>
}
+6 -7
View File
@@ -1,17 +1,16 @@
import { Guild } from "./GuildManager"
import { Rank } from "../../Types/Types"
import { IGuildManager } from "./Interface"
export type GuildManagerIfc = {
GuildManager: {
getHeadCount: () => Promise<{rank:Rank, count: number}[]>
getGuildInfo: () => Promise<Guild>
getHeadCount: IGuildManager['getHeadCount']
getGuildInfo: IGuildManager['getGuildInfo']
}
}
export type GuildManagerFeatureIfc = {
manageGuild: {
setName: (name:string) => Promise<Guild>
setRealm: (realm:string) => Promise<Guild>
setDescription: (description:string) => Promise<Guild>
setName: IGuildManager['setName']
setRealm: IGuildManager['setRealm']
setDescription: IGuildManager['setDescription']
}
}
+6
View File
@@ -0,0 +1,6 @@
import { Item } from "../../Types/Types"
export class IItemManager{
getItems: () => Promise<Item[]>
getItem: (name:string) => Promise<Item>
}
+9 -16
View File
@@ -4,30 +4,22 @@ import { Inject, Module } from "../../Injector/ServiceDecorator";
import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { TableDefinitionExporter } from "../../Types/Interfaces";
import { FrontworkAdmin } from "../../Admin/Admin";
import { TableDefiniton } from "../../Types/Types";
import { TableDefiniton, Item } from "../../Types/Types";
import { IAdmin } from "../../Admin/Interface";
import { IItemManager } from "./Interface";
import { getLogger } from "log4js";
const fetch = require('node-fetch')
const xml2js = require('xml2js');
const parser = new xml2js.Parser(/* options */);
export type Item = {
id?:number
name:string
iconname:string
url:string
quality:string
hidden:boolean
}
@Module()
@Module(IItemManager)
export class ItemManager
implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefinitionExporter{
implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefinitionExporter, IItemManager{
name = "ItemManager" as "ItemManager";
@Inject(IAdmin)
private admin: FrontworkAdmin
private admin: IAdmin
exportRPCs(): RPC<any, any>[]{
return [{
@@ -99,6 +91,8 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
this.initialized = true
const allItems = [...T1]
getLogger('ItemManager').debug('Checking items')
const countCache = await this.countItems()
if(countCache != allItems.length){
const items:Item[] = await Promise.all(allItems.map((i) => this.getItem(i)))
@@ -107,8 +101,7 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
.knex('items')
.insert(items)
}catch(e){
console.log(e)
console.info("Skipping item insertion")
getLogger('ItemManager').debug("Skipping item insertion")
}
}
}
+10 -3
View File
@@ -1,4 +1,11 @@
import { RPCInterface } from "rpclibrary"
import { IItemManager } from "./Interface"
export type ItemManagerIfc = RPCInterface
export type ItemManagerFeatureIfc = RPCInterface
export type ItemManagerIfc = {
ItemManager: {
getItem: IItemManager['getItem']
getItems: IItemManager['getItems']
}
}
export type ItemManagerFeatureIfc = {
}
+11
View File
@@ -0,0 +1,11 @@
import { Auth, Rank, User, RPCPermission } from "../../Types/Types"
export class ILoginManager{
login: (username:string, pwHash:string) => Promise<Auth>
logout: (username: string, tokenValue :string) => Promise<void>
getAuth: (tokenValue: string) => Promise<Auth>
createUser: (user:User) => Promise<User>
setPermission: (perm: RPCPermission) => Promise<void>
getPermissions: () => Promise<RPCPermission[]>
checkToken: (token: string, rank: Rank) => boolean
}
@@ -4,11 +4,13 @@ import { FrontworkAdmin } from "../../Admin/Admin";
import { GuildManager } from "../Guild/GuildManager";
import { ItemManager } from "../Item/ItemManager";
import { RaidManager } from "../Raid/RaidManager";
import { CharacterManager } from "./CharacterManager";
import { CharacterManager } from "../Character/CharacterManager";
import { LoginManagerIfc, LoginManagerFeatureIfc } from "./RPCInterface";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token } from "../../Types/Types";
import { IAdmin } from "../../Admin/Interface";
import { ILoginManager } from "./Interface";
import { getLogger } from "log4js";
const uuid = require('uuid/v4')
@@ -21,9 +23,9 @@ type Serverstate = {
}
@Module()
@Module(ILoginManager)
export class LoginManager
implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>{
implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginManager{
name = "Authenticator" as "Authenticator";
@Inject(IAdmin)
@@ -61,7 +63,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>{
call: this.getAuth
},{
name: 'checkToken' as 'checkToken',
call: async (tokenValue : string, rank: Rank) => this.checkToken(tokenValue, rank)
call: this.checkToken
},{
name: 'createUser' as 'createUser',
call: this.createUser
@@ -111,31 +113,52 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>{
initialize = async () => {
this.exporters = [this.guild, this.item, this.raid, this.character]
//set up permissions
getLogger('LoginManager').debug('inserting permissions')
await Promise.all(
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
try{
await this.admin.knex.insert({ name: feature.name }).into('rpcpermissions')
}catch(e){}
}catch(e){
console.log(e);
}
})))
//start rankServers
const rankServers : any = {}
getLogger('LoginManager').debug('Starting rank servers')
for(let i = 0; i < _Rank.length; i++){
const rank:Rank = _Rank[i]
let rankServers = { } as any
await Promise.all(_Rank.map(async (r,i) => {
const port = 20001 + i
const rankServer = await this.startRankServer(rank, port)
rankServers[rank] = {
const rankServer = await this.startRankServer(r, port)
rankServers[r] = {
server: rankServer,
port: port,
allowed: []
}
}
}))
this.rankServers = rankServers
setInterval(this.checkExpiredSessions, 600_000)
}
stop = async () => {
Object.values(this.userLogins).forEach(x => Object.values(x.connections).forEach(c => c.destroy()))
await Promise.all(Object
.values(this.rankServers)
.map(async state => {
try{
//return await state.server.destroy()
}catch(e){
getLogger('LoginManager').warn(e)
}
})
);
}
checkExpiredSessions = () => {
Object.values(this.userLogins).map(userLogin => {
const auth = userLogin.auth
@@ -146,11 +169,13 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>{
}
checkConnection = async (socket: Socket) => {
let data : any = false
let data : any
let tries = 0
while(!data){
tries ++
if(tries === 5){
getLogger('LoginManager').debug('Connection check failed for connection *'+socket.port)
socket.destroy()
return
}
@@ -282,18 +307,37 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>{
}
startRankServer = async (rank : Rank, port: number) : Promise<RPCServer> => {
const allowedRPCs = await this.getRPCForRank(rank)
let rpcServer : RPCServer = new RPCServer(port, allowedRPCs, {
closeHandler: (socket) => {
Object.values(this.userLogins)
.forEach(login => delete login.connections[socket.port])
},
connectionHandler: (socket) => {
this.checkConnection(socket).catch(() => {}) //sometimes times out if you go too fast
},
sesame: (sesame) => this.checkToken(sesame, rank)
})
const allowedRPCs = await this.getRPCForRank(rank)
let rpcServer
let n = 0
while(!rpcServer){
n++
await Promise.race([
new Promise((res, rej) => {
rpcServer = new RPCServer(port, allowedRPCs, {
closeHandler: (socket) => {
Object.values(this.userLogins)
.forEach(login => delete login.connections[socket.port])
},
connectionHandler: (socket) => {
this.checkConnection(socket).catch((e) => {
console.log(e);
}) //sometimes times out if you go too fast
},
errorHandler: (socket, e, rpcName, args) => {
console.log(rpcName, args);
},
sesame: (sesame) => this.checkToken(sesame, rank)
})
res()
}),
new Promise((res, rej) => setTimeout(res, 500))
])
if(!rpcServer && n>1)
getLogger('LoginManager').warn("createServer retry nr.", n, 'port', port)
}
return rpcServer
}
@@ -0,0 +1,18 @@
import { ILoginManager } from "./Interface"
export type LoginManagerIfc = {
Authenticator: {
checkToken: ILoginManager['checkToken']
login: ILoginManager['login']
logout: ILoginManager['logout']
createUser: ILoginManager['createUser']
getAuth: ILoginManager['getAuth']
}
}
export type LoginManagerFeatureIfc = {
modifyPermissions: {
setPermission: ILoginManager['setPermission']
getPermissions: ILoginManager['getPermissions']
}
}
+10
View File
@@ -0,0 +1,10 @@
import { User, Raid, Signup } from "../../Types/Types"
export class IRaidManager{
getRaids: () => Promise<Raid[]>
createRaid: (raid:Raid) => Promise<any>
addSignup: (signup: Signup) => Promise<any>
removeSignup: (signup: Signup) => Promise<any>
getSignups: (raid:Raid) => Promise<Signup[]>
sign: (user:User, raid:Raid, attending:boolean) => Promise<any>
}
+7 -8
View File
@@ -1,20 +1,19 @@
import { Raid, Signup, User } from "../../Types/Types"
import { IRaidManager } from "./Interface"
export type RaidManagerIfc = {
RaidManager:{
getRaids: () => Promise<Raid[]>
getRaids: IRaidManager['getRaids']
}
}
export type RaidManagerFeatureIfc = {
manageRaid: {
createRaid: (raid:Raid) => Promise<any>
addSignup: (signup: Signup) => Promise<any>
removeSignup: (signup: Signup) => Promise<any>
createRaid: IRaidManager['createRaid']
addSignup: IRaidManager['addSignup']
removeSignup: IRaidManager['removeSignup']
}
signup: {
getRaids: () => Promise<Raid[]>
getSingups: (raid:Raid) => Promise<Signup[]>
sign: (user:User, raid:Raid, attending:boolean) => Promise<any>
getSignups: IRaidManager['getSignups']
sign: IRaidManager['sign']
}
}
+6 -6
View File
@@ -1,17 +1,17 @@
import { Inject, Module } from "../../Injector/ServiceDecorator";
import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { FrontworkAdmin } from "../../Admin/Admin";
import { TableDefiniton, Signup, Raid, User } from "../../Types/Types";
import { IAdmin } from "../../Admin/Interface";
import { IRaidManager } from "./Interface";
@Module()
@Module(IRaidManager)
export class RaidManager
implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>{
implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManager{
name = "RaidManager" as "RaidManager";
@Inject(IAdmin)
private admin: FrontworkAdmin
private admin: IAdmin
exportRPCs = () => [{
name: 'getRaids' as 'getRaids',
@@ -34,7 +34,7 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>{
},{
name: 'signup' as 'signup',
exportRPCs: () => [{
name: 'getSingups' as 'getSingups',
name: 'getSignups' as 'getSignups',
call: this.getSignups
},{
name: 'sign' as 'sign',
@@ -87,7 +87,7 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>{
.select('*')
.from('raids')
getSignups = async (raid:Raid) => await this.admin.knex
getSignups = async (raid:Raid) : Promise<Signup[]> => await this.admin.knex
.select('*')
.from('signups')
.where('raid_id', '=', raid.id!)
@@ -1,32 +0,0 @@
import { Auth, Rank, User, RPCPermission, Character } from "../../Types/Types"
import { SpecT } from "../../Types/PlayerSpecs"
export type LoginManagerIfc = {
Authenticator: {
login: (username:string, pwHash:string) => Promise<Auth>
logout: (username: string, tokenValue :string) => Promise<void>
getAuth: (tokenValue: string) => Promise<Auth>
checkToken: (token: string, rank: Rank) => Promise<boolean>
createUser: (user:User) => Promise<User>
}
}
export type LoginManagerFeatureIfc = {
modifyPermissions: {
setPermission: (perm: RPCPermission) => Promise<void>
getPermissions: () => Promise<RPCPermission[]>
}
}
export type CharacterManagerIfc = {
CharacterManager: {
getSpecId : <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => Promise<number>
getCharacters : () => Promise<Character[]>
}
}
export type CharacterManagerFeatureIfc = {
createCharacter: {
createCharacter: (usertoken: string, char : Character) => Promise<Character>
}
}
+9 -8
View File
@@ -12,7 +12,8 @@ export const Injector = new class {
rootInterface : Type<any>
root : Type<any>
rootModules : Type<any>[] = []
rootModules: Type<any>[] = []
modules : {ifc?: Type<any>, implementation: Type<any>}[] = []
moduleObjs : {[key in string] : FrontworkComponent} = {}
@@ -28,9 +29,11 @@ export const Injector = new class {
return this.moduleObjs[target.name] as any
if(target.name === this.rootInterface.name || target.name === this.root.name){
let modules = this.rootModules.map(m => {
const module = new m()
this.moduleObjs[m.name] = module
let modules = this.modules.map(m => {
const module = new m.implementation()
if(m.ifc)
this.moduleObjs[m.ifc.name] = module
this.moduleObjs[m.implementation.name] = module
return module
})
const rootobj = new this.root(modules);
@@ -42,11 +45,9 @@ export const Injector = new class {
if(this.moduleObjs[i.what.name])
i.target[i.where] = this.moduleObjs[i.what.name]
else
this.injectionQueue.push()
this.injectionQueue.push(i)
}
this.injectionQueue.forEach(i => {
i.target[i.where] = this.moduleObjs[i.what.name]
})
return rootobj
}
this.moduleObjs[target.name] = new target()
+5 -2
View File
@@ -6,9 +6,12 @@ import { FrontworkComponent } from "../Types/FrontworkComponent";
* @returns {GenericClassDecorator<Type<any>>}
* @constructor
*/
export const Module = (...args) : GenericClassDecorator<Type<any>> => {
export const Module = (ifc?: Type<any>) : GenericClassDecorator<Type<any>> => {
return (target: Type<any>) => {
Injector.rootModules.push(target)
Injector.modules.push({
ifc: ifc,
implementation: target
})
}
}
+1
View File
@@ -1,5 +1,6 @@
import { Injector } from './Injector/Injector';
import { IAdmin } from './Admin/Interface';
import "./Admin/Admin"
require('events').EventEmitter.defaultMaxListeners = 0;
Injector.resolve<IAdmin>(IAdmin).start()
+1
View File
@@ -20,4 +20,5 @@ export interface FrontworkComponent<
getTableDefinitions(): TableDefiniton[]
initialize?(): Promise<any>
stop?() : Promise<any>
}
+18 -8
View File
@@ -1,8 +1,16 @@
import * as Knex from "knex"
import { RPCExporter } from "rpclibrary";
import { RaidManagerIfc, RaidManagerFeatureIfc } from "../Components/Raid/RPCInterface";
import { LoginManagerIfc, CharacterManagerIfc, LoginManagerFeatureIfc, CharacterManagerFeatureIfc } from "../Components/User/RPCInterface";
import { LoginManagerIfc, LoginManagerFeatureIfc } from "../Components/Login/RPCInterface";
import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
export type FrontcraftIfc = RaidManagerIfc
& LoginManagerIfc
& CharacterManagerIfc
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc
& LoginManagerFeatureIfc
& CharacterManagerFeatureIfc
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
@@ -30,6 +38,15 @@ export type RPCPermission = {
[rank in Rank] : boolean
}
export type Item = {
id?:number
name:string
iconname:string
url:string
quality:string
hidden:boolean
}
export type User = {
id?: number
name: string
@@ -67,13 +84,6 @@ export type Token = {
export type Auth = {port: number, user: User, token: Token}
export type FrontcraftIfc = RaidManagerIfc
& LoginManagerIfc
& CharacterManagerIfc
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc
& LoginManagerFeatureIfc
& CharacterManagerFeatureIfc
export type Spec = {
id?: number,