@zolomedia/bifrost-client 1.7.74

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.
Files changed (140) hide show
  1. package/L1_Foundation/L1_Foundation.js +13 -0
  2. package/L1_Foundation/bootstrap/bootstrap.js +11 -0
  3. package/L1_Foundation/bootstrap/bootstrap_hooks.js +123 -0
  4. package/L1_Foundation/bootstrap/bootstrap_index.js +15 -0
  5. package/L1_Foundation/bootstrap/bootstrap_logger.js +135 -0
  6. package/L1_Foundation/bootstrap/cdn_loader.js +217 -0
  7. package/L1_Foundation/bootstrap/module_registry.js +102 -0
  8. package/L1_Foundation/bootstrap/prism_loader.js +164 -0
  9. package/L1_Foundation/config/client_config.js +110 -0
  10. package/L1_Foundation/config/config.js +7 -0
  11. package/L1_Foundation/connection/connection.js +8 -0
  12. package/L1_Foundation/connection/websocket_connection.js +122 -0
  13. package/L1_Foundation/constants/bifrost_constants.js +284 -0
  14. package/L1_Foundation/constants/constants.js +7 -0
  15. package/L1_Foundation/logger/logger.js +10 -0
  16. package/L2_Handling/L2_Handling.js +15 -0
  17. package/L2_Handling/cache/cache.js +22 -0
  18. package/L2_Handling/cache/cache_constants.js +69 -0
  19. package/L2_Handling/cache/orchestration/cache_manager.js +299 -0
  20. package/L2_Handling/cache/orchestration/cache_orchestrator.js +260 -0
  21. package/L2_Handling/cache/orchestration/orchestration.js +12 -0
  22. package/L2_Handling/cache/storage/session_manager.js +289 -0
  23. package/L2_Handling/cache/storage/storage.js +10 -0
  24. package/L2_Handling/cache/storage/storage_manager.js +590 -0
  25. package/L2_Handling/display/composite/composite.js +13 -0
  26. package/L2_Handling/display/composite/dashboard_renderer.js +221 -0
  27. package/L2_Handling/display/composite/swiper_renderer.js +564 -0
  28. package/L2_Handling/display/composite/terminal_renderer.js +922 -0
  29. package/L2_Handling/display/composite/wizard_conditional_renderer.js +274 -0
  30. package/L2_Handling/display/display.js +30 -0
  31. package/L2_Handling/display/feedback/feedback.js +11 -0
  32. package/L2_Handling/display/feedback/progressbar_renderer.js +418 -0
  33. package/L2_Handling/display/feedback/spinner_renderer.js +246 -0
  34. package/L2_Handling/display/inputs/button_renderer.js +634 -0
  35. package/L2_Handling/display/inputs/form_renderer.js +583 -0
  36. package/L2_Handling/display/inputs/input_renderer.js +658 -0
  37. package/L2_Handling/display/inputs/inputs.js +12 -0
  38. package/L2_Handling/display/navigation/menu_renderer.js +206 -0
  39. package/L2_Handling/display/navigation/navigation.js +11 -0
  40. package/L2_Handling/display/navigation/navigation_renderer.js +703 -0
  41. package/L2_Handling/display/orchestration/orchestration.js +11 -0
  42. package/L2_Handling/display/orchestration/renderer.js +430 -0
  43. package/L2_Handling/display/orchestration/zdisplay_orchestrator.js +1759 -0
  44. package/L2_Handling/display/outputs/alert_renderer.js +161 -0
  45. package/L2_Handling/display/outputs/audio_renderer.js +94 -0
  46. package/L2_Handling/display/outputs/card_renderer.js +229 -0
  47. package/L2_Handling/display/outputs/code_renderer.js +66 -0
  48. package/L2_Handling/display/outputs/dl_renderer.js +131 -0
  49. package/L2_Handling/display/outputs/header_renderer.js +162 -0
  50. package/L2_Handling/display/outputs/icon_renderer.js +107 -0
  51. package/L2_Handling/display/outputs/image_renderer.js +145 -0
  52. package/L2_Handling/display/outputs/list_renderer.js +190 -0
  53. package/L2_Handling/display/outputs/outputs.js +19 -0
  54. package/L2_Handling/display/outputs/table_renderer.js +765 -0
  55. package/L2_Handling/display/outputs/text_renderer.js +818 -0
  56. package/L2_Handling/display/outputs/typography_renderer.js +293 -0
  57. package/L2_Handling/display/outputs/video_renderer.js +116 -0
  58. package/L2_Handling/display/primitives/document_structure_primitives.js +319 -0
  59. package/L2_Handling/display/primitives/form_primitives.js +526 -0
  60. package/L2_Handling/display/primitives/generic_containers.js +109 -0
  61. package/L2_Handling/display/primitives/interactive_primitives.js +305 -0
  62. package/L2_Handling/display/primitives/link_primitives.js +552 -0
  63. package/L2_Handling/display/primitives/lists_primitives.js +262 -0
  64. package/L2_Handling/display/primitives/media_primitives.js +383 -0
  65. package/L2_Handling/display/primitives/primitives.js +19 -0
  66. package/L2_Handling/display/primitives/semantic_element_primitive.js +226 -0
  67. package/L2_Handling/display/primitives/table_primitives.js +528 -0
  68. package/L2_Handling/display/primitives/typography_primitives.js +175 -0
  69. package/L2_Handling/display/specialized/input_request_renderer.js +467 -0
  70. package/L2_Handling/display/specialized/specialized.js +10 -0
  71. package/L2_Handling/hooks/hooks.js +9 -0
  72. package/L2_Handling/hooks/menu_integration.js +57 -0
  73. package/L2_Handling/hooks/widget_hook_manager.js +292 -0
  74. package/L2_Handling/message/message.js +8 -0
  75. package/L2_Handling/message/message_handler.js +701 -0
  76. package/L2_Handling/navigation/navigation.js +8 -0
  77. package/L2_Handling/navigation/navigation_manager.js +403 -0
  78. package/L2_Handling/zhooks/features/cache_live.js +287 -0
  79. package/L2_Handling/zhooks/features/crumbs_live.js +292 -0
  80. package/L2_Handling/zhooks/zhooks_manager.js +65 -0
  81. package/L2_Handling/zvaf/zvaf.js +8 -0
  82. package/L2_Handling/zvaf/zvaf_manager.js +334 -0
  83. package/L3_Abstraction/L3_Abstraction.js +12 -0
  84. package/L3_Abstraction/orchestrator/container_unwrapper.js +101 -0
  85. package/L3_Abstraction/orchestrator/group_renderer.js +698 -0
  86. package/L3_Abstraction/orchestrator/input_event_handler.js +797 -0
  87. package/L3_Abstraction/orchestrator/metadata_processor.js +249 -0
  88. package/L3_Abstraction/orchestrator/navbar_builder.js +201 -0
  89. package/L3_Abstraction/orchestrator/orchestrator.js +13 -0
  90. package/L3_Abstraction/orchestrator/wizard_gate_handler.js +360 -0
  91. package/L3_Abstraction/renderer/renderer.js +1 -0
  92. package/L3_Abstraction/session/session.js +1 -0
  93. package/L4_Orchestration/L4_Orchestration.js +11 -0
  94. package/L4_Orchestration/client/client.js +1 -0
  95. package/L4_Orchestration/facade/facade.js +9 -0
  96. package/L4_Orchestration/facade/manager_registry.js +118 -0
  97. package/L4_Orchestration/facade/renderer_registry.js +274 -0
  98. package/L4_Orchestration/lifecycle/asset_loader.js +255 -0
  99. package/L4_Orchestration/lifecycle/initializer.js +135 -0
  100. package/L4_Orchestration/lifecycle/lifecycle.js +8 -0
  101. package/L4_Orchestration/rendering/facade.js +94 -0
  102. package/L4_Orchestration/rendering/rendering.js +7 -0
  103. package/LICENSE +21 -0
  104. package/README.md +82 -0
  105. package/bifrost_client.js +204 -0
  106. package/bifrost_core.js +1686 -0
  107. package/docs/ARCHITECTURE.md +111 -0
  108. package/docs/PROTOCOL.md +106 -0
  109. package/docs/RENDERERS.md +101 -0
  110. package/docs/SECURITY.md +92 -0
  111. package/package.json +24 -0
  112. package/syntax/prism-zconfig.js +41 -0
  113. package/syntax/prism-zenv.js +69 -0
  114. package/syntax/prism-zolo-theme.css +288 -0
  115. package/syntax/prism-zolo.js +380 -0
  116. package/syntax/prism-zschema.js +38 -0
  117. package/syntax/prism-zspark.js +25 -0
  118. package/syntax/prism-zui.js +68 -0
  119. package/zSys/accessibility/accessibility.js +10 -0
  120. package/zSys/accessibility/emoji_accessibility.js +173 -0
  121. package/zSys/dom/block_utils.js +122 -0
  122. package/zSys/dom/container_utils.js +370 -0
  123. package/zSys/dom/dom.js +13 -0
  124. package/zSys/dom/dom_utils.js +328 -0
  125. package/zSys/dom/encoding_utils.js +117 -0
  126. package/zSys/dom/style_utils.js +71 -0
  127. package/zSys/errors/error_display.js +299 -0
  128. package/zSys/errors/errors.js +10 -0
  129. package/zSys/theme/color_utils.js +274 -0
  130. package/zSys/theme/dark_mode_utils.js +272 -0
  131. package/zSys/theme/size_utils.js +256 -0
  132. package/zSys/theme/spacing_utils.js +405 -0
  133. package/zSys/theme/theme.js +14 -0
  134. package/zSys/theme/zbase.css +1735 -0
  135. package/zSys/theme/zbase_inject.js +161 -0
  136. package/zSys/theme/ztheme_utils.js +305 -0
  137. package/zSys/validation/error_boundary.js +201 -0
  138. package/zSys/validation/validation.js +11 -0
  139. package/zSys/validation/validation_utils.js +238 -0
  140. package/zSys/zSys.js +14 -0
