@reidelsaltres/pureper 0.2.28 → 0.2.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ import Observable from "./api/Observer.js";
2
+ export type ModuleStruct = {
3
+ name: string;
4
+ description?: string;
5
+ icon?: string;
6
+ core?: boolean;
7
+ };
8
+ export default class Module {
9
+ readonly name: string;
10
+ readonly description?: string;
11
+ readonly icon?: string;
12
+ readonly core: boolean;
13
+ readonly enabled: Observable<boolean>;
14
+ private _registrations;
15
+ constructor(struct: ModuleStruct);
16
+ addRegistration(fn: () => Promise<void>): void;
17
+ getRegistrations(): ReadonlyArray<() => Promise<void>>;
18
+ /**
19
+ * Takes current entries from the global REGISTRY, moves them into this
20
+ * module's internal list, and removes them from REGISTRY.
21
+ *
22
+ * Call this in consumer code AFTER importing the module's components so
23
+ * that all their REGISTRY entries have been pushed.
24
+ */
25
+ captureRegistrations(registry: (() => Promise<void>)[]): void;
26
+ enable(): void;
27
+ disable(): void;
28
+ isActive(): boolean;
29
+ }
30
+ export declare class ModuleManager {
31
+ private static _modules;
32
+ private static readonly STORAGE_KEY;
33
+ static register(struct: ModuleStruct): Module;
34
+ static get(name: string): Module | undefined;
35
+ static getAll(): Module[];
36
+ static isActive(name: string): boolean;
37
+ /**
38
+ * Initializes all modules:
39
+ * 1. Restores saved enabled/disabled preferences
40
+ * 2. Runs registrations from all enabled modules
41
+ * 3. Runs any remaining global REGISTRY entries (backward compat)
42
+ * 4. Returns all promises
43
+ */
44
+ static initialize(): Promise<void>[];
45
+ static persistState(): void;
46
+ static restoreState(): void;
47
+ }
48
+ //# sourceMappingURL=Module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Module.d.ts","sourceRoot":"","sources":["../../src/foundation/Module.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAG3C,MAAM,MAAM,YAAY,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,MAAM;IACvB,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrC,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAgB,IAAI,EAAE,OAAO,CAAC;IAC9B,SAAgB,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAE7C,OAAO,CAAC,cAAc,CAA+B;gBAElC,MAAM,EAAE,YAAY;IAQhC,eAAe,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI9C,gBAAgB,IAAI,aAAa,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAI7D;;;;;;OAMG;IACI,oBAAoB,CAAC,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,IAAI;IAM7D,MAAM,IAAI,IAAI;IAMd,OAAO,IAAI,IAAI;IASf,QAAQ,IAAI,OAAO;CAG7B;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAEvD,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM;IAU7C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI5C,MAAM,CAAC,MAAM,IAAI,MAAM,EAAE;IAIzB,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAKtC;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE;IA4BpC,MAAM,CAAC,YAAY,IAAI,IAAI;IAe3B,MAAM,CAAC,YAAY,IAAI,IAAI;CAiB9B"}
@@ -0,0 +1,141 @@
1
+ import Observable from "./api/Observer.js";
2
+ import { REGISTRY } from "./Triplet.js";
3
+ export default class Module {
4
+ name;
5
+ description;
6
+ icon;
7
+ core;
8
+ enabled;
9
+ _registrations = [];
10
+ constructor(struct) {
11
+ this.name = struct.name;
12
+ this.description = struct.description;
13
+ this.icon = struct.icon;
14
+ this.core = struct.core ?? false;
15
+ this.enabled = new Observable(this.core ? true : true);
16
+ }
17
+ addRegistration(fn) {
18
+ this._registrations.push(fn);
19
+ }
20
+ getRegistrations() {
21
+ return this._registrations;
22
+ }
23
+ /**
24
+ * Takes current entries from the global REGISTRY, moves them into this
25
+ * module's internal list, and removes them from REGISTRY.
26
+ *
27
+ * Call this in consumer code AFTER importing the module's components so
28
+ * that all their REGISTRY entries have been pushed.
29
+ */
30
+ captureRegistrations(registry) {
31
+ const captured = registry.splice(0, registry.length);
32
+ this._registrations.push(...captured);
33
+ console.log(`[Module]: "${this.name}" captured ${captured.length} registration(s)`);
34
+ }
35
+ enable() {
36
+ if (this.enabled.getObject() === true)
37
+ return;
38
+ this.enabled.setObject(true);
39
+ console.log(`[Module]: "${this.name}" enabled`);
40
+ }
41
+ disable() {
42
+ if (this.core) {
43
+ throw new Error(`[Module]: Cannot disable core module "${this.name}"`);
44
+ }
45
+ if (this.enabled.getObject() === false)
46
+ return;
47
+ this.enabled.setObject(false);
48
+ console.log(`[Module]: "${this.name}" disabled`);
49
+ }
50
+ isActive() {
51
+ return this.enabled.getObject() === true;
52
+ }
53
+ }
54
+ export class ModuleManager {
55
+ static _modules = new Map();
56
+ static STORAGE_KEY = "purper:modules";
57
+ static register(struct) {
58
+ if (this._modules.has(struct.name)) {
59
+ throw new Error(`[Module]: Module "${struct.name}" is already registered`);
60
+ }
61
+ const mod = new Module(struct);
62
+ this._modules.set(struct.name, mod);
63
+ console.log(`[Module]: Registered module "${struct.name}"`);
64
+ return mod;
65
+ }
66
+ static get(name) {
67
+ return this._modules.get(name);
68
+ }
69
+ static getAll() {
70
+ return Array.from(this._modules.values());
71
+ }
72
+ static isActive(name) {
73
+ const mod = this._modules.get(name);
74
+ return mod ? mod.isActive() : false;
75
+ }
76
+ /**
77
+ * Initializes all modules:
78
+ * 1. Restores saved enabled/disabled preferences
79
+ * 2. Runs registrations from all enabled modules
80
+ * 3. Runs any remaining global REGISTRY entries (backward compat)
81
+ * 4. Returns all promises
82
+ */
83
+ static initialize() {
84
+ this.restoreState();
85
+ const promises = [];
86
+ for (const mod of this._modules.values()) {
87
+ if (mod.isActive()) {
88
+ console.log(`[Module]: Initializing module "${mod.name}" (${mod.getRegistrations().length} registration(s))`);
89
+ for (const reg of mod.getRegistrations()) {
90
+ promises.push(reg());
91
+ }
92
+ }
93
+ else {
94
+ console.log(`[Module]: Skipping disabled module "${mod.name}"`);
95
+ }
96
+ }
97
+ // Backward compat: run any remaining global REGISTRY entries
98
+ // that were not captured by any module
99
+ if (REGISTRY.length > 0) {
100
+ console.log(`[Module]: Running ${REGISTRY.length} uncaptured global registration(s)`);
101
+ for (const reg of REGISTRY) {
102
+ promises.push(reg());
103
+ }
104
+ }
105
+ return promises;
106
+ }
107
+ static persistState() {
108
+ const state = {};
109
+ for (const mod of this._modules.values()) {
110
+ if (!mod.core) {
111
+ state[mod.name] = mod.isActive();
112
+ }
113
+ }
114
+ try {
115
+ localStorage.setItem(this.STORAGE_KEY, JSON.stringify(state));
116
+ console.log(`[Module]: Persisted module state`);
117
+ }
118
+ catch (e) {
119
+ console.warn(`[Module]: Failed to persist module state`, e);
120
+ }
121
+ }
122
+ static restoreState() {
123
+ try {
124
+ const raw = localStorage.getItem(this.STORAGE_KEY);
125
+ if (!raw)
126
+ return;
127
+ const state = JSON.parse(raw);
128
+ for (const [name, enabled] of Object.entries(state)) {
129
+ const mod = this._modules.get(name);
130
+ if (mod && !mod.core) {
131
+ mod.enabled.setObject(enabled);
132
+ console.log(`[Module]: Restored "${name}" → ${enabled ? "enabled" : "disabled"}`);
133
+ }
134
+ }
135
+ }
136
+ catch (e) {
137
+ console.warn(`[Module]: Failed to restore module state`, e);
138
+ }
139
+ }
140
+ }
141
+ //# sourceMappingURL=Module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Module.js","sourceRoot":"","sources":["../../src/foundation/Module.ts"],"names":[],"mappings":"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"}
package/out/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { default as Attribute } from './foundation/component_api/Attribute.js';
10
10
  export { default as Triplet, TripletStruct, AccessType, REGISTRY } from './foundation/Triplet.js';
