@reidelsaltres/pureper 0.2.29 → 0.2.30

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.
@@ -4,6 +4,7 @@ export type ModuleStruct = {
4
4
  description?: string;
5
5
  icon?: string;
6
6
  core?: boolean;
7
+ enabled?: boolean;
7
8
  };
8
9
  export default class Module {
9
10
  readonly name: string;
@@ -11,6 +12,7 @@ export default class Module {
11
12
  readonly icon?: string;
12
13
  readonly core: boolean;
13
14
  readonly enabled: Observable<boolean>;
15
+ readonly downloaded: Observable<boolean>;
14
16
  private _registrations;
15
17
  constructor(struct: ModuleStruct);
16
18
  addRegistration(fn: () => Promise<void>): void;
@@ -26,10 +28,15 @@ export default class Module {
26
28
  enable(): void;
27
29
  disable(): void;
28
30
  isActive(): boolean;
31
+ /** True if enabled but not downloaded — works only in the current session. */
32
+ get ephemeral(): boolean;
33
+ download(): void;
34
+ undownload(): void;
29
35
  }
30
36
  export declare class ModuleManager {
31
37
  private static _modules;
32
38
  private static readonly STORAGE_KEY;
39
+ private static readonly SESSION_KEY;
33
40
  static register(struct: ModuleStruct): Module;
34
41
  static get(name: string): Module | undefined;
35
42
  static getAll(): Module[];
@@ -1 +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"}
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;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,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;IAC7C,SAAgB,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAEhD,OAAO,CAAC,cAAc,CAA+B;gBAElC,MAAM,EAAE,YAAY;IAShC,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;IAI1B,8EAA8E;IAC9E,IAAW,SAAS,IAAI,OAAO,CAE9B;IAEM,QAAQ,IAAI,IAAI;IAKhB,UAAU,IAAI,IAAI;CAO5B;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAoB;IACvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA4B;IAE/D,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;IAuB3B,MAAM,CAAC,YAAY,IAAI,IAAI;CAsC9B"}
@@ -6,13 +6,15 @@ export default class Module {
6
6
  icon;
7
7
  core;
8
8
  enabled;
9
+ downloaded;
9
10
  _registrations = [];
10
11
  constructor(struct) {
11
12
  this.name = struct.name;
12
13
  this.description = struct.description;
13
14
  this.icon = struct.icon;
14
15
  this.core = struct.core ?? false;
15
- this.enabled = new Observable(this.core ? true : true);
16
+ this.enabled = new Observable(this.core ? true : (struct.enabled ?? false));
17
+ this.downloaded = new Observable(this.core ? true : false);
16
18
  }
17
19
  addRegistration(fn) {
18
20
  this._registrations.push(fn);
@@ -50,10 +52,26 @@ export default class Module {
50
52
  isActive() {
51
53
  return this.enabled.getObject() === true;
52
54
  }
55
+ /** True if enabled but not downloaded — works only in the current session. */
56
+ get ephemeral() {
57
+ return this.isActive() && !this.downloaded.getObject();
58
+ }
59
+ download() {
60
+ this.downloaded.setObject(true);
61
+ console.log(`[Module]: "${this.name}" downloaded`);
62
+ }
63
+ undownload() {
64
+ if (this.core) {
65
+ throw new Error(`[Module]: Cannot remove core module "${this.name}" from downloads`);
66
+ }
67
+ this.downloaded.setObject(false);
68
+ console.log(`[Module]: "${this.name}" removed from downloads`);
69
+ }
53
70
  }
54
71
  export class ModuleManager {
55
72
  static _modules = new Map();
56
73
  static STORAGE_KEY = "purper:modules";
74
+ static SESSION_KEY = "purper:modules:session";
57
75
  static register(struct) {
58
76
  if (this._modules.has(struct.name)) {
59
77
  throw new Error(`[Module]: Module "${struct.name}" is already registered`);
@@ -105,14 +123,21 @@ export class ModuleManager {
105
123
  return promises;
106
124
  }
107
125
  static persistState() {
108
- const state = {};
126
+ const localState = {};
127
+ const sessionState = {};
109
128
  for (const mod of this._modules.values()) {
110
- if (!mod.core) {
111
- state[mod.name] = mod.isActive();
129
+ if (mod.core)
130
+ continue;
131
+ if (mod.downloaded.getObject()) {
132
+ localState[mod.name] = { enabled: mod.isActive(), downloaded: true };
133
+ }
134
+ else if (mod.isActive()) {
135
+ sessionState[mod.name] = { enabled: true };
112
136
  }
113
137
  }
114
138
  try {
115
- localStorage.setItem(this.STORAGE_KEY, JSON.stringify(state));
139
+ localStorage.setItem(this.STORAGE_KEY, JSON.stringify(localState));
140
+ sessionStorage.setItem(this.SESSION_KEY, JSON.stringify(sessionState));
116
141
  console.log(`[Module]: Persisted module state`);
117
142
  }
118
143
  catch (e) {
@@ -120,21 +145,42 @@ export class ModuleManager {
120
145
  }
121
146
  }
122
147
  static restoreState() {
148
+ // Restore from localStorage (downloaded modules)
123
149
  try {
124
150
  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"}`);
151
+ if (raw) {
152
+ const state = JSON.parse(raw);
153
+ for (const [name, data] of Object.entries(state)) {
154
+ const mod = this._modules.get(name);
155
+ if (mod && !mod.core) {
156
+ if (data.downloaded) {
157
+ mod.downloaded.setObject(true);
158
+ }
159
+ mod.enabled.setObject(data.enabled);
160
+ console.log(`[Module]: Restored "${name}" → downloaded=${data.downloaded}, enabled=${data.enabled}`);
161
+ }
162
+ }
163
+ }
164
+ }
165
+ catch (e) {
166
+ console.warn(`[Module]: Failed to restore localStorage state`, e);
167
+ }
168
+ // Restore from sessionStorage (ephemeral modules)
169
+ try {
170
+ const raw = sessionStorage.getItem(this.SESSION_KEY);
171
+ if (raw) {
172
+ const state = JSON.parse(raw);
173
+ for (const [name, data] of Object.entries(state)) {
174
+ const mod = this._modules.get(name);
175
+ if (mod && !mod.core && !mod.downloaded.getObject()) {
176
+ mod.enabled.setObject(data.enabled);
177
+ console.log(`[Module]: Restored ephemeral "${name}" → enabled=${data.enabled}`);
178
+ }
133
179
  }
134
180
  }
135
181
  }
136
182
  catch (e) {
137
- console.warn(`[Module]: Failed to restore module state`, e);
183
+ console.warn(`[Module]: Failed to restore sessionStorage state`, e);
138
184
  }
139
185
  }
140
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Module.js","sourceRoot":"","sources":["../../src/foundation/Module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Module.js","sourceRoot":"","sources":["../../src/foundation/Module.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAUxC,MAAM,CAAC,OAAO,OAAO,MAAM;IACP,IAAI,CAAS;IACb,WAAW,CAAU;IACrB,IAAI,CAAU;IACd,IAAI,CAAU;IACd,OAAO,CAAsB;IAC7B,UAAU,CAAsB;IAExC,cAAc,GAA4B,EAAE,CAAC;IAErD,YAAmB,MAAoB;QACnC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAU,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC;QACrF,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAU,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;IAEM,eAAe,CAAC,EAAuB;QAC1C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAEM,gBAAgB;QACnB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC/B,CAAC;IAED;;;;;;OAMG;IACI,oBAAoB,CAAC,QAAiC;QACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,cAAc,QAAQ,CAAC,MAAM,kBAAkB,CAAC,CAAC;IACxF,CAAC;IAEM,MAAM;QACT,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI;YAAE,OAAO;QAC9C,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,WAAW,CAAC,CAAC;IACpD,CAAC;IAEM,OAAO;QACV,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yCAAyC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,KAAK;YAAE,OAAO;QAC/C,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,YAAY,CAAC,CAAC;IACrD,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,CAAC;IAC7C,CAAC;IAED,8EAA8E;IAC9E,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;IAC3D,CAAC;IAEM,QAAQ;QACX,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC;IACvD,CAAC;IAEM,UAAU;QACb,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,0BAA0B,CAAC,CAAC;IACnE,CAAC;CACJ;AAED,MAAM,OAAO,aAAa;IACd,MAAM,CAAC,QAAQ,GAAwB,IAAI,GAAG,EAAE,CAAC;IACjD,MAAM,CAAU,WAAW,GAAG,gBAAgB,CAAC;IAC/C,MAAM,CAAU,WAAW,GAAG,wBAAwB,CAAC;IAE/D,MAAM,CAAC,QAAQ,CAAC,MAAoB;QAChC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,IAAI,yBAAyB,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QAC5D,OAAO,GAAG,CAAC;IACf,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,CAAC,MAAM;QACT,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,IAAY;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACxC,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,UAAU;QACb,IAAI,CAAC,YAAY,EAAE,CAAC;QAEpB,MAAM,QAAQ,GAAoB,EAAE,CAAC;QAErC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,MAAM,mBAAmB,CAAC,CAAC;gBAC9G,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,gBAAgB,EAAE,EAAE,CAAC;oBACvC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBACzB,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,GAAG,CAAC,uCAAuC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YACpE,CAAC;QACL,CAAC;QAED,6DAA6D;QAC7D,uCAAuC;QACvC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,qBAAqB,QAAQ,CAAC,MAAM,oCAAoC,CAAC,CAAC;YACtF,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACzB,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,YAAY;QACf,MAAM,UAAU,GAA8D,EAAE,CAAC;QACjF,MAAM,YAAY,GAAyC,EAAE,CAAC;QAE9D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,GAAG,CAAC,IAAI;gBAAE,SAAS;YAEvB,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC7B,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;YACzE,CAAC;iBAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACxB,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/C,CAAC;QACL,CAAC;QAED,IAAI,CAAC;YACD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;YACnE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,0CAA0C,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC;IACL,CAAC;IAED,MAAM,CAAC,YAAY;QACf,iDAAiD;QACjD,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACnD,IAAI,GAAG,EAAE,CAAC;gBACN,MAAM,KAAK,GAA8D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACzF,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACpC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;wBACnB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;4BAClB,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;wBACnC,CAAC;wBACD,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACpC,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,kBAAkB,IAAI,CAAC,UAAU,aAAa,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;oBACzG,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,gDAAgD,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,kDAAkD;QAClD,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,GAAG,EAAE,CAAC;gBACN,MAAM,KAAK,GAAyC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACpE,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACpC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;wBAClD,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACpC,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,eAAe,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;oBACpF,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;IACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reidelsaltres/pureper",
3
- "version": "0.2.29",
3
+ "version": "0.2.30",
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",
@@ -6,6 +6,7 @@ export type ModuleStruct = {
6
6
  description?: string;
7
7
  icon?: string;
8
8
  core?: boolean;
9
+ enabled?: boolean;
9
10
  };
10
11
 
11
12
  export default class Module {
@@ -14,6 +15,7 @@ export default class Module {
14
15
  public readonly icon?: string;
15
16
  public readonly core: boolean;
16
17
  public readonly enabled: Observable<boolean>;
18
+ public readonly downloaded: Observable<boolean>;
17
19
 
18
20
  private _registrations: (() => Promise<void>)[] = [];
19
21
 
@@ -22,7 +24,8 @@ export default class Module {
22
24
  this.description = struct.description;
23
25
  this.icon = struct.icon;
24
26
  this.core = struct.core ?? false;
25
- this.enabled = new Observable<boolean>(this.core ? true : true);
27
+ this.enabled = new Observable<boolean>(this.core ? true : (struct.enabled ?? false));
28
+ this.downloaded = new Observable<boolean>(this.core ? true : false);
26
29
  }
27
30
 
28
31
  public addRegistration(fn: () => Promise<void>): void {
@@ -64,11 +67,30 @@ export default class Module {
64
67
  public isActive(): boolean {
65
68
  return this.enabled.getObject() === true;
66
69
  }
70
+
71
+ /** True if enabled but not downloaded — works only in the current session. */
72
+ public get ephemeral(): boolean {
73
+ return this.isActive() && !this.downloaded.getObject();
74
+ }
75
+
76
+ public download(): void {
77
+ this.downloaded.setObject(true);
78
+ console.log(`[Module]: "${this.name}" downloaded`);
79
+ }
80
+
81
+ public undownload(): void {
82
+ if (this.core) {
83
+ throw new Error(`[Module]: Cannot remove core module "${this.name}" from downloads`);
84
+ }
85
+ this.downloaded.setObject(false);
86
+ console.log(`[Module]: "${this.name}" removed from downloads`);
87
+ }
67
88
  }
68
89
 
69
90
  export class ModuleManager {
70
91
  private static _modules: Map<string, Module> = new Map();
71
92
  private static readonly STORAGE_KEY = "purper:modules";
93
+ private static readonly SESSION_KEY = "purper:modules:session";
72
94
 
73
95
  static register(struct: ModuleStruct): Module {
74
96
  if (this._modules.has(struct.name)) {
@@ -129,14 +151,22 @@ export class ModuleManager {
129
151
  }
130
152
 
131
153
  static persistState(): void {
132
- const state: Record<string, boolean> = {};
154
+ const localState: Record<string, { enabled: boolean, downloaded: boolean }> = {};
155
+ const sessionState: Record<string, { enabled: boolean }> = {};
156
+
133
157
  for (const mod of this._modules.values()) {
134
- if (!mod.core) {
135
- state[mod.name] = mod.isActive();
158
+ if (mod.core) continue;
159
+
160
+ if (mod.downloaded.getObject()) {
161
+ localState[mod.name] = { enabled: mod.isActive(), downloaded: true };
162
+ } else if (mod.isActive()) {
163
+ sessionState[mod.name] = { enabled: true };
136
164
  }
137
165
  }
166
+
138
167
  try {
139
- localStorage.setItem(this.STORAGE_KEY, JSON.stringify(state));
168
+ localStorage.setItem(this.STORAGE_KEY, JSON.stringify(localState));
169
+ sessionStorage.setItem(this.SESSION_KEY, JSON.stringify(sessionState));
140
170
  console.log(`[Module]: Persisted module state`);
141
171
  } catch (e) {
142
172
  console.warn(`[Module]: Failed to persist module state`, e);
@@ -144,20 +174,41 @@ export class ModuleManager {
144
174
  }
145
175
 
146
176
  static restoreState(): void {
177
+ // Restore from localStorage (downloaded modules)
147
178
  try {
148
179
  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"}`);
180
+ if (raw) {
181
+ const state: Record<string, { enabled: boolean, downloaded: boolean }> = JSON.parse(raw);
182
+ for (const [name, data] of Object.entries(state)) {
183
+ const mod = this._modules.get(name);
184
+ if (mod && !mod.core) {
185
+ if (data.downloaded) {
186
+ mod.downloaded.setObject(true);
187
+ }
188
+ mod.enabled.setObject(data.enabled);
189
+ console.log(`[Module]: Restored "${name}" → downloaded=${data.downloaded}, enabled=${data.enabled}`);
190
+ }
191
+ }
192
+ }
193
+ } catch (e) {
194
+ console.warn(`[Module]: Failed to restore localStorage state`, e);
195
+ }
196
+
197
+ // Restore from sessionStorage (ephemeral modules)
198
+ try {
199
+ const raw = sessionStorage.getItem(this.SESSION_KEY);
200
+ if (raw) {
201
+ const state: Record<string, { enabled: boolean }> = JSON.parse(raw);
202
+ for (const [name, data] of Object.entries(state)) {
203
+ const mod = this._modules.get(name);
204
+ if (mod && !mod.core && !mod.downloaded.getObject()) {
205
+ mod.enabled.setObject(data.enabled);
206
+ console.log(`[Module]: Restored ephemeral "${name}" → enabled=${data.enabled}`);
207
+ }
157
208
  }
158
209
  }
159
210
  } catch (e) {
160
- console.warn(`[Module]: Failed to restore module state`, e);
211
+ console.warn(`[Module]: Failed to restore sessionStorage state`, e);
161
212
  }
162
213
  }
163
214
  }