import appSettings from '../scripts/settings/appSettings'; import { pluginManager } from './pluginManager'; /* eslint-disable indent */ class PackageManager { #packagesList = []; #settingsKey = 'installedpackages1'; init() { console.groupCollapsed('loading packages'); const manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]'); return Promise.all(manifestUrls.map((url) => { return this.loadPackage(url); })) .then(() => { console.debug('finished loading packages'); return Promise.resolve(); }) .catch(() => { return Promise.resolve(); }).finally(() => { console.groupEnd('loading packages'); }); } get packages() { return this.#packagesList.slice(0); } install(url) { return this.loadPackage(url, true).then((pkg) => { const manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]'); if (!manifestUrls.includes(url)) { manifestUrls.push(url); appSettings.set(this.#settingsKey, JSON.stringify(manifestUrls)); } return pkg; }); } uninstall(name) { const pkg = this.#packagesList.filter((p) => { return p.name === name; })[0]; if (pkg) { this.#packagesList = this.#packagesList.filter((p) => { return p.name !== name; }); this.removeUrl(pkg.url); } return Promise.resolve(); } mapPath(pkg, pluginUrl) { const urlLower = pluginUrl.toLowerCase(); if (urlLower.startsWith('http:') || urlLower.startsWith('https:') || urlLower.startsWith('file:')) { return pluginUrl; } let packageUrl = pkg.url; packageUrl = packageUrl.substring(0, packageUrl.lastIndexOf('/')); packageUrl += '/'; packageUrl += pluginUrl; return packageUrl; } addPackage(pkg) { this.#packagesList = this.#packagesList.filter((p) => { return p.name !== pkg.name; }); this.#packagesList.push(pkg); } removeUrl(url) { let manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]'); manifestUrls = manifestUrls.filter((i) => { return i !== url; }); appSettings.set(this.#settingsKey, JSON.stringify(manifestUrls)); } loadPackage(url, throwError = false) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); const originalUrl = url; url += url.indexOf('?') === -1 ? '?' : '&'; url += 't=' + new Date().getTime(); xhr.open('GET', url, true); const onError = () => { if (throwError === true) { reject(); } else { this.removeUrl(originalUrl); resolve(); } }; xhr.onload = () => { if (this.status < 400) { const pkg = JSON.parse(this.response); pkg.url = originalUrl; this.addPackage(pkg); const plugins = pkg.plugins || []; if (pkg.plugin) { plugins.push(pkg.plugin); } const promises = plugins.map((pluginUrl) => { return pluginManager.loadPlugin(this.mapPath(pkg, pluginUrl)); }); Promise.all(promises).then(resolve, resolve); } else { onError(); } }; xhr.onerror = onError; xhr.send(); }); } } /* eslint-enable indent */ export default new PackageManager();