11
11
  export { ReComponent, RePage, ReImplementation } from './foundation/TripletDecorator.js';
12
12
  export { Implementation, ImplementationStruct, Placeholder } from './foundation/Injection.js';
13
+ export { default as Module, ModuleStruct, ModuleManager } from './foundation/Module.js';
13
14
  export { default as Fetcher } from './foundation/Fetcher.js';
14
15
  export * from './foundation/engine/TemplateEngine.js';
15
16
  export { Router } from './foundation/worker/Router.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EACrB,SAAS,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAErK,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EACrB,SAAS,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAErK,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
package/out/index.js CHANGED
@@ -8,6 +8,7 @@ export { default as Attribute } from './foundation/component_api/Attribute.js';
8
8
  export { default as Triplet, AccessType, REGISTRY } from './foundation/Triplet.js';
9
9
  export { ReComponent, RePage, ReImplementation } from './foundation/TripletDecorator.js';
10
10
  export { Implementation, Placeholder } from './foundation/Injection.js';
11
+ export { default as Module, ModuleManager } from './foundation/Module.js';
11
12
  export { default as Fetcher } from './foundation/Fetcher.js';
12
13
  export * from './foundation/engine/TemplateEngine.js';
13
14
  export { Router } from './foundation/worker/Router.js';
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EAC+B,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAiB,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAwB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAuF,MAAM,sCAAsC,CAAC;AAErK,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AAGtC,qEAAqE;AACrE;;WAEQ;AAER,yEAAyE"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EAC+B,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAiB,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAwB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,MAAM,EAAgB,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAuF,MAAM,sCAAsC,CAAC;AAErK,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AAGtC,qEAAqE;AACrE;;WAEQ;AAER,yEAAyE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reidelsaltres/pureper",
3
- "version": "0.2.28",
3
+ "version": "0.2.29",
4
4
  "description": "Minimal library extracted from the Pureper SPA foundation — utilities and base classes for components/pages.",
