This commit is contained in:
peter
2019-08-03 22:40:15 +02:00
parent 3c0db6dca9
commit 6601b4bf2f
14 changed files with 188 additions and 25 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
import * as Logger from 'log4js'
import { Plugin, socketioRPC, ConfigLoader } from 'frontblock-generic/Plugin';
import { ErrorResponse, SuccessResponse } from 'frontblock-generic/Types';
import { PluginManagerPlugin } from './PluginManager/Plugin'
import { default as PluginManagerPlugin } from './PluginManager/Plugin'
import express = require('express');
import http = require('http');
import bsock = require('bsock');
+1 -4
View File
@@ -17,12 +17,9 @@ const logger = Logger.getLogger("PluginManager/Plugin")
export default class PluginManagerPlugin extends PluginManager implements Plugin{
name: string;
constructor(){
super()
this.installPlugin(this.name)
}
exportRPCs(): import("frontblock-generic/Plugin").socketioRPC[] {
@@ -83,7 +80,7 @@ export default class PluginManagerPlugin extends PluginManager implements Plugin
}
async start(): Promise<void> {
await this.installPlugin("admin") //self-update
await this.loadPlugin("admin")
}
stop(): void {
+46 -18
View File
@@ -6,7 +6,7 @@ import fs = require('fs');
import path = require('path')
import unzip = require('unzip')
import { Plugin, ConfigLoader } from 'frontblock-generic/Plugin';
import { SemVer } from "semver";
import { SemVer, parse } from "semver";
Logger.configure({
appenders:
@@ -24,7 +24,6 @@ const logger = Logger.getLogger("PluginManager")
type PluginVersion = {
installed?: SemVer,
cached?: SemVer,
loaded?: SemVer
}
export type PluginVersioning = {
[pluginName in string]?: PluginVersion | string
@@ -45,9 +44,6 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
super("PluginManager")
this.cacheDir = path.join(this.conf.installDir, '.cache')
this.initialize()
//this.installPlugin("ApiClient")
}
getDefaultConfig(): PluginManagerConfig&PluginVersioning{
@@ -108,26 +104,40 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
file.on('error', err => {throw new Error(err)})
const response = await fetch(url)
if (!response.ok) throw new Error(response.statusText)
response.body.pipe(file)
await response.body.pipe(file)
} catch (error) {
logger.error(error)
await fs.promises.unlink(dest)
}
}
private async getLatestRelease(pluginName:string):Promise<any>{
logger.info("Downloading Plugin", pluginName)
if(pluginName === this.name) pluginName = "admin"
logger.error(this.conf.resourceLocation + pluginName + '/releases')
const response = await fetch(this.conf.resourceLocation + pluginName + '/releases')
if (!response.ok) throw new Error(pluginName+": "+response.statusText)
const releases = await response.json()
if (!releases || !releases.length) throw new Error('Empty response')
return releases[0]
}
private async getLatestVersion(pluginName:string):Promise<SemVer>{
const latest = await this.getLatestRelease(pluginName)
const version = latest.tag_name
return parse(version)!
}
private async downloadPlugin(pluginName: string) {
try {
logger.info("Downloading Plugin", pluginName)
if(pluginName === this.name) pluginName = "admin"
logger.error(this.conf.resourceLocation + pluginName + '/releases')
const response = await fetch(this.conf.resourceLocation + pluginName + '/releases')
if (!response.ok) throw new Error(pluginName+": "+response.statusText)
let version = await this.getLatestVersion(pluginName)
const releases = await response.json()
if (!releases || !releases.length) throw new Error('Empty response')
const latest = releases[0]
const version = latest.tag_name
if(this.conf[pluginName] != null && version == this.conf[pluginName]!["installed"]){
return
}
const latest = await this.getLatestRelease(pluginName)
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')
@@ -141,6 +151,13 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
await this.downloadFile(archiveURL, path.join(this.cacheDir, pluginName, 'plugin.zip'))
await this.downloadFile(checksumURL, path.join(this.cacheDir, pluginName, 'md5sum.txt'))
if(this.conf[pluginName] == null){
this.conf[pluginName] = {}
}
this.conf[pluginName]!["cached"] = version
this.updateConfig(this.conf)
} catch (error) {
logger.error(error)
}
@@ -151,12 +168,22 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
const archivePath = path.join(this.cacheDir, pluginName, "plugin.zip")
const outputPath = path.join(this.conf.installDir,pluginName)
await fs.createReadStream(archivePath).pipe(unzip.Extract({ path: outputPath }));
if(this.conf[pluginName] == null){
this.conf[pluginName] = {}
}
this.conf[pluginName]!["installed"] = this.conf[pluginName]!["cached"]
this.updateConfig(this.conf)
}
public async installPlugin(pluginName: string) {
try {
await this.downloadPlugin(pluginName)
await this.extractPlugin(pluginName)
let version = await this.getLatestVersion(pluginName)
if(this.conf[pluginName] != null || version != this.conf[pluginName]!["installed"]){
await this.downloadPlugin(pluginName)
await this.extractPlugin(pluginName)
}
await this.loadPlugin(pluginName)
} catch (error) {
logger.error(error)
@@ -179,6 +206,7 @@ export default class PluginManager extends ConfigLoader<PluginManagerConfig&Plug
const pth = path.join("..", "..", this.conf.installDir, pluginName)
logger.info("Loading plugin from fs", pth+"/Plugin")
const clazz = await import(pth+"/Plugin")
logger.warn(clazz)
let obj:Plugin = new clazz.default()
await obj.start()
this.loadedPlugins[pluginName] = {backend: obj, frontend: this.loadFrontend(pluginName)}
+1 -1
View File
@@ -7,7 +7,7 @@ const path = require('path');
mode: 'production',
entry: path.resolve(__dirname, '../../lib/FrontblockLib.js'),
output: {
path: path.resolve(__dirname, '../../../static'),
path: path.resolve(__dirname, '../../static'),
filename: 'FrontblockLib.js',
},
module: {