add PluginLoader
This commit is contained in:
@@ -134,7 +134,7 @@ implements TableDefinitionExporter {
|
||||
logger.info("Webserver stopped")
|
||||
}
|
||||
|
||||
protected async makeKnex():Promise<Knex>{
|
||||
public async makeKnex():Promise<Knex>{
|
||||
const conf:Knex.Config = this.config.getConfigKey("dbConf")
|
||||
|
||||
logger.debug("Making new knex:", conf)
|
||||
|
||||
+164
-10
@@ -1,19 +1,173 @@
|
||||
import { RPCExporter } from "rpclibrary/js/src/Interfaces";
|
||||
import { Git, Types } from "upgiter"
|
||||
import { Git } from "upgiter"
|
||||
import { FolderStatus } from "upgiter/js/src/Types";
|
||||
import { Plugin } from "./Plugin";
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
|
||||
export type GitUpdaterIfc = {
|
||||
cloneRepo: (force:boolean) => Promise<Types.FolderStatus>
|
||||
getStatus: () => Promise<Types.FolderStatus>
|
||||
checkoutTag: (tag:string) => Promise<Types.FolderStatus>
|
||||
isOutdated: () => Promise<boolean>
|
||||
export type PluginLoaderIfc = {
|
||||
PluginLoader: {
|
||||
installPlugin: (name:string, force:boolean) => Promise<FolderStatus>
|
||||
startPlugin: (name:string) => Promise<boolean>
|
||||
updatePlugin: (name:string) => Promise<boolean>
|
||||
setPluginVersion: (name:string, tag:string) => Promise<FolderStatus>
|
||||
getLoadedPluginNames: () => Promise<String[]>
|
||||
selfUpdate: (force:boolean) => Promise<FolderStatus>
|
||||
destroy: () => Promise<void>
|
||||
}
|
||||
}
|
||||
|
||||
class RPCUpgiter
|
||||
extends Git.Updater
|
||||
implements RPCExporter<any, "PluginLoader">{
|
||||
class PluginLoader
|
||||
implements RPCExporter<PluginLoaderIfc, "PluginLoader">{
|
||||
|
||||
name = "PluginLoader" as "PluginLoader";
|
||||
private runningPlugins: Plugin[]
|
||||
private pluginUpdaters:{[name in string]:Git.Updater} = {}
|
||||
|
||||
constructor(private admin:FrontworkAdmin){}
|
||||
|
||||
private async selfUpdate(force:boolean = false){
|
||||
const updater = new Git.Updater({
|
||||
schema: 'https',
|
||||
localPath: './dist',
|
||||
remoteHost: 'www.versioncontrol.me',
|
||||
remotePath: 'frontwork-distribution',
|
||||
repoName: 'admin'
|
||||
})
|
||||
|
||||
let status = await updater.getStatus()
|
||||
if(force || !status.remote || !status.remote.includes("fb-dist/admin") || !status.exists || status.empty || !status.currentTag){
|
||||
//logger.warn("Cloning fb-dist/admin into ./dist ..."+(force?" USING FORCE!":""))
|
||||
status = await updater.cloneRepo(force)
|
||||
|
||||
//this.destroy()
|
||||
const installer = eval("require")("./Installer").installAdmin
|
||||
installer(this.getPlugins())
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
async installPlugin(name: string, force:boolean = false):Promise<FolderStatus>{
|
||||
//logger.warn("Cloning fb-dist/"+name+".git into ./plugins/"+name+" ..."+(force?" USING FORCE!":""))
|
||||
this.pluginUpdaters[name] = new Git.Updater({
|
||||
schema: 'https',
|
||||
localPath: './dist',
|
||||
remoteHost: 'www.versioncontrol.me',
|
||||
remotePath: 'frontwork-distribution',
|
||||
repoName: name
|
||||
})
|
||||
//new GitUpdater("./plugins/"+name)
|
||||
const status = await this.pluginUpdaters[name].cloneRepo(force)
|
||||
return status
|
||||
}
|
||||
|
||||
async startPlugin(name:string):Promise<boolean>{
|
||||
if(!this.pluginUpdaters[name]) return false
|
||||
const status = await this.pluginUpdaters[name].getStatus()
|
||||
if(!status.exists || status.empty || !status.tags || status.tags.length === 0){
|
||||
if(status.currentTag && !status.latestTag){
|
||||
//git glitches sometimes if you check immediately after clone
|
||||
//logger.warn("re-fetching tag for "+name+"...")
|
||||
return await this.startPlugin(name)
|
||||
}
|
||||
//logger.error("Bad repo status", name, status)
|
||||
return false
|
||||
}
|
||||
|
||||
/* if(this.loadedPlugins[name]){
|
||||
logger.error("Plugin", name, "is already started")
|
||||
return false
|
||||
}
|
||||
*/
|
||||
|
||||
let str = "../plugins/"+name+"/Plugin"
|
||||
const pluginClass = await eval('require')(str)
|
||||
const pluginObj = new pluginClass.default(this)
|
||||
try{
|
||||
if(pluginObj.start)
|
||||
await pluginObj.start()
|
||||
//this.pushNotification({message: "Started plugin "+pluginObj.name, severity: "Important", topic:"admin"})
|
||||
this.addPlugin(pluginObj)
|
||||
return true
|
||||
}catch(e){
|
||||
//logger.error(e)
|
||||
//this.pushNotification({message: "Start of plugin "+pluginObj.name+" failed because of "+String(e), severity: "Error", topic:"admin"})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async updatePlugin(name:string):Promise<boolean>{
|
||||
if(!this.pluginUpdaters[name]) return false
|
||||
const status = await this.pluginUpdaters[name].getStatus()
|
||||
if(!status.exists || status.empty || !status.tags || status.tags.length === 0){
|
||||
//logger.error("Bad repo status", name, status)
|
||||
return false
|
||||
}
|
||||
if(status.currentTag == status.latestTag){
|
||||
//logger.warn(name, "already at latest tag")
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
if(this.loadedPlugins[name]){
|
||||
logger.error("Plugin", name, "is running. Stop it first")
|
||||
return false
|
||||
}
|
||||
*/
|
||||
|
||||
this.pluginUpdaters[name].checkoutTag(status.latestTag!)
|
||||
return true
|
||||
}
|
||||
|
||||
async setPluginVersion(pluginName:string, tag:string):Promise<FolderStatus>{
|
||||
const status = await this.pluginUpdaters[pluginName].getStatus()
|
||||
if(!status.exists || !status.tags || status.tags.length === 0 || !status.tags.includes(tag)){
|
||||
//logger.error("Bad repo status", pluginName, status)
|
||||
return status
|
||||
}
|
||||
|
||||
return await this.pluginUpdaters[pluginName].checkoutTag(tag)
|
||||
}
|
||||
|
||||
async addPlugin(plugin: Plugin){
|
||||
this.runningPlugins.push(plugin)
|
||||
if(plugin.getTableDefinitions().length != 0)
|
||||
await this.admin.makeKnex()
|
||||
}
|
||||
|
||||
removePlugin(plugin: Plugin){
|
||||
this.runningPlugins = this.runningPlugins.filter(p => p.name !== plugin.name)
|
||||
}
|
||||
|
||||
getPlugins():Plugin[]{
|
||||
return [...this.runningPlugins]
|
||||
}
|
||||
|
||||
private async destroy(){
|
||||
return
|
||||
}
|
||||
|
||||
exportRPCs(){
|
||||
return []
|
||||
return [{
|
||||
name: "installPlugin" as "installPlugin",
|
||||
call: async (name:string, force = false) => {return await this.installPlugin(name, force)},
|
||||
},{
|
||||
name: "startPlugin" as "startPlugin",
|
||||
call: async (name:string) => {return await this.startPlugin(name)},
|
||||
},{
|
||||
name: "updatePlugin" as "updatePlugin",
|
||||
call: async (name:string) => {return await this.updatePlugin(name)},
|
||||
},{
|
||||
name: "setPluginVersion" as "setPluginVersion",
|
||||
call: async (name:string, tag:string) => {return await this.setPluginVersion(name, tag)},
|
||||
},{
|
||||
name: "getLoadedPluginNames" as "getLoadedPluginNames",
|
||||
call: async () => {return this.getPlugins().map(p => p.name)},
|
||||
},{
|
||||
name: "selfUpdate" as "selfUpdate",
|
||||
call: async (force: boolean) => {return await this.selfUpdate(force)},
|
||||
},{
|
||||
name: "destroy" as "destroy",
|
||||
call: async () => {return this.destroy()}
|
||||
}]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user