import Application from './application.mjs' import Util from './util.mjs' import { Low } from 'lowdb' export default class Core { static providers = new Map() static addProvider(name, provider) { if (!name || typeof(name) !== 'string') throw new Error('addProvider name must be a string') if (typeof(provider) !== 'function') throw new Error(`addProvider ${name} provider must be a class`) let test = new provider({}) if (typeof(test.checkConfig) !== 'function') throw new Error(`addProvider ${name} provider class missing checkConfig`) if (typeof(test.getLatestVersion) !== 'function') throw new Error(`addProvider ${name} provider class missing getLatestVersion`) Core.providers.set(name, provider) } constructor(db, util, log, restart) { // some sanity checks if (typeof(restart) !== 'function') throw new Error('restart parameter was not a function') if (!log || typeof(log) !== 'object') throw new Error('log parameter was invalid') if (typeof(log.event) !== 'object') throw new Error('log parameter was invalid') if (typeof(log.info) !== 'function' || typeof(log.warn) !== 'function' || typeof(log.error) !== 'function' || typeof(log.event.info) !== 'function' || typeof(log.event.warn) !== 'function' || typeof(log.event.error) !== 'function') throw new Error('log parameter was invalid') if (!util || !(util instanceof Util)) throw new Error('util not instance of Util') if (!db || !(db instanceof Low)) throw new Error('db not instance of Low') this.db = db this.util = util this.log = log this.restart = restart this.applications = [] this.applicationMap = new Map() } getApplication(name) { return this.applicationMap.get(name) } async init() { this.util.verifyConfig(this.db.config) let names = this.util.getAppNames(this.db.config) let lastError = null for (let name of names) { try { let provConstructor = Core.providers.get(this.db.config[name].provider) let provider = new provConstructor(this.db.config[name]) await provider.checkConfig(this.db.config[name]) let application = new Application({ db: this.db, util: this.util, log: this.log, core: this, }, provider, name) this.applications.push(application) this.applicationMap.set(name, application) } catch (err) { this.log.error(err, `Error creating application ${name} with provider ${this.db.config[name].provider}: ${err.message}`) lastError = err } } if (names.length && !this.applications.length) { throw lastError } } async runApplication(name) { let application = this.applicationMap.get(name) if (!application) { return Promise.reject(new Error(`Core.runApplication was called on a non-existing application name ${name}`)) } let found = false for (let i = 0; i < this.db.data.core[name].versions.length; i++) { let version = this.db.data.core[name].versions[i] await application.closeServer() try { await application.runVersion() } catch(err) { this.log.error(err, `Error starting ${name} ${version.id}: ${err.message}`) } } throw new Error(``) } }