moved stuff

This commit is contained in:
Daniel Hübleitner
2019-08-27 15:09:29 +02:00
parent 0fb9aa0a9f
commit 0c38130296
4 changed files with 444 additions and 354 deletions
+93 -7
View File
@@ -733,6 +733,21 @@
"qs": "6.7.0",
"raw-body": "2.4.0",
"type-is": "~1.6.17"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"brace-expansion": {
@@ -1362,11 +1377,11 @@
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "2.0.0"
"ms": "^2.1.1"
}
},
"decamelize": {
@@ -1675,6 +1690,14 @@
"to-regex": "^3.0.1"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -1690,6 +1713,11 @@
"requires": {
"is-extendable": "^0.1.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
@@ -1736,6 +1764,21 @@
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"extend": {
@@ -1875,6 +1918,21 @@
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"find-cache-dir": {
@@ -3864,9 +3922,9 @@
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"mysql": {
"version": "2.17.1",
@@ -4984,6 +5042,21 @@
"statuses": "~1.5.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@@ -5118,6 +5191,14 @@
"use": "^3.1.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -5134,6 +5215,11 @@
"is-extendable": "^0.1.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+1
View File
@@ -24,6 +24,7 @@
"bsert": "0.0.10",
"bsock": "^0.1.9",
"child-process-promise": "^2.2.1",
"debug": "^4.1.1",
"express": "^4.16.4",
"frontblock": "^0.14.0",
"frontblock-generic": "^0.30.1",
+350
View File
@@ -0,0 +1,350 @@
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 & {
prefix: string
empty?: boolean
}
export abstract class FSExtension<Status extends FSStatus> extends Extension<Status>{
constructor(
name: string,
protected readonly prefix: string){
super(name)
}
public async status(): Promise<Status>{
const shdStatus = await super.status()
const empty = await this.isEmpty()
return <Status>{...shdStatus, prefix: this.prefix, empty: empty}
}
public async install():Promise<boolean>{
const installed = await this.isInstalled()
if (!installed) {
logger.info('Installing extension to', path.resolve(this.prefix, this.name))
await fs.mkdir(path.resolve(this.prefix, this.name), {recursive: true})
return true
}
logger.warn('Extension already installed at', path.resolve(this.prefix, this.name))
return false
}
public async uninstall(): Promise<void>{
logger.info('Uninstalling extension from', path.resolve(this.prefix, this.name))
return await trash(path.resolve(this.prefix, 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.prefix, this.name))
return files.length === 0
} catch (error) {
logger.warn('TODO')
return
}
}
public async isInstalled(): Promise<boolean>{
try {
await fs.access(path.resolve(this.prefix, this.name))
return true
} catch (error) {
return false
}
}
}
type NPMStatus = FSStatus & {
latest?: string,
current?: string,
author?: string
}
export class NPMExtension extends FSExtension<NPMStatus>{
constructor(
pkgName: string,
prefix: string){
super(pkgName, prefix)
}
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()
return {
...fsStatus,
latest: latest,
author: author,
current: current
}
}
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)
if (error !== null) {
logger.warn('npm install', this.name, 'from prefix', this.prefix, 'stderr:', stderr)
return false
} else {
logger.info('npm install', this.name, '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.warn('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.warn('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.warn('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.warn(stderr)
return
} else {
logger.info(stdout)
return stdout
}
}
private async getLatestVersion(): Promise<string | undefined>{
const {
error,
stdout,
stderr } = await exec('npm view --prefix ' + this.prefix + ' ' + this.name + " version")
if(error){
logger.warn(stderr)
return
} else {
logger.info(stdout)
return stdout
}
}
private async getCurrentVersion(): Promise<string | undefined>{
return //TODO
}
}
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 {
}
}
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
}
}
-347
View File
@@ -28,353 +28,6 @@ Logger.configure({
})
const logger = Logger.getLogger("admin/updatemanager")
/*
cool snibbet
const SharedStatus = <Status>
(privateStatus: Status) =>
(name: string) =>
(installed: boolean) =>
(outdated: boolean) =>
{
return {
name: name,
installed: installed,
outdated: outdated,
...privateStatus
}
}
*/
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 & {
prefix: string
empty?: boolean
}
export abstract class FSExtension<Status extends FSStatus> extends Extension<Status>{
constructor(
name: string,
protected readonly prefix: string){
super(name)
}
public async status(): Promise<Status>{
const shdStatus = await super.status()
const empty = await this.isEmpty()
return <Status>{...shdStatus, prefix: this.prefix, empty: empty}
}
public async install():Promise<boolean>{
const installed = await this.isInstalled()
if (!installed) {
logger.info('Installing extension to', path.resolve(this.prefix, this.name))
await fs.mkdir(path.resolve(this.prefix, this.name), {recursive: true})
return true
}
logger.warn('Extension already installed at', path.resolve(this.prefix, this.name))
return false
}
public async uninstall(): Promise<void>{
logger.info('Uninstalling extension from', path.resolve(this.prefix, this.name))
return await trash(path.resolve(this.prefix, 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.prefix, this.name))
return files.length === 0
} catch (error) {
logger.warn('TODO')
return
}
}
public async isInstalled(): Promise<boolean>{
try {
await fs.access(path.resolve(this.prefix, this.name))
return true
} catch (error) {
return false
}
}
}
type NPMStatus = FSStatus & {
latest?: string,
current?: string,
author?: string
}
export class NPMExtension extends FSExtension<NPMStatus>{
constructor(
pkgName: string,
prefix: string){
super(pkgName, prefix)
}
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()
return {
...fsStatus,
latest: latest,
author: author,
current: current
}
}
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)
if (error !== null) {
logger.warn('npm install', this.name, 'from prefix', this.prefix, 'stderr:', stderr)
return false
} else {
logger.info('npm install', this.name, '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.warn('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.warn('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.warn('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.warn(stderr)
return
} else {
logger.info(stdout)
return stdout
}
}
private async getLatestVersion(): Promise<string | undefined>{
const {
error,
stdout,
stderr } = await exec('npm view --prefix ' + this.prefix + ' ' + this.name + " version")
if(error){
logger.warn(stderr)
return
} else {
logger.info(stdout)
return stdout
}
}
private async getCurrentVersion(): Promise<string | undefined>{
return //TODO
}
}
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 {
}
}
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
}
}
export class UpdateManager extends Plugin{
private loadedPlugins:{[name in string]:Plugin} = {}