werks here

This commit is contained in:
peter
2019-08-03 20:28:36 +02:00
parent d9ccd4d9d3
commit 52ec9c8201
53 changed files with 561 additions and 349 deletions
+9 -4
View File
@@ -112,7 +112,7 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
//translate RPCs to socket-bound function metadata
const loadedPlugins = this.pm.getLoadedPlugins()
for(const name in loadedPlugins){
loadedPlugins[name].exportRPCs().forEach(rpc => {
loadedPlugins[name].backend.exportRPCs().forEach(rpc => {
const info = this.rpcToRpcInfo(name, rpc)
rpcInfos.push(info)
})
@@ -170,6 +170,13 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
this.express = express()
this.express.use(express.static('static'))
this.express.get('/plugins/:id'+".js", (request, response) => {
let frontend = this.pm.getFrontend(request.params.id)
response.status(200)
response.set('Content-Type', 'application/javascript')
response.send(frontend)
})
this.httpServer = new http.Server(this.express)
this.httpServer.listen(port, () => {
logger.info('Admin panel listening for HTTP on *'+port)
@@ -257,6 +264,4 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
}
}
(async() => {
new FrontblockAdmin()
})()
new FrontblockAdmin()
+7 -3
View File
@@ -22,7 +22,7 @@ export class PluginManagerPlugin extends PluginManager implements Plugin{
constructor(){
super()
this.loadedPlugins[this.name] = this
this.loadedPlugins[this.name] = {backend:this, frontend: this.loadFrontend(this.name)}
}
exportRPCs(): import("frontblock-generic/Plugin").socketioRPC[] {
@@ -44,8 +44,12 @@ export class PluginManagerPlugin extends PluginManager implements Plugin{
visibility: "private",
rpc: async () => { return this.getLoadedPlugins() },
type: 'call'
},
{
},{
name: "getLoadedPluginNames",
visibility: "private",
rpc: async () => { return this.getLoadedPluginNames() },
type: 'call'
},{
name: "installPlugin",
visibility: "private",
rpc: async(pluginName:string) => { return await this.installPlugin(pluginName) },
+42 -18
View File
@@ -29,7 +29,7 @@ type PluginVersion = {
export type PluginVersioning = {
[pluginName in string]?: PluginVersion | string
}
export type PluginMap = {[pluginName:string]: Plugin}
export type PluginMap = {[pluginName:string]: {backend: Plugin, frontend:any}}
export type PluginManagerConfig = {
resourceLocation: string,
@@ -45,11 +45,13 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
super("PluginManager")
this.cacheDir = path.join(this.conf.installDir, '.cache')
this.initialize()
this.loadPlugin("../../../../../../apiclient")
this.installPlugin("ApiClient")
}
getDefaultConfig(): PluginManagerConfig&PluginVersioning{
return {resourceLocation: "https://gitea.frontblock.me/api/v1/repos/fb-vendor/", installDir: "./plugins"}
return {resourceLocation: "https://gitea.frontblock.me/api/v1/repos/fb-vendor/", installDir: "plugins"}
}
@@ -91,6 +93,10 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
}
}
public getLoadedPluginNames(): string[] {
return Object.keys(this.loadedPlugins)
}
public getLoadedPlugins(): PluginMap {
return this.loadedPlugins
}
@@ -98,12 +104,6 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
private async downloadFile(url: URL, dest: string) {
try {
fs.access(path.dirname(dest), err => {
if (err && err.code === 'ENOENT') {
fs.mkdirSync(path.dirname(dest), {recursive: true})
}
})
const file = fs.createWriteStream(dest)
file.on('error', err => {throw new Error(err)})
const response = await fetch(url)
@@ -119,6 +119,7 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
try {
logger.info("Downloading Plugin")
logger.error(this.conf.resourceLocation + pluginName + '/releases')
const response = await fetch(this.conf.resourceLocation + pluginName + '/releases')
if (!response.ok) throw new Error(response.statusText)
@@ -127,27 +128,44 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
const latest = releases[0]
const version = latest.tag_name
const archiveURL = latest.assets.filter(asset => asset.name === pluginName + '.zip')[0].browser_download_url
const archiveURL = latest.assets.filter(asset => asset.name === 'plugin.zip')[0].browser_download_url
const checksumURL = latest.assets.filter(asset => asset.name === 'md5sum.txt')[0].browser_download_url
if (!version || ! archiveURL || !checksumURL) throw new Error('Malformed response')
await this.downloadFile(archiveURL, path.join(this.cacheDir, pluginName, version, 'plugin.zip'))
await this.downloadFile(checksumURL, path.join(this.cacheDir, pluginName, version, 'md5sum.txt'))
await fs.access(path.join(this.cacheDir, pluginName), err => {
if (err && err.code === 'ENOENT') {
fs.mkdirSync(path.join(this.cacheDir, pluginName), {recursive: true})
}
})
await this.downloadFile(archiveURL, path.join(this.cacheDir, pluginName, 'plugin.zip'))
await this.downloadFile(checksumURL, path.join(this.cacheDir, pluginName, 'md5sum.txt'))
} catch (error) {
logger.error(error)
}
}
private extractPlugin(pluginName: string){
fs
.createReadStream(path.join(this.cacheDir, pluginName, "plugin.zip"))
.pipe(unzip.Extract({ path: path.join(this.conf.installDir,pluginName) }));
}
public async installPlugin(pluginName: string) {
try {
await this.downloadPlugin(pluginName)
//TODO do something
await this.extractPlugin(pluginName)
await this.loadPlugin(pluginName)
} catch (error) {
logger.error(error)
}
}
public getFrontend(pluginName: string){
return this.loadedPlugins[pluginName].frontend.toString()
}
public async uninstallPlugin(pluginName: string) {
//TODO check for exists
logger.info("Deleting plugin", pluginName)
@@ -156,12 +174,18 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
public async loadPlugin(pluginName:string) {
const pth = path.join(this.conf.installDir, pluginName, "Plugin")
logger.info("Loading plugin from fs", pth)
const clazz = await import(pth)
const pth = path.join("..", "..", this.conf.installDir, pluginName, "static")
logger.info("Loading plugin from fs", pth+"/Plugin")
const clazz = await import(pth+"/Plugin")
let obj:Plugin = new clazz.default()
await obj.start()
this.loadedPlugins[pluginName] = obj
this.loadedPlugins[pluginName] = {backend: obj, frontend: this.loadFrontend(pluginName)}
}
public loadFrontend(pluginName:string){
const pth = path.join("..", "..", this.conf.installDir, pluginName, "static")
logger.info("Loading frontend plugin from fs", path.join(__dirname,pth,"FrontendPlugin.js"))
return fs.readFileSync(path.join(__dirname, pth,"FrontendPlugin.js"))
}
@@ -171,7 +195,7 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
return
}
logger.info("Unloading plugin ", pluginName)
this.loadedPlugins[pluginName].stop()
this.loadedPlugins[pluginName].backend.stop()
delete this.loadedPlugins[pluginName]
}
}