MCPcopy Create free account
hub / github.com/chieapp/chie / ExtensionManager

Class ExtensionManager

src/controller/extension-manager.ts:11–105  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

9type ExtensionManagerData = Record<string, {dirPath: string}>;
10
11export class ExtensionManager extends ConfigStoreItem {
12 onAddExtension: Signal<(extension: Extension) => void> = new Signal();
13 onRemoveExtension: Signal<(extension: Extension) => void> = new Signal();
14
15 #extensions: Record<string, Extension> = {};
16
17 constructor() {
18 super();
19 const sourceRootDir = path.resolve(__dirname, '..', '..');
20 const exportsDir = path.resolve(__dirname, '..', 'exports');
21 // Override how Node searches modules.
22 const nodeModulePaths = Module['_nodeModulePaths'];
23 Module['_nodeModulePaths'] = function(p) {
24 const nodeModulesIndex = p.indexOf('node_modules');
25 const fromNodeModule = nodeModulesIndex > -1 && nodeModulesIndex > sourceRootDir.length;
26 const fromInternal = p.startsWith(sourceRootDir + path.sep);
27 const paths = nodeModulePaths.call(this, p)
28 .filter(mp => {
29 if (fromInternal) {
30 // Avoid using modules from outside the app bundle.
31 if (!mp.startsWith(sourceRootDir))
32 return false;
33 }
34 return true;
35 });
36 // Make it possible to do require('chie') when request does not come from
37 // a npm module.
38 if (!fromNodeModule) {
39 // For extensions the exportsDir is preferred, while for inside app
40 // bundle it is used as last resort. This is to make require('gui') use
41 // the actual module inside app bundle, and use the fake one in the
42 // extensions.
43 if (fromInternal)
44 paths.push(exportsDir);
45 else
46 paths.unshift(exportsDir);
47 }
48 return paths;
49 };
50 }
51
52 deserialize(data: ExtensionManagerData) {
53 this.activateBuiltinExtensions();
54 for (const name in data)
55 this.registerExternalExtension(data[name].dirPath);
56 }
57
58 serialize() {
59 const data: ExtensionManagerData = {};
60 for (const name in this.#extensions)
61 data[name] = {dirPath: this.#extensions[name].dirPath};
62 return data;
63 }
64
65 // Load builtin extensions.
66 activateBuiltinExtensions() {
67 const extensionsDir = path.join(__dirname, '..', 'extensions');
68 const extensions = fs.readdirSync(extensionsDir);

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected