aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-modmgr.js
blob: 32bb2ccf8c833bd41eaed8b2123c581cb8e2cef3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Extracted from newOS4 index.html — ModuleManagerModule
        class ModuleManagerModule {
            constructor() { this.commands = {}; this.terminal = null; }
            getHelpInfo() {
                return {
                    'modules': 'modules — Open the module manager GUI',
                    'listmods': 'listmods — List all loaded modules with status',
                    'modules-list': 'modules-list [core|ext] — List all available modules from the module index (46 total)',
                    'loadmod': 'loadmod <url> — Load a module from a URL',
                    'removemod': 'removemod <name> — Remove a loaded module by name',
                    'startup-modules': 'startup-modules — Open the startup modules selector',
                    'load-local': 'load-local <path> — Load a module from VFS or URL',
                    'loadlocal': 'loadlocal <path> — Alias for load-local',
                };
            }
            registerCommands() {
                this.commands['modules'] = () => { this.terminal.openModuleManager(); };
                this.commands['loadmod'] = async (args) => {
                    if(!args[0]) return this.terminal.print("Usage: loadmod <url>", 'warning');
                    await this.terminal.moduleManager.loadModuleFromURL(args[0]);
                    this.terminal.renderModuleList();
                };
                this.commands['removemod'] = (args) => {
                    if(!args[0]) return this.terminal.print("Usage: removemod <name>", 'warning');
                    if(this.terminal.moduleManager.unregisterModule(args[0])) {
                        this.terminal.print(`Module '${args[0]}' removed`, 'success');
                    } else {
                        this.terminal.print(`Module not found: ${args[0]}`, 'error');
                    }
                };
                this.commands['listmods'] = () => {
                    const mods = this.terminal.moduleManager.getModuleList();
                    if(mods.length === 0) return this.terminal.print("No modules loaded");
                    mods.forEach(m => {
                        const status = m.loaded ? '✓' : '✗';
                        const badge = m.url ? '' : ' [Built-in]';
                        this.terminal.print(`${status} ${m.name}${badge}`);
                    });
                };
                this.commands['modules-list'] = async (args) => {
                    try {
                        const filter = (args[0] || '').toLowerCase();
                        const resp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || ''));
                        if (!resp.ok) return this.terminal.print('Failed to load module index', 'error');
                        const idx = await resp.json();
                        let mods = Object.values(idx.modules);
                        if (filter === 'core' || filter === 'ext') mods = mods.filter(m => m.type === filter);
                        if (filter === 'infra') mods = mods.filter(m => m.layer === 'infrastructure');
                        const loaded = this.terminal.moduleManager.modules || {};
                        const loadedCount = Object.keys(loaded).length;
                        const byLayer = {};
                        mods.forEach(m => {
                            const l = m.layer || m.type || 'other';
                            if (!byLayer[l]) byLayer[l] = [];
                            byLayer[l].push(m);
                        });
                        const layerSummary = Object.entries(byLayer).map(([l, ms]) => `${ms.length} ${l}`).join(', ');
                        this.terminal.print(`📦 Module Index (${mods.length} modules: ${layerSummary} — ${loadedCount} loaded)`, 'header');
                        for (const [layer, layerMods] of Object.entries(byLayer)) {
                            this.terminal.print(`  ── ${layer.toUpperCase()} (${layerMods.length}) ──`, 'info');
                            for (const m of layerMods) {
                                const isLoaded = loaded[m.class] ? '✓' : ' ';
                                const layerTag = m.layer === 'infrastructure' ? '[infra]' : m.type === 'core' ? '[core]' : '[ext]';
                                const cmdHint = m.commands.length > 0 ? ` ${m.commands.slice(0, 4).join(', ')}${m.commands.length > 4 ? '...' : ''}` : '';
                                const desc = m.description ? ` — ${m.description.substring(0, 60)}` : '';
                                this.terminal.print(`  ${isLoaded} ${layerTag} ${m.name}${cmdHint}${desc}`, '');
                            }
                        }
                    } catch (e) {
                        this.terminal.print(`modules-list error: ${e.message}`, 'error');
                    }
                };
            }
        }