@@ -0,0 +1,590 @@
1
+ /**
2
+ *
3
+ * zCLI - StorageManager (Layer 0 Primitive)
4
+ *
5
+ *
6
+ * Unified storage interface with progressive enhancement:
7
+ * - Primary: IndexedDB (~50MB, async, modern browsers)
8
+ * - Fallback: localStorage (~5-10MB, sync, universal)
9
+ *
10
+ * Mirrors zLoader's backend cache architecture for consistency.
11
+ *
12
+ * Usage:
13
+ * const storage = new StorageManager('zBifrost');
14
+ * await storage.init();
15
+ * await storage.set('key', {data: 'value'}, 'system');
16
+ * const data = await storage.get('key', 'system');
17
+ *
18
+ * Architecture:
19
+ * - Single unified interface (get/set/clear/remove)
20
+ * - Automatic fallback (IndexedDB → localStorage)
21
+ * - Namespace isolation (prevents key collisions)
22
+ * - Type-safe (validates JSON serialization)
23
+ *
24
+ * @version 1.6.0
25
+ * @since 2025-12-16
26
+ *
27
+ */
28
+
29
+ (function(root, factory) {
30
+ if (typeof define === 'function' && define.amd) {
31
+ define([], factory);
32
+ } else if (typeof module === 'object' && module.exports) {
33
+ module.exports = factory();
34
+ } else {
35
+ root.StorageManager = factory();
36
+ }
37
+ }(typeof self !== 'undefined' ? self : this, () => {
38
+ 'use strict';
39
+
40
+ //
41
+ // Constants (imported from cache_constants for SSOT)
42
+ //
43
+ // Note: These are duplicated here for UMD module compatibility
44
+ // SSOT is in ../cache_constants.js
45
+ //
46
+
47
+ const DB_VERSION = 2; // SSOT: cache_constants.DB_VERSION (v2 drops legacy tiers)
48
+ const STORE_NAMES = ['rendered']; // SSOT: cache_constants.STORE_NAMES (trail only)
49
+ const LEGACY_STORE_NAMES = ['system', 'pinned', 'plugin']; // dropped in v2
50
+
51
+ //
52
+ // StorageManager Class
53
+ //
54
+
55
+ class StorageManager {
56
+ /**
57
+ * Create a new storage manager instance
58
+ *
59
+ * @param {string} namespace - Namespace for storage isolation (e.g., 'zBifrost')
60
+ * @param {Object} logger - Optional logger instance
61
+ */
62
+ constructor(namespace = 'zBifrost', logger = null) {
63
+ this.namespace = namespace;
64
+ this.dbName = `${namespace}_cache`;
65
+ this.db = null;
66
+ this.useIndexedDB = false;
67
+ this.useLocalStorage = false;
68
+ this.initialized = false;
69
+ this.logger = logger || console;
70
+
71
+ // In-memory session cache (never persisted)
72
+ this.sessionCache = new Map();
73
+
74
+ this.logger.debug(`[StorageManager] Created with namespace: ${namespace}`);
75
+ }
76
+
77
+ /**
78
+ * Initialize storage (must be called before use)
79
+ *
80
+ * Attempts IndexedDB first, falls back to localStorage if unavailable.
81
+ *
82
+ * @returns {Promise<boolean>} Success status
83
+ */
84
+ async init() {
85
+ if (this.initialized) {
86
+ this.logger.debug('[StorageManager] Already initialized');
87
+ return true;
88
+ }
89
+
90
+ // Try IndexedDB first (modern, async, large capacity)
91
+ try {
92
+ await this._initIndexedDB();
93
+ this.useIndexedDB = true;
94
+ this.logger.debug('[StorageManager] Initialized with IndexedDB');
95
+ this.initialized = true;
96
+ return true;
97
+ } catch (error) {
98
+ this.logger.warn('[StorageManager] [WARN] IndexedDB unavailable, falling back to localStorage:', error.message);
99
+ }
100
+
101
+ // Fallback to localStorage (universal, sync, limited capacity)
102
+ try {
103
+ this._initLocalStorage();
104
+ this.useLocalStorage = true;
105
+ this.logger.debug('[StorageManager] Initialized with localStorage (fallback)');
106
+ this.initialized = true;
107
+ return true;
108
+ } catch (error) {
109
+ this.logger.error('[StorageManager] [ERROR] Both IndexedDB and localStorage unavailable:', error);
110
+ this.initialized = false;
111
+ return false;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Initialize IndexedDB
117
+ *
118
+ * Creates object stores for each cache tier (system, pinned, plugin, rendered).
119
+ * Session cache is in-memory only and not persisted.
120
+ *
121
+ * @private
122
+ * @returns {Promise<void>}
123
+ */
124
+ _initIndexedDB() {
125
+ return new Promise((resolve, reject) => {
126
+ if (!window.indexedDB) {
127
+ reject(new Error('IndexedDB not supported'));
128
+ return;
129
+ }
130
+
131
+ const request = indexedDB.open(this.dbName, DB_VERSION);
132
+
133
+ request.onerror = () => {
134
+ reject(new Error(`IndexedDB open failed: ${request.error}`));
135
+ };
136
+
137
+ request.onsuccess = () => {
138
+ this.db = request.result;
139
+ this.logger.info(`[StorageManager] IndexedDB opened: ${this.dbName}`);
140
+ resolve();
141
+ };
142
+
143
+ request.onupgradeneeded = (event) => {
144
+ const db = event.target.result;
145
+
146
+ // Create the trail store (rendered pages)
147
+ STORE_NAMES.forEach(storeName => {
148
+ if (!db.objectStoreNames.contains(storeName)) {
149
+ const store = db.createObjectStore(storeName, { keyPath: 'key' });
150
+ store.createIndex('timestamp', 'timestamp', { unique: false });
151
+ this.logger.info(`[StorageManager] Created object store: ${storeName}`);
152
+ }
153
+ });
154
+
155
+ // v2: drop the legacy mirror-of-zLoader stores — the client no longer
156
+ // caches UI files / configs / plugins (the server is the cache of record).
157
+ LEGACY_STORE_NAMES.forEach(storeName => {
158
+ if (db.objectStoreNames.contains(storeName)) {
159
+ db.deleteObjectStore(storeName);
160
+ this.logger.info(`[StorageManager] Dropped legacy object store: ${storeName}`);
161
+ }
162
+ });
163
+ };
164
+ });
165
+ }
166
+
167
+ /**
168
+ * Initialize localStorage (fallback)
169
+ *
170
+ * Validates localStorage is available and writable.
171
+ *
172
+ * @private
173
+ */
174
+ _initLocalStorage() {
175
+ if (typeof localStorage === 'undefined') {
176
+ throw new Error('localStorage not supported');
177
+ }
178
+
179
+ // Test write/read
180
+ const testKey = `${this.namespace}_test`;
181
+ try {
182
+ localStorage.setItem(testKey, 'test');
183
+ localStorage.removeItem(testKey);
184
+ } catch (error) {
185
+ throw new Error(`localStorage not writable: ${error.message}`);
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Get value from storage
191
+ *
192
+ * @param {string} key - Storage key
193
+ * @param {string} tier - Cache tier ('system', 'pinned', 'plugin', 'session', 'rendered')
194
+ * @returns {Promise<any|null>} Stored value or null if not found
195
+ */
196
+ async get(key, tier = 'system') {
197
+ if (!this.initialized) {
198
+ this.logger.warn('[StorageManager] Not initialized, call init() first');
199
+ return null;
200
+ }
201
+
202
+ // Session cache is in-memory only
203
+ if (tier === 'session') {
204
+ return this.sessionCache.get(key) || null;
205
+ }
206
+
207
+ // Try persistent storage
208
+ if (this.useIndexedDB) {
209
+ return await this._getFromIndexedDB(key, tier);
210
+ } else if (this.useLocalStorage) {
211
+ return this._getFromLocalStorage(key, tier);
212
+ }
213
+
214
+ return null;
215
+ }
216
+
217
+ /**
218
+ * Set value in storage
219
+ *
220
+ * @param {string} key - Storage key
221
+ * @param {any} value - Value to store (must be JSON-serializable)
222
+ * @param {string} tier - Cache tier ('system', 'pinned', 'plugin', 'session', 'rendered')
223
+ * @param {number} ttl - Time-to-live in milliseconds (optional, for cache validation)
224
+ * @returns {Promise<boolean>} Success status
225
+ */
226
+ async set(key, value, tier = 'system', ttl = null) {
227
+ if (!this.initialized) {
228
+ this.logger.warn('[StorageManager] Not initialized, call init() first');
229
+ return false;
230
+ }
231
+
232
+ // Validate JSON serialization
233
+ try {
234
+ JSON.stringify(value);
235
+ } catch (error) {
236
+ this.logger.error('[StorageManager] Value not JSON-serializable:', error);
237
+ return false;
238
+ }
239
+
240
+ // Session cache is in-memory only
241
+ if (tier === 'session') {
242
+ this.sessionCache.set(key, value);
243
+ return true;
244
+ }
245
+
246
+ // Add metadata
247
+ const entry = {
248
+ key: key,
249
+ value: value,
250
+ timestamp: Date.now(),
251
+ ttl: ttl
252
+ };
253
+
254
+ // Store persistently
255
+ if (this.useIndexedDB) {
256
+ return await this._setInIndexedDB(entry, tier);
257
+ } else if (this.useLocalStorage) {
258
+ return this._setInLocalStorage(entry, tier);
259
+ }
260
+
261
+ return false;
262
+ }
263
+
264
+ /**
265
+ * Remove value from storage
266
+ *
267
+ * @param {string} key - Storage key
268
+ * @param {string} tier - Cache tier
269
+ * @returns {Promise<boolean>} Success status
270
+ */
271
+ async remove(key, tier = 'system') {
272
+ if (!this.initialized) {
273
+ this.logger.warn('[StorageManager] Not initialized, call init() first');
274
+ return false;
275
+ }
276
+
277
+ if (tier === 'session') {
278
+ return this.sessionCache.delete(key);
279
+ }
280
+
281
+ if (this.useIndexedDB) {
282
+ return await this._removeFromIndexedDB(key, tier);
283
+ } else if (this.useLocalStorage) {
284
+ return this._removeFromLocalStorage(key, tier);
285
+ }
286
+
287
+ return false;
288
+ }
289
+
290
+ /**
291
+ * Clear entire cache tier
292
+ *
293
+ * @param {string} tier - Cache tier to clear (or 'all' to clear everything)
294
+ * @returns {Promise<boolean>} Success status
295
+ */
296
+ async clear(tier = 'all') {
297
+ if (!this.initialized) {
298
+ this.logger.warn('[StorageManager] Not initialized, call init() first');
299
+ return false;
300
+ }
301
+
302
+ const tiersToClean = tier === 'all' ? ['session', 'rendered'] : [tier];
303
+
304
+ for (const t of tiersToClean) {
305
+ if (t === 'session') {
306
+ this.sessionCache.clear();
307
+ } else if (this.useIndexedDB) {
308
+ await this._clearIndexedDBStore(t);
309
+ } else if (this.useLocalStorage) {
310
+ this._clearLocalStorageTier(t);
311
+ }
312
+ }
313
+
314
+ this.logger.info(`[StorageManager] Cleared tier(s): ${tier}`);
315
+ return true;
316
+ }
317
+
318
+ /**
319
+ * Get all keys in a tier
320
+ *
321
+ * @param {string} tier - Cache tier
322
+ * @returns {Promise<string[]>} Array of keys
323
+ */
324
+ async keys(tier = 'system') {
325
+ if (!this.initialized) {
326
+ return [];
327
+ }
328
+
329
+ if (tier === 'session') {
330
+ return Array.from(this.sessionCache.keys());
331
+ }
332
+
333
+ if (this.useIndexedDB) {
334
+ return await this._getIndexedDBKeys(tier);
335
+ } else if (this.useLocalStorage) {
336
+ return this._getLocalStorageKeys(tier);
337
+ }
338
+
339
+ return [];
340
+ }
341
+
342
+ /**
343
+ * Get all entries in a tier as [{ key, value, timestamp }]. Used for
344
+ * LRU eviction and trail diagnostics.
345
+ *
346
+ * @param {string} tier - Cache tier
347
+ * @returns {Promise<Array<{key:string, value:any, timestamp:number}>>}
348
+ */
349
+ async getAll(tier = 'rendered') {
350
+ if (!this.initialized) {
351
+ return [];
352
+ }
353
+
354
+ if (tier === 'session') {
355
+ return Array.from(this.sessionCache.entries()).map(([key, value]) => ({
356
+ key, value, timestamp: 0
357
+ }));
358
+ }
359
+
360
+ if (this.useIndexedDB) {
361
+ return await this._getAllFromIndexedDB(tier);
362
+ } else if (this.useLocalStorage) {
363
+ return this._getAllFromLocalStorage(tier);
364
+ }
365
+
366
+ return [];
367
+ }
368
+
369
+ //
370
+ // IndexedDB Private Methods
371
+ //
372
+
373
+ _getFromIndexedDB(key, tier) {
374
+ return new Promise((resolve, _reject) => {
375
+ try {
376
+ const transaction = this.db.transaction([tier], 'readonly');
377
+ const store = transaction.objectStore(tier);
378
+ const request = store.get(key);
379
+
380
+ request.onsuccess = () => {
381
+ const entry = request.result;
382
+ resolve(entry ? entry.value : null);
383
+ };
384
+
385
+ request.onerror = () => {
386
+ this.logger.error('[StorageManager] IndexedDB get error:', request.error);
387
+ resolve(null);
388
+ };
389
+ } catch (error) {
390
+ this.logger.error('[StorageManager] IndexedDB get exception:', error);
391
+ resolve(null);
392
+ }
393
+ });
394
+ }
395
+
396
+ _setInIndexedDB(entry, tier) {
397
+ return new Promise((resolve, _reject) => {
398
+ try {
399
+ const transaction = this.db.transaction([tier], 'readwrite');
400
+ const store = transaction.objectStore(tier);
401
+ const request = store.put(entry);
402
+
403
+ request.onsuccess = () => resolve(true);
404
+ request.onerror = () => {
405
+ this.logger.error('[StorageManager] IndexedDB set error:', request.error);
406
+ resolve(false);
407
+ };
408
+ } catch (error) {
409
+ this.logger.error('[StorageManager] IndexedDB set exception:', error);
410
+ resolve(false);
411
+ }
412
+ });
413
+ }
414
+
415
+ _removeFromIndexedDB(key, tier) {
416
+ return new Promise((resolve) => {
417
+ try {
418
+ const transaction = this.db.transaction([tier], 'readwrite');
419
+ const store = transaction.objectStore(tier);
420
+ const request = store.delete(key);
421
+
422
+ request.onsuccess = () => resolve(true);
423
+ request.onerror = () => resolve(false);
424
+ } catch (error) {
425
+ resolve(false);
426
+ }
427
+ });
428
+ }
429
+
430
+ _clearIndexedDBStore(tier) {
431
+ return new Promise((resolve) => {
432
+ try {
433
+ const transaction = this.db.transaction([tier], 'readwrite');
434
+ const store = transaction.objectStore(tier);
435
+ const request = store.clear();
436
+
437
+ request.onsuccess = () => resolve(true);
438
+ request.onerror = () => resolve(false);
439
+ } catch (error) {
440
+ resolve(false);
441
+ }
442
+ });
443
+ }
444
+
445
+ _getIndexedDBKeys(tier) {
446
+ return new Promise((resolve) => {
447
+ try {
448
+ const transaction = this.db.transaction([tier], 'readonly');
449
+ const store = transaction.objectStore(tier);
450
+ const request = store.getAllKeys();
451
+
452
+ request.onsuccess = () => resolve(request.result || []);
453
+ request.onerror = () => resolve([]);
454
+ } catch (error) {
455
+ resolve([]);
456
+ }
457
+ });
458
+ }
459
+
460
+ _getAllFromIndexedDB(tier) {
461
+ return new Promise((resolve) => {
462
+ try {
463
+ const transaction = this.db.transaction([tier], 'readonly');
464
+ const store = transaction.objectStore(tier);
465
+ const request = store.getAll();
466
+
467
+ request.onsuccess = () => resolve(request.result || []);
468
+ request.onerror = () => resolve([]);
469
+ } catch (error) {
470
+ resolve([]);
471
+ }
472
+ });
473
+ }
474
+
475
+ //
476
+ // localStorage Private Methods
477
+ //
478
+
479
+ _makeLocalStorageKey(key, tier) {
480
+ return `${this.namespace}_${tier}_${key}`;
481
+ }
482
+
483
+ _getFromLocalStorage(key, tier) {
484
+ try {
485
+ const storageKey = this._makeLocalStorageKey(key, tier);
486
+ const json = localStorage.getItem(storageKey);
487
+ if (!json) {
488
+ return null;
489
+ }
490
+
491
+ const entry = JSON.parse(json);
492
+ return entry.value || null;
493
+ } catch (error) {
494
+ this.logger.error('[StorageManager] localStorage get error:', error);
495
+ return null;
496
+ }
497
+ }
498
+
499
+ _setInLocalStorage(entry, tier) {
500
+ try {
501
+ const storageKey = this._makeLocalStorageKey(entry.key, tier);
502
+ localStorage.setItem(storageKey, JSON.stringify(entry));
503
+ return true;
504
+ } catch (error) {
505
+ this.logger.error('[StorageManager] localStorage set error (quota exceeded?):', error);
506
+ return false;
507
+ }
508
+ }
509
+
510
+ _removeFromLocalStorage(key, tier) {
511
+ try {
512
+ const storageKey = this._makeLocalStorageKey(key, tier);
513
+ localStorage.removeItem(storageKey);
514
+ return true;
515
+ } catch (error) {
516
+ return false;
517
+ }
518
+ }
519
+
520
+ _clearLocalStorageTier(tier) {
521
+ try {
522
+ const prefix = `${this.namespace}_${tier}_`;
523
+ const keysToRemove = [];
524
+
525
+ for (let i = 0; i < localStorage.length; i++) {
526
+ const key = localStorage.key(i);
527
+ if (key && key.startsWith(prefix)) {
528
+ keysToRemove.push(key);
529
+ }
530
+ }
531
+
532
+ keysToRemove.forEach(key => localStorage.removeItem(key));
533
+ return true;
534
+ } catch (error) {
535
+ return false;
536
+ }
537
+ }
538
+
539
+ _getLocalStorageKeys(tier) {
540
+ try {
541
+ const prefix = `${this.namespace}_${tier}_`;
542
+ const keys = [];
543
+
544
+ for (let i = 0; i < localStorage.length; i++) {
545
+ const key = localStorage.key(i);
546
+ if (key && key.startsWith(prefix)) {
547
+ // Remove prefix to get original key
548
+ keys.push(key.substring(prefix.length));
549
+ }
550
+ }
551
+
552
+ return keys;
553
+ } catch (error) {
554
+ return [];
555
+ }
556
+ }
557
+
558
+ _getAllFromLocalStorage(tier) {
559
+ try {
560
+ const prefix = `${this.namespace}_${tier}_`;
561
+ const out = [];
562
+
563
+ for (let i = 0; i < localStorage.length; i++) {
564
+ const storageKey = localStorage.key(i);
565
+ if (storageKey && storageKey.startsWith(prefix)) {
566
+ try {
567
+ const entry = JSON.parse(localStorage.getItem(storageKey));
568
+ out.push({
569
+ key: storageKey.substring(prefix.length),
570
+ value: entry.value,
571
+ timestamp: entry.timestamp || 0
572
+ });
573
+ } catch (_e) { /* skip malformed entry */ }
574
+ }
575
+ }
576
+
577
+ return out;
578
+ } catch (error) {
579
+ return [];
580
+ }
581
+ }
582
+ }
583
+
584
+ //
585
+ // Export
586
+ //
587
+
588
+ return StorageManager;
589
+ }));
590
+
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Composite Rendering Module Barrel Export
3
+ *
4
+ * Complex composite components (dashboards, terminals, swipers, wizards).
5
+ *
6
+ * @module rendering/composite
7
+ * @layer 3 (Composite Rendering)
8
+ */
9
+
10
+ export * from './dashboard_renderer.js';
11
+ export * from './swiper_renderer.js';
12
+ export * from './terminal_renderer.js';
13
+ export * from './wizard_conditional_renderer.js';