fix admin not exporting own RPCs for real lol
This commit is contained in:
@@ -1,428 +0,0 @@
|
|||||||
|
|
||||||
import * as Logger from 'log4js'
|
|
||||||
import * as path from "path";
|
|
||||||
import { promises as fs } from "fs"
|
|
||||||
import * as git from "simple-git/promise"
|
|
||||||
import * as trash from "trash"
|
|
||||||
|
|
||||||
|
|
||||||
Logger.configure({
|
|
||||||
appenders:
|
|
||||||
{
|
|
||||||
"admin/extension": { type: 'stdout' },
|
|
||||||
//app: { type: 'file', filename: 'application.log' }
|
|
||||||
},
|
|
||||||
categories:
|
|
||||||
{
|
|
||||||
default: { appenders: [ 'admin/extension' ], level: 'debug' }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const exec = require('child-process-promise').exec;
|
|
||||||
const logger = Logger.getLogger("admin/updatemanager")
|
|
||||||
|
|
||||||
type SharedStatus = {
|
|
||||||
name: string
|
|
||||||
installed?: boolean
|
|
||||||
outdated?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Extension<Status extends SharedStatus>{
|
|
||||||
constructor(
|
|
||||||
protected name: string
|
|
||||||
){}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the generic Status object
|
|
||||||
*/
|
|
||||||
protected async status():Promise<Status>{
|
|
||||||
const installed = await this.isInstalled()
|
|
||||||
const outdated = await this.isOutdated()
|
|
||||||
return <Status>{ name: this.name, installed: installed, outdated: outdated }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true => extension was installed
|
|
||||||
* false => extension was not install
|
|
||||||
* undefined => signals error
|
|
||||||
*/
|
|
||||||
abstract async install():Promise<boolean | undefined>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reverts the install procedure
|
|
||||||
*/
|
|
||||||
abstract async uninstall():Promise<void>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true => an update was performed
|
|
||||||
* false => no update was performed
|
|
||||||
* undefined => signals error
|
|
||||||
*/
|
|
||||||
abstract async update(force?: boolean): Promise<boolean | undefined>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true => update would install a newer version
|
|
||||||
* false => nothing would be updated if update would be performed
|
|
||||||
* undefined => signals error
|
|
||||||
*/
|
|
||||||
abstract async isOutdated():Promise<boolean | undefined>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* promises a boolean
|
|
||||||
* true => install would do nothing would it be called
|
|
||||||
* false => install would try to install the newest extension
|
|
||||||
* undefined => signals error
|
|
||||||
*/
|
|
||||||
abstract async isInstalled():Promise<boolean | undefined>
|
|
||||||
}
|
|
||||||
|
|
||||||
export type FSStatus = SharedStatus & {
|
|
||||||
path: string
|
|
||||||
empty?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class FSExtension<Status extends FSStatus> extends Extension<Status>{
|
|
||||||
constructor(
|
|
||||||
name: string,
|
|
||||||
protected readonly path: string){
|
|
||||||
super(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async status(): Promise<Status>{
|
|
||||||
const shdStatus = await super.status()
|
|
||||||
const empty = await this.isEmpty()
|
|
||||||
return {...shdStatus, prefix: this.path, empty: empty}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async install():Promise<boolean>{
|
|
||||||
const installed = await this.isInstalled()
|
|
||||||
if (!installed) {
|
|
||||||
logger.info('Installing extension to', path.resolve(this.path, this.name))
|
|
||||||
await fs.mkdir(path.resolve(this.path, this.name), {recursive: true})
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
logger.error('Extension already installed at', path.resolve(this.path, this.name))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
public async uninstall(): Promise<void>{
|
|
||||||
logger.info('Uninstalling extension from', path.resolve(this.path, this.name))
|
|
||||||
return await trash(path.resolve(this.path, this.name))
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(force?: boolean): Promise<boolean | undefined>{
|
|
||||||
if (force) await this.uninstall()
|
|
||||||
return await this.install()
|
|
||||||
}
|
|
||||||
|
|
||||||
public async isEmpty(): Promise<boolean | undefined>{
|
|
||||||
if (!this.isInstalled()) return true
|
|
||||||
try {
|
|
||||||
const files = await fs.readdir(path.resolve(this.path, this.name))
|
|
||||||
return files.length === 0
|
|
||||||
} catch (error) {
|
|
||||||
logger.error("fs read error", error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async isInstalled(): Promise<boolean>{
|
|
||||||
try {
|
|
||||||
await fs.access(path.resolve(this.path, this.name))
|
|
||||||
return true
|
|
||||||
} catch (error) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type NPMStatus = FSStatus & {
|
|
||||||
latest?: string,
|
|
||||||
current?: string,
|
|
||||||
author?: string
|
|
||||||
license?: string,
|
|
||||||
description?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NPMExtension extends FSExtension<NPMStatus>{
|
|
||||||
private prefix: string
|
|
||||||
constructor(
|
|
||||||
pkgName: string,
|
|
||||||
prefix: string = './plugins',
|
|
||||||
private version: string,
|
|
||||||
){
|
|
||||||
super(pkgName, path.resolve(prefix, pkgName, "node_modules"))
|
|
||||||
this.prefix = (path.resolve(prefix, pkgName))
|
|
||||||
}
|
|
||||||
|
|
||||||
public async status(): Promise<NPMStatus> {
|
|
||||||
|
|
||||||
const fsStatus = await super.status()
|
|
||||||
const latest = await this.getLatestVersion()
|
|
||||||
const author = await this.getAuthor()
|
|
||||||
const current = await this.getCurrentVersion()
|
|
||||||
const license = await this.getLicense()
|
|
||||||
const description = await this.getDescription()
|
|
||||||
|
|
||||||
return {
|
|
||||||
...fsStatus,
|
|
||||||
latest: latest,
|
|
||||||
author: author,
|
|
||||||
current: current,
|
|
||||||
license: license,
|
|
||||||
description: description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async install(): Promise<boolean> {
|
|
||||||
super.install()
|
|
||||||
logger.info("npm install", this.name, 'to', path.resolve(this.prefix, this.name))
|
|
||||||
const { error, stdout, stderr } = await exec('npm install --prefix '+ this.prefix + ' ' + this.name+"@"+this.version)
|
|
||||||
if (error) {
|
|
||||||
logger.error('npm install', this.name, "@", this.version, ' from prefix', this.prefix, 'stderr:', stderr)
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
logger.info('npm install', this.name, "@", this.version, 'from prefix', this.prefix, 'stdout:', stdout)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async uninstall(force?: boolean): Promise<void> {
|
|
||||||
super.uninstall()
|
|
||||||
logger.info("npm uninstall", this.name, 'from', path.resolve(this.prefix, this.name))
|
|
||||||
const { error, stdout, stderr } = await exec('npm uninstall --prefix '+ this.prefix + ' ' + this.name)
|
|
||||||
if (error) {
|
|
||||||
logger.error('npm uninstall', this.name, 'from prefix', this.prefix, 'stderr:', stderr)
|
|
||||||
} else {
|
|
||||||
logger.info('npm uninstall', this.name, 'from prefix', this.prefix, 'stdout:', stdout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(force?: boolean): Promise<boolean> {
|
|
||||||
super.update(force)
|
|
||||||
logger.info("npm update", path.resolve(this.prefix, this.name))
|
|
||||||
const { error, stdout, stderr } = await exec('npm update --prefix '+ this.prefix + ' ' + this.name)
|
|
||||||
if (error) {
|
|
||||||
logger.error('npm update', this.name, 'from prefix', this.prefix, 'stderr:', stderr)
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
logger.info('npm update', this.name, 'from prefix', this.prefix, 'stdout:', stdout)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async isOutdated(): Promise<boolean | undefined> {
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
error,
|
|
||||||
stdout,
|
|
||||||
stderr } = await exec('npm outdated --prefix ' + this.prefix + " --json" + ' ' + this.name)
|
|
||||||
if (error) throw new Error(stderr)
|
|
||||||
if (Object.keys(JSON.parse(stdout)).length > 0) return true
|
|
||||||
else return false
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('npm outdated', this.name, 'from prefix', this.prefix, 'stderr:', error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getAuthor(): Promise<string | undefined>{
|
|
||||||
const {
|
|
||||||
error,
|
|
||||||
stdout,
|
|
||||||
stderr } = await exec('npm author ls --prefix ' + this.prefix + ' ' + this.name)
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
logger.error(stderr)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
logger.info(stdout)
|
|
||||||
return stdout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getLatestVersion(): Promise<string | undefined>{
|
|
||||||
try{
|
|
||||||
const {
|
|
||||||
error,
|
|
||||||
stdout,
|
|
||||||
stderr } = await exec('npm view --prefix ' + this.prefix + ' ' + this.name + " version")
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
logger.error(stderr)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
logger.info(stdout)
|
|
||||||
return stdout
|
|
||||||
}
|
|
||||||
}catch(error){
|
|
||||||
logger.error(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getCurrentVersion(): Promise<string | undefined>{
|
|
||||||
try{
|
|
||||||
const {
|
|
||||||
error,
|
|
||||||
stdout,
|
|
||||||
stderr } = await exec('npm list --json --prefix ' + this.prefix + ' ' + this.name)
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
logger.error(stderr)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
logger.info(stdout)
|
|
||||||
return JSON.parse(stdout)
|
|
||||||
['dependencies']
|
|
||||||
['frontblock']
|
|
||||||
['dependencies']
|
|
||||||
[this.name]
|
|
||||||
['version']
|
|
||||||
}
|
|
||||||
}catch(error){
|
|
||||||
logger.error(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getDescription(): Promise<string | undefined>{
|
|
||||||
try{
|
|
||||||
const {
|
|
||||||
error,
|
|
||||||
stdout,
|
|
||||||
stderr } = await exec('npm show --prefix ' + this.prefix + ' ' + this.name+" description")
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
logger.error(stderr)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
logger.info(stdout)
|
|
||||||
return stdout
|
|
||||||
}
|
|
||||||
}catch(error){
|
|
||||||
logger.error(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getLicense(): Promise<string | undefined>{
|
|
||||||
try{
|
|
||||||
|
|
||||||
const {
|
|
||||||
error,
|
|
||||||
stdout,
|
|
||||||
stderr } = await exec('npm show --prefix ' + this.prefix + ' ' + this.name+" license")
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
logger.error(stderr)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
logger.info(stdout)
|
|
||||||
return stdout
|
|
||||||
}
|
|
||||||
}catch(error){
|
|
||||||
logger.error(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GitStatus = FSStatus & {
|
|
||||||
branch?: string
|
|
||||||
remote?: string
|
|
||||||
latest?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GitExtension<Status extends GitStatus> extends FSExtension<Status>{
|
|
||||||
protected repo: git.SimpleGit
|
|
||||||
constructor(
|
|
||||||
repoName:string,
|
|
||||||
localPrefix:string,
|
|
||||||
protected gitCloneURL: string,
|
|
||||||
protected credentials?: [string, string]
|
|
||||||
){
|
|
||||||
super(repoName, localPrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async status(): Promise<Status>{
|
|
||||||
const fsStatus = await super.status()
|
|
||||||
|
|
||||||
return {
|
|
||||||
...fsStatus,
|
|
||||||
branch: 'wat',
|
|
||||||
remote: this.gitCloneURL,
|
|
||||||
latest: 'kek'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async install(): Promise<boolean> {
|
|
||||||
if (super.install()){
|
|
||||||
if (this.credentials){
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async update(): Promise<boolean> {
|
|
||||||
return true // do git pull remote origin && git checkout
|
|
||||||
}
|
|
||||||
|
|
||||||
public async isOutdated(): Promise<boolean> {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PluginStatus = GitStatus & {
|
|
||||||
hasFrontend: boolean,
|
|
||||||
hasBackend: boolean,
|
|
||||||
isFrontendLoaded: boolean,
|
|
||||||
isBackendLoaded: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PluginExtension<Status extends GitStatus> extends GitExtension<Status> {
|
|
||||||
protected frontendLoaded: boolean
|
|
||||||
protected backendLoaded: boolean
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
pluginName: string,
|
|
||||||
gitCloneURL: string,
|
|
||||||
localPrefix: string = './plugins',
|
|
||||||
credentials?: [string, string],
|
|
||||||
protected hasBackend: boolean = true,
|
|
||||||
protected hasFrontend: boolean = true){
|
|
||||||
super(pluginName,localPrefix,gitCloneURL,credentials)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async load(): Promise<void>{
|
|
||||||
if (this.hasFrontend) await this.loadFrontend()
|
|
||||||
if (this.hasBackend) await this.loadBackend()
|
|
||||||
}
|
|
||||||
|
|
||||||
public async loadFrontend(): Promise<void>{
|
|
||||||
return //TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
public async loadBackend(): Promise<void>{
|
|
||||||
return //TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
public async unload(): Promise<void>{
|
|
||||||
if (this.hasFrontend) await this.unloadFrontend()
|
|
||||||
if (this.hasBackend) await this.unloadBackend()
|
|
||||||
}
|
|
||||||
|
|
||||||
public async unloadFrontend(): Promise<void>{
|
|
||||||
return //TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
public async unloadBackend(): Promise<void>{
|
|
||||||
return //TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -84,7 +84,6 @@ export class FrontblockAdmin extends AdminBase<AdminConf>{
|
|||||||
private async initialize(){
|
private async initialize(){
|
||||||
this.addPlugin(this.updateManager)
|
this.addPlugin(this.updateManager)
|
||||||
await this.updateManager.updateAdmin()
|
await this.updateManager.updateAdmin()
|
||||||
await this.updateManager.updatePlatformDependencies()
|
|
||||||
await this.updateManager.updateDashboard()
|
await this.updateManager.updateDashboard()
|
||||||
await this.updateManager.updateFrontblockLib()
|
await this.updateManager.updateFrontblockLib()
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -5,21 +5,21 @@ var exec = require('child-process-promise').exec;
|
|||||||
Logger.configure({
|
Logger.configure({
|
||||||
appenders:
|
appenders:
|
||||||
{
|
{
|
||||||
"admin": { type: 'stdout' },
|
"main": { type: 'stdout' },
|
||||||
//app: { type: 'file', filename: 'application.log' }
|
//app: { type: 'file', filename: 'application.log' }
|
||||||
},
|
},
|
||||||
categories:
|
categories:
|
||||||
{
|
{
|
||||||
default: { appenders: [ 'admin' ], level: 'debug' }
|
default: { appenders: [ 'main' ], level: 'debug' }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const logger = Logger.getLogger("admin")
|
const logger = Logger.getLogger("main")
|
||||||
|
|
||||||
|
|
||||||
logger.info("Checking npm dependencies...")
|
logger.info("Checking npm dependencies...")
|
||||||
exec("npm i --prefix ./plugins knex@0.19.2 sqlite3@4.1.0").then(process => {
|
exec("npm i --prefix ./plugins knex@0.19.2 sqlite3@4.1.0").then(process => {
|
||||||
logger.debug(process.stdout)
|
logger.debug(process.stdout)
|
||||||
const admin = require("./FrontblockAdmin").FrontblockAdmin
|
const Admin = require("./FrontblockAdmin").FrontblockAdmin
|
||||||
new admin()
|
new Admin()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,8 @@ import { GitUpdater, RepoFolderStatus } from "./GitUpdater";
|
|||||||
import { FrontblockCherryPicker } from "git-cherrypicker";
|
import { FrontblockCherryPicker } from "git-cherrypicker";
|
||||||
import * as Logger from 'log4js'
|
import * as Logger from 'log4js'
|
||||||
import { FrontblockAdmin } from "./FrontblockAdmin";
|
import { FrontblockAdmin } from "./FrontblockAdmin";
|
||||||
import { NPMExtension } from "./Extension";
|
|
||||||
import { TableDefiniton } from "frontblock-generic/Admin";
|
import { TableDefiniton } from "frontblock-generic/Admin";
|
||||||
|
|
||||||
var exec = require('child-process-promise').exec;
|
|
||||||
|
|
||||||
Logger.configure({
|
Logger.configure({
|
||||||
appenders:
|
appenders:
|
||||||
{
|
{
|
||||||
@@ -24,7 +21,6 @@ const logger = Logger.getLogger("admin/updatemanager")
|
|||||||
|
|
||||||
export class UpdateManager extends Plugin{
|
export class UpdateManager extends Plugin{
|
||||||
|
|
||||||
|
|
||||||
private loadedPlugins:{[name in string]:Plugin} = {}
|
private loadedPlugins:{[name in string]:Plugin} = {}
|
||||||
private dashboardUpdater:GitUpdater
|
private dashboardUpdater:GitUpdater
|
||||||
private adminUpdater:GitUpdater
|
private adminUpdater:GitUpdater
|
||||||
@@ -76,16 +72,6 @@ export class UpdateManager extends Plugin{
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
async updatePlatformDependencies(){
|
|
||||||
|
|
||||||
logger.info("installing npm stuff")
|
|
||||||
const extensions:NPMExtension[] = []
|
|
||||||
|
|
||||||
await Promise.all(extensions.map(e => e.install()))
|
|
||||||
const status = await Promise.all(extensions.map(e => e.status()))
|
|
||||||
console.log(status)
|
|
||||||
}
|
|
||||||
|
|
||||||
async installPlugin(name: string, force:boolean = false):Promise<RepoFolderStatus>{
|
async installPlugin(name: string, force:boolean = false):Promise<RepoFolderStatus>{
|
||||||
logger.warn("Cloning fb-dist/"+name+".git into ./plugins/"+name+" ..."+(force?" USING FORCE!":""))
|
logger.warn("Cloning fb-dist/"+name+".git into ./plugins/"+name+" ..."+(force?" USING FORCE!":""))
|
||||||
this.pluginUpdaters[name] = new GitUpdater("./plugins/"+name)
|
this.pluginUpdaters[name] = new GitUpdater("./plugins/"+name)
|
||||||
|
|||||||
Reference in New Issue
Block a user