5
5
  "type": "module",
6
6
  "main": "out/src/index.js",
@@ -0,0 +1,163 @@
1
+ import Observable from "./api/Observer.js";
2
+ import { REGISTRY } from "./Triplet.js";
3
+
4
+ export type ModuleStruct = {
5
+ name: string;
6
+ description?: string;
7
+ icon?: string;
8
+ core?: boolean;
9
+ };
10
+
11
+ export default class Module {
12
+ public readonly name: string;
13
+ public readonly description?: string;
14
+ public readonly icon?: string;
15
+ public readonly core: boolean;
16
+ public readonly enabled: Observable<boolean>;
17
+
18
+ private _registrations: (() => Promise<void>)[] = [];
19
+
20
+ public constructor(struct: ModuleStruct) {
21
+ this.name = struct.name;
22
+ this.description = struct.description;
23
+ this.icon = struct.icon;
24
+ this.core = struct.core ?? false;
25
+ this.enabled = new Observable<boolean>(this.core ? true : true);
26
+ }
27
+
28
+ public addRegistration(fn: () => Promise<void>): void {
29
+ this._registrations.push(fn);
30
+ }
31
+
32
+ public getRegistrations(): ReadonlyArray<() => Promise<void>> {
33
+ return this._registrations;
34
+ }
35
+
36
+ /**
37
+ * Takes current entries from the global REGISTRY, moves them into this
38
+ * module's internal list, and removes them from REGISTRY.
39
+ *
40
+ * Call this in consumer code AFTER importing the module's components so
41
+ * that all their REGISTRY entries have been pushed.
42
+ */
43
+ public captureRegistrations(registry: (() => Promise<void>)[]): void {
44
+ const captured = registry.splice(0, registry.length);
45
+ this._registrations.push(...captured);
46
+ console.log(`[Module]: "${this.name}" captured ${captured.length} registration(s)`);
47
+ }
48
+
49
+ public enable(): void {
50
+ if (this.enabled.getObject() === true) return;
51
+ this.enabled.setObject(true);
52
+ console.log(`[Module]: "${this.name}" enabled`);
53
+ }
54
+
55
+ public disable(): void {
56
+ if (this.core) {
57
+ throw new Error(`[Module]: Cannot disable core module "${this.name}"`);
58
+ }
59
+ if (this.enabled.getObject() === false) return;
60
+ this.enabled.setObject(false);
61
+ console.log(`[Module]: "${this.name}" disabled`);
62
+ }
63
+
64
+ public isActive(): boolean {
65
+ return this.enabled.getObject() === true;
66
+ }
67
+ }
68
+
69
+ export class ModuleManager {
70
+ private static _modules: Map<string, Module> = new Map();
71
+ private static readonly STORAGE_KEY = "purper:modules";
72
+
73
+ static register(struct: ModuleStruct): Module {
74
+ if (this._modules.has(struct.name)) {
75
+ throw new Error(`[Module]: Module "${struct.name}" is already registered`);
76
+ }
77
+ const mod = new Module(struct);
78
+ this._modules.set(struct.name, mod);
79
+ console.log(`[Module]: Registered module "${struct.name}"`);
80
+ return mod;
81
+ }
82
+
83
+ static get(name: string): Module | undefined {
84
+ return this._modules.get(name);
85
+ }
86
+
87
+ static getAll(): Module[] {
88
+ return Array.from(this._modules.values());
89
+ }
90
+
91
+ static isActive(name: string): boolean {
92
+ const mod = this._modules.get(name);
93
+ return mod ? mod.isActive() : false;
94
+ }
95
+
96
+ /**
97
+ * Initializes all modules:
98
+ * 1. Restores saved enabled/disabled preferences
99
+ * 2. Runs registrations from all enabled modules
100
+ * 3. Runs any remaining global REGISTRY entries (backward compat)
101
+ * 4. Returns all promises
102
+ */
103
+ static initialize(): Promise<void>[] {
104
+ this.restoreState();
105
+
106
+ const promises: Promise<void>[] = [];
107
+
108
+ for (const mod of this._modules.values()) {
109
+ if (mod.isActive()) {
110
+ console.log(`[Module]: Initializing module "${mod.name}" (${mod.getRegistrations().length} registration(s))`);
111
+ for (const reg of mod.getRegistrations()) {
112
+ promises.push(reg());
113
+ }
114
+ } else {
115
+ console.log(`[Module]: Skipping disabled module "${mod.name}"`);
116
+ }
117
+ }
118
+
119
+ // Backward compat: run any remaining global REGISTRY entries
120
+ // that were not captured by any module
121
+ if (REGISTRY.length > 0) {
122
+ console.log(`[Module]: Running ${REGISTRY.length} uncaptured global registration(s)`);
123
+ for (const reg of REGISTRY) {
124
+ promises.push(reg());
125
+ }
126
+ }
127
+
128
+ return promises;
129
+ }
130
+
131
+ static persistState(): void {
132
+ const state: Record<string, boolean> = {};
133
+ for (const mod of this._modules.values()) {
134
+ if (!mod.core) {
135
+ state[mod.name] = mod.isActive();
136
+ }
137
+ }
138
+ try {
139
+ localStorage.setItem(this.STORAGE_KEY, JSON.stringify(state));
140
+ console.log(`[Module]: Persisted module state`);
141
+ } catch (e) {
142
+ console.warn(`[Module]: Failed to persist module state`, e);
143
+ }
144
+ }
145
+
146
+ static restoreState(): void {
147
+ try {
148
+ const raw = localStorage.getItem(this.STORAGE_KEY);
149
+ if (!raw) return;
150
+
151
+ const state: Record<string, boolean> = JSON.parse(raw);
152
+ for (const [name, enabled] of Object.entries(state)) {
153
+ const mod = this._modules.get(name);
154
+ if (mod && !mod.core) {
155
+ mod.enabled.setObject(enabled);
156
+ console.log(`[Module]: Restored "${name}" → ${enabled ? "enabled" : "disabled"}`);
157
+ }
158
+ }
159
+ } catch (e) {
160
+ console.warn(`[Module]: Failed to restore module state`, e);
161
+ }
162
+ }
163
+ }
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ export { default as Triplet, TripletStruct, AccessType, REGISTRY } from './found
19
19
  export { ReComponent, RePage, ReImplementation } from './foundation/TripletDecorator.js';
20
20
 
21
21
  export { Implementation, ImplementationStruct, Placeholder } from './foundation/Injection.js';
22
+ export { default as Module, ModuleStruct, ModuleManager } from './foundation/Module.js';
22
23
  export { default as Fetcher } from './foundation/Fetcher.js';
23
24
 
24
25
  export * from './foundation/engine/TemplateEngine.js';