UNPKG

@launchmenu/core

Version:

An environment for visual keyboard controlled applets

259 lines 20.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppletManager = void 0; const hmr_1 = __importStar(require("@launchmenu/hmr")); const model_react_1 = require("model-react"); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const createAppletResultCategory_1 = require("./createAppletResultCategory"); const withLM_1 = require("./declaration/withLM"); const JSONFile_1 = require("../../settings/storage/fileTypes/JSONFile"); /** * A manager of applets, takes care of loading applets given their locations */ class AppletManager { /** * Creates a new applet manager instances with the given sources * @param LM The LM instance that this applet manager is for * @param settingsDirectory The directory to retrieve the installed applets from * @param reloadOnChanges Whether to listen for applet code changes and update the applet when such a change occurs */ constructor(LM, settingsConfig, reloadOnChanges = LM.isInDevMode()) { this.destroyed = new model_react_1.Field(false); /** A field that can be used to dynamically add any applets to the manager (does require some manual maintenance) */ this.extraApplets = new model_react_1.Field([]); // TODO: make helper methods to manager the extra applets /** Versions numbers of the applets, such that applets are reloaded if their version changes */ this.appletVersions = new model_react_1.Field({}); /** * The sources in an array form */ this.sources = new model_react_1.DataCacher(h => { const appletsObject = this.sourceFile.get(h); if (appletsObject instanceof Object && !(appletsObject instanceof Array)) { const appletSources = Object.keys(appletsObject).flatMap(ID => { const data = appletsObject[ID]; if (typeof data == "string") return { ID, directory: data }; else return []; }); return appletSources; } else { console.error("No valid applets config was found"); return []; } }); /** * A transformer that obtains applets from the sources, versions and whether this manager is destroyed */ this.applets = new model_react_1.DataCacher((h, prevApplets = []) => { const destroyed = this.destroyed.get(h); const sources = destroyed ? [] : this.sources.get(h); const versions = this.appletVersions.get(h); const sourcesWithVersions = sources.map(source => { var _a; return ({ ...source, version: (_a = versions[source.ID]) !== null && _a !== void 0 ? _a : 0, }); }); // Dispose of any applets that are no longer used (or of which a new version is requested) prevApplets.forEach(appletData => { const stillUsed = !!sourcesWithVersions.find(source => source.ID == appletData.applet.ID && source.version == appletData.version); if (!stillUsed) this.disposeAppletData(appletData); }); // Retrieve the new list of applets, using the previously initialized applet if available const applets = sourcesWithVersions.flatMap(source => { var _a, _b; const prevApplet = prevApplets.find(({ applet, version }) => applet.ID == source.ID && version == source.version); if (prevApplet) return prevApplet; // If no applet exists for this source yet, create it try { const applet = this.initApplet(source, source.version); return { applet, category: createAppletResultCategory_1.createAppletResultCategory(applet), version: source.version, watcher: ((_a = applet.development) === null || _a === void 0 ? void 0 : _a.liveReload) != false && this.reloadOnChanges ? this.setupAppletWatcher(source, applet) : undefined, }; } catch (e) { console.error(e); // If the latest version errored while loading, try to reinitialize the previous version const prev = prevApplets.find(({ applet }) => applet.ID == source.ID); if (prev) { return { ...prev, watcher: ((_b = prev.applet.development) === null || _b === void 0 ? void 0 : _b.liveReload) != false && this.reloadOnChanges ? this.setupAppletWatcher(source, prev.applet) : undefined, }; } return []; } }); return applets; }); this.LM = LM; this.settingsConfig = settingsConfig; this.reloadOnChanges = reloadOnChanges; this.sourceFile = new JSONFile_1.JSONFile(path_1.default.join(settingsConfig.directory, "applets.json")); } /** * Properly disposes all data associated to this applet * @param appletData The applet data to be disposed */ disposeAppletData(appletData) { var _a, _b, _c; try { (_b = (_a = appletData.applet).onDispose) === null || _b === void 0 ? void 0 : _b.call(_a); } catch (e) { console.error(e); } this.settingsConfig.removeSettings(appletData.applet.ID); (_c = appletData.watcher) === null || _c === void 0 ? void 0 : _c.destroy(); } /** * Disposes of all data */ destroy() { this.destroyed.set(true); // Force retrieve the applets to uninitialize old applets this.applets.get(); this.extraApplets.set([]); } // Getters /** * Retrieves all the applets, including dynamic extra applets * @param hook The hook to subscribe to changes * @returns The applets data */ getAppletsData(hook) { return [...this.applets.get(hook), ...this.extraApplets.get(hook)]; } /** * Retrieves the loaded applets * @param hook The hook to subscribe to changes * @returns The applets */ getApplets(hook) { return this.getAppletsData(hook).map(({ applet }) => applet); } /** * Retrieves the loaded applet with the given ID * @param ID The ID of the applet to retrieve * @param hook The hook to subscribe to changes * @returns The applet if found */ getApplet(ID, hook) { var _a; return (((_a = this.getAppletsData(hook).find(({ applet }) => applet.ID == ID)) === null || _a === void 0 ? void 0 : _a.applet) || null); } /** * Retrieves the applet and categories that items for them can be listed in * @param hook The hook to subscribe to changes * @returns The applets and categories */ getAppletCategories(hook) { return this.getAppletsData(hook); } /** * Retrieves the category for the given applet * @param applet The applet to get the category of * @param hook The hook to subscribe to changes * @returns The category */ getAppletCategory(applet, hook) { var _a; return (_a = this.getAppletsData(hook).find(({ applet: { ID } }) => ID == applet.ID)) === null || _a === void 0 ? void 0 : _a.category; } // Applet management /** * Initializes an applet * @param source The source data of the applet * @param version The new version of the applet * @throws An exception if no valid applet was found * @returns The applet data */ initApplet({ ID, directory }, version) { var _a; // Obtain the module export and check if it has a valid applet export const appletExport = hmr_1.referencelessRequire(path_1.default.isAbsolute(directory) ? directory : path_1.default.join(process.cwd(), directory)); if ((_a = appletExport === null || appletExport === void 0 ? void 0 : appletExport.default) === null || _a === void 0 ? void 0 : _a.info) { // Load the applet if valid const baseApplet = { ...appletExport.default, ID, }; const settingsTree = this.settingsConfig.getSettings(baseApplet, version); return withLM_1.withLM(baseApplet, this.LM, settingsTree); } else { // Throw an error when the module has no proper applet throw Error(`Failed to load applet ${ID}, please make sure it has a proper default export`); } } /** * Retrieves a file watcher for a given applet * @param source The source of the applet * @param applet The applet to setup the watcher for * @returns The file watcher that was created */ setupAppletWatcher(source, applet) { var _a, _b; const baseDir = source.directory; const absoluteBaseDir = path_1.default.isAbsolute(baseDir) ? path_1.default.dirname(require.resolve(`${baseDir}/package.json`)) : path_1.default.join(process.cwd(), baseDir); const buildDir = path_1.default.resolve(absoluteBaseDir, (_b = (_a = applet.development) === null || _a === void 0 ? void 0 : _a.watchDirectory) !== null && _b !== void 0 ? _b : "build"); const watchDir = fs_1.default.existsSync(buildDir) ? buildDir : absoluteBaseDir; const watcher = hmr_1.default(watchDir, () => { var _a; try { // Update the version number in order to force a new instance to be initialized const oldVersions = this.appletVersions.get(); this.appletVersions.set({ ...oldVersions, [source.ID]: ((_a = oldVersions[source.ID]) !== null && _a !== void 0 ? _a : 0) + 1, }); console.log(`%cApplet %c${source.ID} %chas been reloaded`, "color: blue;", "color: green;", "color: blue;"); } catch (e) { console.error(e); } }); return watcher; } } exports.AppletManager = AppletManager; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXBwbGV0TWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHBsaWNhdGlvbi9hcHBsZXRzL0FwcGxldE1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHVEQUFzRTtBQUN0RSw2Q0FBeUQ7QUFHekQsZ0RBQXdCO0FBQ3hCLDRDQUFvQjtBQUlwQiw2RUFBd0U7QUFDeEUsaURBQTRDO0FBQzVDLHdFQUFtRTtBQWNuRTs7R0FFRztBQUNILE1BQWEsYUFBYTtJQWN0Qjs7Ozs7T0FLRztJQUNILFlBQ0ksRUFBYyxFQUNkLGNBQStCLEVBQy9CLGtCQUEyQixFQUFFLENBQUMsV0FBVyxFQUFFO1FBbEJyQyxjQUFTLEdBQUcsSUFBSSxtQkFBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBR3ZDLG9IQUFvSDtRQUM3RyxpQkFBWSxHQUFHLElBQUksbUJBQUssQ0FBQyxFQUFtQixDQUFDLENBQUMsQ0FBQyx5REFBeUQ7UUFFL0csK0ZBQStGO1FBQ3JGLG1CQUFjLEdBQUcsSUFBSSxtQkFBSyxDQUFDLEVBQTRCLENBQUMsQ0FBQztRQXlLbkU7O1dBRUc7UUFDTyxZQUFPLEdBQUcsSUFBSSx3QkFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ25DLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdDLElBQUksYUFBYSxZQUFZLE1BQU0sSUFBSSxDQUFDLENBQUMsYUFBYSxZQUFZLEtBQUssQ0FBQyxFQUFFO2dCQUN0RSxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRTtvQkFDMUQsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUMvQixJQUFJLE9BQU8sSUFBSSxJQUFJLFFBQVE7d0JBQUUs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