@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,13 @@
1
+ /**
2
+ * L1_Foundation - Core Infrastructure Layer
3
+ *
4
+ * Low-level primitives with no dependencies on higher layers.
5
+ * Provides: Connection, Logging, Configuration, Constants, Bootstrap
6
+ */
7
+
8
+ // Export subdirectories (will be populated in Step 2)
9
+ export * from './connection/connection.js';
10
+ export * from './logger/logger.js';
11
+ export * from './config/config.js';
12
+ export * from './constants/constants.js';
13
+ export * from './bootstrap/bootstrap.js';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * L1_Foundation/bootstrap - Bootstrap Infrastructure
3
+ *
4
+ * UMD bootstrap components, CDN loading, module registry.
5
+ */
6
+
7
+ export { BootstrapLogger } from './bootstrap_logger.js';
8
+ export { BootstrapHooks } from './bootstrap_hooks.js';
9
+ export { CDNLoader } from './cdn_loader.js';
10
+ export { ModuleRegistry } from './module_registry.js';
11
+ export { loadPrismJS } from './prism_loader.js';
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Bootstrap Hooks - Lightweight inline hook manager for UMD bootstrap
3
+ *
4
+ * Zero-dependency hook system used before ES modules load.
5
+ * Intentional duplication of core/hooks.js for UMD compatibility.
6
+ *
7
+ * @module bootstrap/bootstrap_hooks
8
+ * @layer -1 (Bootstrap - loaded before all other layers)
9
+ *
10
+ * Pattern: UMD module that creates browser global
11
+ *
12
+ * Usage:
13
+ * ```javascript
14
+ * const hooks = createBootstrapHooks({ onConnected: () => {} }, logger);
15
+ * hooks.call('onConnected', data);
16
+ * hooks.register('onMessage', (msg) => {});
17
+ * ```
18
+ *
19
+ * Extracted from bifrost_client.js (Phase 2)
20
+ */
21
+
22
+ (function(root, factory) {
23
+ if (typeof define === 'function' && define.amd) {
24
+ define([], factory);
25
+ } else if (typeof module === 'object' && module.exports) {
26
+ module.exports = factory();
27
+ } else {
28
+ root.createBootstrapHooks = factory();
29
+ }
30
+ }(typeof self !== 'undefined' ? self : this, () => {
31
+ 'use strict';
32
+
33
+ /**
34
+ * Create a lightweight hook manager instance
35
+ *
36
+ * @param {Object} initialHooks - Initial hooks object
37
+ * @param {Object} logger - Logger instance for debugging
38
+ * @returns {Object} Hook manager instance
39
+ */
40
+ function createBootstrapHooks(initialHooks = {}, logger = console) {
41
+ const hookManager = {
42
+ hooks: initialHooks,
43
+ errorHandler: null,
44
+ logger: logger,
45
+
46
+ call: (hookName, ...args) => {
47
+ const hook = hookManager.hooks[hookName];
48
+ hookManager.logger.debug(`[Hooks] Calling hook: ${hookName}`);
49
+
50
+ if (typeof hook === 'function') {
51
+ try {
52
+ return hook(...args);
53
+ } catch (error) {
54
+ // Log to console
55
+ hookManager.logger.error(`Error in ${hookName} hook:`, error);
56
+
57
+ // Display in UI if error handler is set
58
+ if (hookManager.errorHandler) {
59
+ try {
60
+ hookManager.errorHandler({
61
+ type: 'hook_error',
62
+ hookName,
63
+ error,
64
+ message: error.message,
65
+ stack: error.stack
66
+ });
67
+ } catch (displayError) {
68
+ hookManager.logger.error('Error handler itself failed:', displayError);
69
+ }
70
+ }
71
+
72
+ // Call onError hook if it exists and isn't the one that failed
73
+ if (hookName !== 'onError' && hookManager.hooks.onError) {
74
+ try {
75
+ hookManager.hooks.onError(error);
76
+ } catch (onErrorError) {
77
+ hookManager.logger.error('onError hook failed:', onErrorError);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ },
83
+
84
+ has: (hookName) => {
85
+ return typeof hookManager.hooks[hookName] === 'function';
86
+ },
87
+
88
+ register: (hookName, fn) => {
89
+ if (typeof fn === 'function') {
90
+ hookManager.hooks[hookName] = fn;
91
+ hookManager.logger.debug(`[Hooks] Registered hook: ${hookName}`);
92
+ } else {
93
+ hookManager.logger.error(`[Hooks] [ERROR] Failed to register hook ${hookName}: not a function`);
94
+ }
95
+ },
96
+
97
+ unregister: (hookName) => {
98
+ delete hookManager.hooks[hookName];
99
+ },
100
+
101
+ list: () => Object.keys(hookManager.hooks),
102
+
103
+ // Dark mode utilities (requires dynamic import)
104
+ initBuiltInHooks: () => {
105
+ // Initialize dark mode from localStorage
106
+ const savedTheme = localStorage.getItem('zTheme-mode');
107
+ if (savedTheme === 'dark') {
108
+ hookManager._applyDarkMode(true);
109
+ }
110
+ },
111
+
112
+ _applyDarkMode: async (isDark) => {
113
+ // Note: This requires import, so it's kept in bifrost_client.js
114
+ // This method is a placeholder that will be overridden
115
+ hookManager.logger.warn('[Hooks] _applyDarkMode not yet initialized');
116
+ }
117
+ };
118
+
119
+ return hookManager;
120
+ }
121
+
122
+ return createBootstrapHooks;
123
+ }));
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Bootstrap Module Barrel Export
3
+ *
4
+ * Centralized exports for all bootstrap utilities.
5
+ *
6
+ * @module bootstrap
7
+ * @layer -1 (Bootstrap)
8
+ */
9
+
10
+ // Note: bootstrap_logger.js and bootstrap_hooks.js are UMD modules
11
+ // They are loaded directly in bifrost_client.js via <script> tags or dynamic import
12
+ // This barrel file only exports ES modules
13
+
14
+ export * from './module_registry.js';
15
+ export * from './cdn_loader.js';
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Bootstrap Logger - Lightweight inline logger for UMD bootstrap
3
+ *
4
+ * Zero-dependency logger used before ES modules load.
5
+ * Intentional duplication of core/logger.js for UMD compatibility.
6
+ *
7
+ * @module bootstrap/bootstrap_logger
8
+ * @layer -1 (Bootstrap - loaded before all other layers)
9
+ *
10
+ * Pattern: UMD module that creates browser global
11
+ *
12
+ * Usage:
13
+ * ```javascript
14
+ * const logger = createBootstrapLogger('Bifrost', 'INFO');
15
+ * logger.log('Message');
16
+ * logger.error('Error');
17
+ * ```
18
+ *
19
+ * Extracted from bifrost_client.js (Phase 2)
20
+ */
21
+
22
+ (function(root, factory) {
23
+ if (typeof define === 'function' && define.amd) {
24
+ define([], factory);
25
+ } else if (typeof module === 'object' && module.exports) {
26
+ module.exports = factory();
27
+ } else {
28
+ root.createBootstrapLogger = factory();
29
+ }
30
+ }(typeof self !== 'undefined' ? self : this, () => {
31
+ 'use strict';
32
+
33
+ /**
34
+ * Create a lightweight logger instance
35
+ *
36
+ * @param {string} context - Logger context name (e.g., 'Bifrost')
37
+ * @param {string} logLevel - Log level (DEBUG, INFO, WARN, ERROR)
38
+ * @returns {Object} Logger instance
39
+ */
40
+ function createBootstrapLogger(context = 'Bifrost', logLevel = 'INFO') {
41
+ const logger = {
42
+ levels: { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 },
43
+ level: logLevel === 'DEBUG' ? 0 : logLevel === 'INFO' ? 1 : logLevel === 'WARN' ? 2 : 3,
44
+ context: context,
45
+
46
+ _interpolate: (message, args) => {
47
+ if (args.length === 0) return message;
48
+
49
+ // Support Python-style %s interpolation
50
+ if (message.includes('%s')) {
51
+ let result = message;
52
+ args.forEach(arg => {
53
+ result = result.replace('%s', String(arg));
54
+ });
55
+ return result;
56
+ }
57
+
58
+ return message;
59
+ },
60
+
61
+ _formatMessage: (level, message, args = []) => {
62
+ const interpolated = logger._interpolate(message, args);
63
+
64
+ // ANSI color codes for browser console
65
+ const colors = {
66
+ debug: '\x1b[90m', // Gray for DEBUG
67
+ info: '\x1b[34m', // Blue for INFO
68
+ warn: '\x1b[33m', // Yellow for WARN
69
+ error: '\x1b[91m', // Bright red for ERROR
70
+ message: '\x1b[38;2;255;251;203m', // Cream #fffbcb for message text
71
+ bold: '\x1b[1m', // Bold
72
+ reset: '\x1b[0m'
73
+ };
74
+
75
+ const levelColor = colors[level.toLowerCase()] || colors.info;
76
+
77
+ return `${colors.bold}${levelColor}[${level}]${colors.reset}: ${colors.message}${interpolated}${colors.reset}`;
78
+ },
79
+
80
+ debug: (message, ...args) => {
81
+ if (logger.level <= logger.levels.DEBUG) {
82
+ const formatted = logger._formatMessage('DEBUG', message, args);
83
+ console.debug(formatted, ...args.filter(arg => typeof arg === 'object'));
84
+ }
85
+ },
86
+
87
+ info: (message, ...args) => {
88
+ if (logger.level <= logger.levels.INFO) {
89
+ const formatted = logger._formatMessage('INFO', message, args);
90
+ console.info(formatted, ...args.filter(arg => typeof arg === 'object'));
91
+ }
92
+ },
93
+
94
+ log: (message, ...args) => {
95
+ if (logger.level <= logger.levels.INFO) {
96
+ const formatted = logger._formatMessage('INFO', message, args);
97
+ console.log(formatted, ...args.filter(arg => typeof arg === 'object'));
98
+ }
99
+ },
100
+
101
+ error: (message, ...args) => {
102
+ const formatted = logger._formatMessage('ERROR', message, args);
103
+ console.error(formatted, ...args.filter(arg => typeof arg === 'object'));
104
+ },
105
+
106
+ warn: (message, ...args) => {
107
+ if (logger.level <= logger.levels.WARN) {
108
+ const formatted = logger._formatMessage('WARN', message, args);
109
+ console.warn(formatted, ...args.filter(arg => typeof arg === 'object'));
110
+ }
111
+ },
112
+
113
+ setLevel: (level) => {
114
+ const levelMap = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 };
115
+ logger.level = levelMap[level] || levelMap.INFO;
116
+ },
117
+
118
+ enable: () => {
119
+ logger.level = logger.levels.DEBUG;
120
+ },
121
+
122
+ disable: () => {
123
+ logger.level = logger.levels.ERROR;
124
+ },
125
+
126
+ isEnabled: () => {
127
+ return logger.level <= logger.levels.INFO;
128
+ }
129
+ };
130
+
131
+ return logger;
132
+ }
133
+
134
+ return createBootstrapLogger;
135
+ }));
@@ -0,0 +1,217 @@
1
+ /**
2
+ * CDN Loader - External asset loading utilities
3
+ *
4
+ * Centralized logic for loading external CSS/JS from CDNs.
5
+ * Extracted from bifrost_client.js to reduce main file size.
6
+ *
7
+ * @module bootstrap/cdn_loader
8
+ * @layer -1 (Bootstrap)
9
+ *
10
+ * Pattern: ES module (not UMD - only used by bifrost_client.js)
11
+ *
12
+ * Usage:
13
+ * ```javascript
14
+ * import { loadZThemeCDN, loadBootstrapIcons, loadPrismJS } from './bootstrap/cdn_loader.js';
15
+ * await loadZThemeCDN('https://cdn.jsdelivr.net/gh/ZoloAi/zTheme@main/dist');
16
+ * await loadBootstrapIcons();
17
+ * await loadPrismJS();
18
+ * ```
19
+ *
20
+ * Created in Phase 2
21
+ */
22
+
23
+ /**
24
+ * Load zTheme CSS and JS from CDN
25
+ *
26
+ * @param {string} cdnBaseUrl - CDN base URL (default: jsdelivr ZoloAi/zTheme)
27
+ * @param {Object} logger - Logger instance
28
+ * @returns {Promise<void>}
29
+ */
30
+ export async function loadZThemeCDN(cdnBaseUrl = 'https://cdn.jsdelivr.net/gh/ZoloAi/zTheme@main/dist', logger = console) {
31
+ if (typeof document === 'undefined') {
32
+ logger.warn('[CDN] Not in browser environment - skipping zTheme CDN load');
33
+ return;
34
+ }
35
+
36
+ // Check if already loaded
37
+ if (document.querySelector('link[href*="zTheme"]')) {
38
+ logger.log('[CDN] zTheme CSS already loaded');
39
+ return;
40
+ }
41
+
42
+ logger.log(`[CDN] Loading zTheme from: ${cdnBaseUrl}`);
43
+
44
+ // Load CSS
45
+ const cssLink = document.createElement('link');
46
+ cssLink.rel = 'stylesheet';
47
+ cssLink.href = `${cdnBaseUrl}/zTheme.css`;
48
+ document.head.appendChild(cssLink);
49
+
50
+ // Load JS (if exists)
51
+ try {
52
+ const jsScript = document.createElement('script');
53
+ jsScript.src = `${cdnBaseUrl}/zTheme.js`;
54
+ jsScript.async = true;
55
+ document.head.appendChild(jsScript);
56
+
57
+ await new Promise((resolve, reject) => {
58
+ jsScript.onload = resolve;
59
+ jsScript.onerror = () => {
60
+ logger.warn('[CDN] zTheme JS not found (CSS-only mode)');
61
+ resolve(); // Non-fatal
62
+ };
63
+ });
64
+ } catch (err) {
65
+ logger.warn('[CDN] Failed to load zTheme JS:', err);
66
+ }
67
+
68
+ logger.log('[CDN] zTheme loaded successfully');
69
+ }
70
+
71
+ /**
72
+ * Load Bootstrap Icons from CDN
73
+ *
74
+ * @param {string} cdnUrl - CDN URL (default: jsdelivr bootstrap-icons)
75
+ * @param {Object} logger - Logger instance
76
+ * @returns {Promise<void>}
77
+ */
78
+ export async function loadBootstrapIcons(
79
+ cdnUrl = 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css',
80
+ logger = console
81
+ ) {
82
+ if (typeof document === 'undefined') {
83
+ logger.warn('[CDN] Not in browser environment - skipping Bootstrap Icons');
84
+ return;
85
+ }
86
+
87
+ // Check if already loaded
88
+ if (document.querySelector('link[href*="bootstrap-icons"]')) {
89
+ logger.log('[CDN] Bootstrap Icons already loaded');
90
+ return;
91
+ }
92
+
93
+ logger.log('[CDN] Loading Bootstrap Icons');
94
+
95
+ const link = document.createElement('link');
96
+ link.rel = 'stylesheet';
97
+ link.href = cdnUrl;
98
+ document.head.appendChild(link);
99
+
100
+ await new Promise((resolve) => {
101
+ link.onload = resolve;
102
+ link.onerror = () => {
103
+ logger.warn('[CDN] Failed to load Bootstrap Icons');
104
+ resolve(); // Non-fatal
105
+ };
106
+ });
107
+
108
+ logger.log('[CDN] Bootstrap Icons loaded');
109
+ }
110
+
111
+ /**
112
+ * Load Prism.js from CDN
113
+ *
114
+ * @param {string} baseUrl - Base URL for Prism assets
115
+ * @param {Object} logger - Logger instance
116
+ * @returns {Promise<void>}
117
+ */
118
+ export async function loadPrismJS(baseUrl = null, logger = console) {
119
+ if (typeof document === 'undefined') {
120
+ logger.warn('[CDN] Not in browser environment - skipping Prism.js');
121
+ return;
122
+ }
123
+
124
+ // Check if already loaded
125
+ if (window.Prism) {
126
+ logger.log('[CDN] Prism.js already loaded');
127
+ return;
128
+ }
129
+
130
+ logger.log('[CDN] Loading Prism.js');
131
+
132
+ // Determine base URL (prefer local, fallback to CDN)
133
+ const prismBaseUrl = baseUrl || 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0';
134
+
135
+ // Load CSS
136
+ const cssLink = document.createElement('link');
137
+ cssLink.rel = 'stylesheet';
138
+ cssLink.href = `${prismBaseUrl}/themes/prism.css`;
139
+ document.head.appendChild(cssLink);
140
+
141
+ // Load JS
142
+ const script = document.createElement('script');
143
+ script.src = `${prismBaseUrl}/prism.js`;
144
+ script.async = true;
145
+ document.head.appendChild(script);
146
+
147
+ await new Promise((resolve) => {
148
+ script.onload = resolve;
149
+ script.onerror = () => {
150
+ logger.warn('[CDN] Failed to load Prism.js');
151
+ resolve(); // Non-fatal
152
+ };
153
+ });
154
+
155
+ logger.log('[CDN] Prism.js loaded');
156
+ }
157
+
158
+ /**
159
+ * Generic CSS loader
160
+ *
161
+ * @param {string} href - CSS file URL
162
+ * @param {Object} logger - Logger instance
163
+ * @returns {Promise<void>}
164
+ */
165
+ export async function loadCSS(href, logger = console) {
166
+ if (typeof document === 'undefined') {
167
+ return;
168
+ }
169
+
170
+ // Check if already loaded
171
+ if (document.querySelector(`link[href="${href}"]`)) {
172
+ logger.debug(`[CDN] CSS already loaded: ${href}`);
173
+ return;
174
+ }
175
+
176
+ const link = document.createElement('link');
177
+ link.rel = 'stylesheet';
178
+ link.href = href;
179
+ document.head.appendChild(link);
180
+
181
+ await new Promise((resolve) => {
182
+ link.onload = resolve;
183
+ link.onerror = () => {
184
+ logger.warn(`[CDN] Failed to load CSS: ${href}`);
185
+ resolve(); // Non-fatal
186
+ };
187
+ });
188
+ }
189
+
190
+ /**
191
+ * Generic JS loader
192
+ *
193
+ * @param {string} src - JS file URL
194
+ * @param {Object} logger - Logger instance
195
+ * @returns {Promise<void>}
196
+ */
197
+ export async function loadJS(src, logger = console) {
198
+ if (typeof document === 'undefined') {
199
+ return;
200
+ }
201
+
202
+ // Check if already loaded
203
+ if (document.querySelector(`script[src="${src}"]`)) {
204
+ logger.debug(`[CDN] JS already loaded: ${src}`);
205
+ return;
206
+ }
207
+
208
+ const script = document.createElement('script');
209
+ script.src = src;
210
+ script.async = true;
211
+ document.head.appendChild(script);
212
+
213
+ await new Promise((resolve, reject) => {
214
+ script.onload = resolve;
215
+ script.onerror = () => reject(new Error(`Failed to load: ${src}`));
216
+ });
217
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Module Registry - SSOT for dynamic module loading paths
3
+ *
4
+ * Centralized registry of all dynamically loaded modules and their paths.
5
+ * Eliminates hardcoded string paths in _loadModule().
6
+ *
7
+ * @module bootstrap/module_registry
8
+ * @layer -1 (Bootstrap)
9
+ *
10
+ * Pattern: ES module (not UMD - only used by bifrost_client.js)
11
+ *
12
+ * Usage:
13
+ * ```javascript
14
+ * import { MODULE_REGISTRY, getModulePath } from './bootstrap/module_registry.js';
15
+ * const path = getModulePath('connection'); // 'core/connection.js'
16
+ * ```
17
+ *
18
+ * Created in Phase 2
19
+ */
20
+
21
+ // ─────────────────────────────────────────────────────────────────
22
+ // Module Registry - SSOT for all module paths
23
+ // ─────────────────────────────────────────────────────────────────
24
+
25
+ export const MODULE_REGISTRY = {
26
+ // L1 Foundation modules
27
+ connection: 'L1_Foundation/connection/connection.js',
28
+ logger: 'L1_Foundation/logger/logger.js',
29
+
30
+ // L2 Handling modules
31
+ message_handler: 'L2_Handling/message/message_handler.js',
32
+ navigation_manager: 'L2_Handling/navigation/navigation_manager.js',
33
+ widget_hook_manager: 'L2_Handling/hooks/widget_hook_manager.js',
34
+ zvaf_manager: 'L2_Handling/zvaf/zvaf_manager.js',
35
+ error_display: 'zSys/errors/error_display.js', // Step 6: Moved to zSys
36
+
37
+ // L2 Display: Orchestration
38
+ renderer: 'L2_Handling/display/orchestration/renderer.js',
39
+ zdisplay_orchestrator: 'L2_Handling/display/orchestration/zdisplay_orchestrator.js',
40
+ // L2 Display: Navigation
41
+ navigation_renderer: 'L2_Handling/display/navigation/navigation_renderer.js',
42
+ menu_renderer: 'L2_Handling/display/navigation/menu_renderer.js',
43
+
44
+ // L2 Display: Inputs
45
+ form_renderer: 'L2_Handling/display/inputs/form_renderer.js',
46
+ button_renderer: 'L2_Handling/display/inputs/button_renderer.js',
47
+ input_renderer: 'L2_Handling/display/inputs/input_renderer.js',
48
+
49
+ // L2 Display: Outputs
50
+ text_renderer: 'L2_Handling/display/outputs/text_renderer.js',
51
+ table_renderer: 'L2_Handling/display/outputs/table_renderer.js',
52
+ card_renderer: 'L2_Handling/display/outputs/card_renderer.js',
53
+ header_renderer: 'L2_Handling/display/outputs/header_renderer.js',
54
+ typography_renderer: 'L2_Handling/display/outputs/typography_renderer.js',
55
+ alert_renderer: 'L2_Handling/display/outputs/alert_renderer.js',
56
+ list_renderer: 'L2_Handling/display/outputs/list_renderer.js',
57
+ image_renderer: 'L2_Handling/display/outputs/image_renderer.js',
58
+ icon_renderer: 'L2_Handling/display/outputs/icon_renderer.js',
59
+ dl_renderer: 'L2_Handling/display/outputs/dl_renderer.js',
60
+
61
+ // L2 Display: Composite
62
+ dashboard_renderer: 'L2_Handling/display/composite/dashboard_renderer.js',
63
+ terminal_renderer: 'L2_Handling/display/composite/terminal_renderer.js',
64
+ swiper_renderer: 'L2_Handling/display/composite/swiper_renderer.js',
65
+ wizard_conditional_renderer: 'L2_Handling/display/composite/wizard_conditional_renderer.js',
66
+
67
+ // L2 Display: Feedback
68
+ progressbar_renderer: 'L2_Handling/display/feedback/progressbar_renderer.js',
69
+ spinner_renderer: 'L2_Handling/display/feedback/spinner_renderer.js',
70
+
71
+ // L2 Display: Specialized
72
+ input_request_renderer: 'L2_Handling/display/specialized/input_request_renderer.js',
73
+ };
74
+
75
+ /**
76
+ * Get module path from registry
77
+ *
78
+ * @param {string} moduleName - Module name (e.g., 'connection')
79
+ * @returns {string|null} Module path or null if not found
80
+ */
81
+ export function getModulePath(moduleName) {
82
+ return MODULE_REGISTRY[moduleName] || null;
83
+ }
84
+
85
+ /**
86
+ * Get all registered module names
87
+ *
88
+ * @returns {string[]} Array of module names
89
+ */
90
+ export function getAllModuleNames() {
91
+ return Object.keys(MODULE_REGISTRY);
92
+ }
93
+
94
+ /**
95
+ * Check if module is registered
96
+ *
97
+ * @param {string} moduleName - Module name to check
98
+ * @returns {boolean} True if module is registered
99
+ */
100
+ export function isModuleRegistered(moduleName) {
101
+ return moduleName in MODULE_REGISTRY;
102
+ }