@zintrust/workers 0.1.27

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 (178) hide show
  1. package/README.md +861 -0
  2. package/dist/AnomalyDetection.d.ts +102 -0
  3. package/dist/AnomalyDetection.js +321 -0
  4. package/dist/AutoScaler.d.ts +127 -0
  5. package/dist/AutoScaler.js +425 -0
  6. package/dist/BroadcastWorker.d.ts +21 -0
  7. package/dist/BroadcastWorker.js +24 -0
  8. package/dist/CanaryController.d.ts +103 -0
  9. package/dist/CanaryController.js +380 -0
  10. package/dist/ChaosEngineering.d.ts +79 -0
  11. package/dist/ChaosEngineering.js +216 -0
  12. package/dist/CircuitBreaker.d.ts +106 -0
  13. package/dist/CircuitBreaker.js +374 -0
  14. package/dist/ClusterLock.d.ts +90 -0
  15. package/dist/ClusterLock.js +385 -0
  16. package/dist/ComplianceManager.d.ts +177 -0
  17. package/dist/ComplianceManager.js +556 -0
  18. package/dist/DatacenterOrchestrator.d.ts +133 -0
  19. package/dist/DatacenterOrchestrator.js +404 -0
  20. package/dist/DeadLetterQueue.d.ts +122 -0
  21. package/dist/DeadLetterQueue.js +539 -0
  22. package/dist/HealthMonitor.d.ts +42 -0
  23. package/dist/HealthMonitor.js +301 -0
  24. package/dist/MultiQueueWorker.d.ts +89 -0
  25. package/dist/MultiQueueWorker.js +277 -0
  26. package/dist/NotificationWorker.d.ts +21 -0
  27. package/dist/NotificationWorker.js +23 -0
  28. package/dist/Observability.d.ts +153 -0
  29. package/dist/Observability.js +530 -0
  30. package/dist/PluginManager.d.ts +123 -0
  31. package/dist/PluginManager.js +392 -0
  32. package/dist/PriorityQueue.d.ts +117 -0
  33. package/dist/PriorityQueue.js +244 -0
  34. package/dist/ResourceMonitor.d.ts +164 -0
  35. package/dist/ResourceMonitor.js +605 -0
  36. package/dist/SLAMonitor.d.ts +110 -0
  37. package/dist/SLAMonitor.js +274 -0
  38. package/dist/WorkerFactory.d.ts +193 -0
  39. package/dist/WorkerFactory.js +1507 -0
  40. package/dist/WorkerInit.d.ts +85 -0
  41. package/dist/WorkerInit.js +223 -0
  42. package/dist/WorkerMetrics.d.ts +114 -0
  43. package/dist/WorkerMetrics.js +509 -0
  44. package/dist/WorkerRegistry.d.ts +145 -0
  45. package/dist/WorkerRegistry.js +319 -0
  46. package/dist/WorkerShutdown.d.ts +61 -0
  47. package/dist/WorkerShutdown.js +159 -0
  48. package/dist/WorkerVersioning.d.ts +107 -0
  49. package/dist/WorkerVersioning.js +300 -0
  50. package/dist/build-manifest.json +462 -0
  51. package/dist/config/workerConfig.d.ts +3 -0
  52. package/dist/config/workerConfig.js +19 -0
  53. package/dist/createQueueWorker.d.ts +23 -0
  54. package/dist/createQueueWorker.js +113 -0
  55. package/dist/dashboard/index.d.ts +1 -0
  56. package/dist/dashboard/index.js +1 -0
  57. package/dist/dashboard/types.d.ts +117 -0
  58. package/dist/dashboard/types.js +1 -0
  59. package/dist/dashboard/workers-api.d.ts +4 -0
  60. package/dist/dashboard/workers-api.js +638 -0
  61. package/dist/dashboard/workers-dashboard-ui.d.ts +3 -0
  62. package/dist/dashboard/workers-dashboard-ui.js +1026 -0
  63. package/dist/dashboard/workers-dashboard.d.ts +4 -0
  64. package/dist/dashboard/workers-dashboard.js +904 -0
  65. package/dist/helper/index.d.ts +5 -0
  66. package/dist/helper/index.js +10 -0
  67. package/dist/http/WorkerApiController.d.ts +38 -0
  68. package/dist/http/WorkerApiController.js +312 -0
  69. package/dist/http/WorkerController.d.ts +374 -0
  70. package/dist/http/WorkerController.js +1351 -0
  71. package/dist/http/middleware/CustomValidation.d.ts +92 -0
  72. package/dist/http/middleware/CustomValidation.js +270 -0
  73. package/dist/http/middleware/DatacenterValidator.d.ts +3 -0
  74. package/dist/http/middleware/DatacenterValidator.js +94 -0
  75. package/dist/http/middleware/EditWorkerValidation.d.ts +7 -0
  76. package/dist/http/middleware/EditWorkerValidation.js +55 -0
  77. package/dist/http/middleware/FeaturesValidator.d.ts +3 -0
  78. package/dist/http/middleware/FeaturesValidator.js +60 -0
  79. package/dist/http/middleware/InfrastructureValidator.d.ts +31 -0
  80. package/dist/http/middleware/InfrastructureValidator.js +226 -0
  81. package/dist/http/middleware/OptionsValidator.d.ts +3 -0
  82. package/dist/http/middleware/OptionsValidator.js +112 -0
  83. package/dist/http/middleware/PayloadSanitizer.d.ts +7 -0
  84. package/dist/http/middleware/PayloadSanitizer.js +42 -0
  85. package/dist/http/middleware/ProcessorPathSanitizer.d.ts +3 -0
  86. package/dist/http/middleware/ProcessorPathSanitizer.js +74 -0
  87. package/dist/http/middleware/QueueNameSanitizer.d.ts +3 -0
  88. package/dist/http/middleware/QueueNameSanitizer.js +45 -0
  89. package/dist/http/middleware/ValidateDriver.d.ts +7 -0
  90. package/dist/http/middleware/ValidateDriver.js +20 -0
  91. package/dist/http/middleware/VersionSanitizer.d.ts +3 -0
  92. package/dist/http/middleware/VersionSanitizer.js +25 -0
  93. package/dist/http/middleware/WorkerNameSanitizer.d.ts +3 -0
  94. package/dist/http/middleware/WorkerNameSanitizer.js +46 -0
  95. package/dist/http/middleware/WorkerValidationChain.d.ts +27 -0
  96. package/dist/http/middleware/WorkerValidationChain.js +185 -0
  97. package/dist/index.d.ts +46 -0
  98. package/dist/index.js +48 -0
  99. package/dist/routes/workers.d.ts +12 -0
  100. package/dist/routes/workers.js +81 -0
  101. package/dist/storage/WorkerStore.d.ts +45 -0
  102. package/dist/storage/WorkerStore.js +195 -0
  103. package/dist/type.d.ts +76 -0
  104. package/dist/type.js +1 -0
  105. package/dist/ui/router/ui.d.ts +3 -0
  106. package/dist/ui/router/ui.js +83 -0
  107. package/dist/ui/types/worker-ui.d.ts +229 -0
  108. package/dist/ui/types/worker-ui.js +5 -0
  109. package/package.json +53 -0
  110. package/src/AnomalyDetection.ts +434 -0
  111. package/src/AutoScaler.ts +654 -0
  112. package/src/BroadcastWorker.ts +34 -0
  113. package/src/CanaryController.ts +531 -0
  114. package/src/ChaosEngineering.ts +301 -0
  115. package/src/CircuitBreaker.ts +495 -0
  116. package/src/ClusterLock.ts +499 -0
  117. package/src/ComplianceManager.ts +815 -0
  118. package/src/DatacenterOrchestrator.ts +561 -0
  119. package/src/DeadLetterQueue.ts +733 -0
  120. package/src/HealthMonitor.ts +390 -0
  121. package/src/MultiQueueWorker.ts +431 -0
  122. package/src/NotificationWorker.ts +33 -0
  123. package/src/Observability.ts +696 -0
  124. package/src/PluginManager.ts +551 -0
  125. package/src/PriorityQueue.ts +351 -0
  126. package/src/ResourceMonitor.ts +769 -0
  127. package/src/SLAMonitor.ts +408 -0
  128. package/src/WorkerFactory.ts +2108 -0
  129. package/src/WorkerInit.ts +313 -0
  130. package/src/WorkerMetrics.ts +709 -0
  131. package/src/WorkerRegistry.ts +443 -0
  132. package/src/WorkerShutdown.ts +210 -0
  133. package/src/WorkerVersioning.ts +422 -0
  134. package/src/config/workerConfig.ts +25 -0
  135. package/src/createQueueWorker.ts +174 -0
  136. package/src/dashboard/index.ts +6 -0
  137. package/src/dashboard/types.ts +141 -0
  138. package/src/dashboard/workers-api.ts +785 -0
  139. package/src/dashboard/zintrust.svg +30 -0
  140. package/src/helper/index.ts +11 -0
  141. package/src/http/WorkerApiController.ts +369 -0
  142. package/src/http/WorkerController.ts +1512 -0
  143. package/src/http/middleware/CustomValidation.ts +360 -0
  144. package/src/http/middleware/DatacenterValidator.ts +124 -0
  145. package/src/http/middleware/EditWorkerValidation.ts +74 -0
  146. package/src/http/middleware/FeaturesValidator.ts +82 -0
  147. package/src/http/middleware/InfrastructureValidator.ts +295 -0
  148. package/src/http/middleware/OptionsValidator.ts +144 -0
  149. package/src/http/middleware/PayloadSanitizer.ts +52 -0
  150. package/src/http/middleware/ProcessorPathSanitizer.ts +86 -0
  151. package/src/http/middleware/QueueNameSanitizer.ts +55 -0
  152. package/src/http/middleware/ValidateDriver.ts +29 -0
  153. package/src/http/middleware/VersionSanitizer.ts +30 -0
  154. package/src/http/middleware/WorkerNameSanitizer.ts +56 -0
  155. package/src/http/middleware/WorkerValidationChain.ts +230 -0
  156. package/src/index.ts +98 -0
  157. package/src/routes/workers.ts +154 -0
  158. package/src/storage/WorkerStore.ts +240 -0
  159. package/src/type.ts +89 -0
  160. package/src/types/queue-monitor.d.ts +38 -0
  161. package/src/types/queue-redis.d.ts +38 -0
  162. package/src/ui/README.md +13 -0
  163. package/src/ui/components/JsonEditor.js +670 -0
  164. package/src/ui/components/JsonViewer.js +387 -0
  165. package/src/ui/components/WorkerCard.js +178 -0
  166. package/src/ui/components/WorkerExpandPanel.js +257 -0
  167. package/src/ui/components/fetcher.js +42 -0
  168. package/src/ui/components/sla-scorecard.js +32 -0
  169. package/src/ui/components/styles.css +30 -0
  170. package/src/ui/components/table-expander.js +34 -0
  171. package/src/ui/integration/worker-ui-integration.js +565 -0
  172. package/src/ui/router/ui.ts +99 -0
  173. package/src/ui/services/workerApi.js +240 -0
  174. package/src/ui/types/worker-ui.ts +283 -0
  175. package/src/ui/utils/jsonValidator.js +444 -0
  176. package/src/ui/workers/index.html +202 -0
  177. package/src/ui/workers/main.js +1781 -0
  178. package/src/ui/workers/styles.css +1350 -0
@@ -0,0 +1,387 @@
1
+ /* eslint-disable no-restricted-syntax */
2
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
3
+ /* eslint-disable no-undef */
4
+ /**
5
+ * JSON Viewer Modal Component
6
+ * Displays JSON data in a formatted modal with syntax highlighting
7
+ */
8
+
9
+ /**
10
+ * Default configuration for JSON viewer
11
+ */
12
+ const getDefaultOptions = () => ({
13
+ title: 'JSON Data',
14
+ width: '800px',
15
+ height: '600px',
16
+ closable: true,
17
+ backdrop: true,
18
+ expandAll: false,
19
+ searchEnabled: true,
20
+ copyEnabled: true,
21
+ theme: 'light',
22
+ });
23
+
24
+ /**
25
+ * Create backdrop element
26
+ * @returns {HTMLDivElement} Backdrop element
27
+ */
28
+ const createBackdropElement = () => {
29
+ const backdrop = document.createElement('div');
30
+ backdrop.style.position = 'fixed';
31
+ backdrop.style.top = '0';
32
+ backdrop.style.left = '0';
33
+ backdrop.style.width = '100%';
34
+ backdrop.style.height = '100%';
35
+ backdrop.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
36
+ backdrop.style.zIndex = '999';
37
+ return backdrop;
38
+ };
39
+
40
+ /**
41
+ * Format JSON with proper indentation
42
+ * @param {*} data - Data to format
43
+ * @returns {string} Formatted JSON string
44
+ */
45
+ const formatJsonData = (data) => {
46
+ return JSON.stringify(data, null, 2);
47
+ };
48
+
49
+ /**
50
+ * Apply syntax highlighting to JSON string
51
+ * @param {string} jsonString - JSON string to highlight
52
+ * @returns {string} Highlighted HTML string
53
+ */
54
+ const highlightJsonSyntax = (jsonString) => {
55
+ return jsonString
56
+ .replaceAll(/"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/g, (match) => {
57
+ if (/:$/.test(match)) {
58
+ return `<span class="json-key">${match}</span>`;
59
+ } else {
60
+ return `<span class="json-string">${match}</span>`;
61
+ }
62
+ })
63
+ .replaceAll(/\b(true|false)\b/g, '<span class="json-boolean">$1</span>')
64
+ .replaceAll(/\bnull\b/g, '<span class="json-null">$&</span>')
65
+ .replaceAll(/-?\d+(?:\.\d*)?(?:[eE[+-]?\d+)?/g, '<span class="json-number">$&</span>');
66
+ };
67
+
68
+ /**
69
+ * Create modal header element
70
+ * @param {Object} config - Configuration object
71
+ * @param {Function} onClose - Close handler
72
+ * @param {Function} onCopy - Copy handler
73
+ * @returns {HTMLDivElement} Modal header element
74
+ */
75
+ const createModalHeader = (config, onClose, onCopy) => {
76
+ const modalHeader = document.createElement('div');
77
+ modalHeader.className = 'modal-header';
78
+ modalHeader.style.padding = '16px 20px';
79
+ modalHeader.style.borderBottom = '1px solid #e5e7eb';
80
+ modalHeader.style.display = 'flex';
81
+ modalHeader.style.justifyContent = 'space-between';
82
+ modalHeader.style.alignItems = 'center';
83
+
84
+ const title = document.createElement('h3');
85
+ title.textContent = config.title;
86
+ title.style.margin = '0';
87
+ title.style.fontSize = '18px';
88
+ title.style.fontWeight = '600';
89
+
90
+ const headerActions = document.createElement('div');
91
+ headerActions.style.display = 'flex';
92
+ headerActions.style.gap = '8px';
93
+
94
+ if (config.copyEnabled) {
95
+ const copyBtn = document.createElement('button');
96
+ copyBtn.textContent = 'Copy';
97
+ copyBtn.className = 'btn btn-sm btn-secondary';
98
+ copyBtn.addEventListener('click', onCopy);
99
+ headerActions.appendChild(copyBtn);
100
+ }
101
+
102
+ if (config.closable) {
103
+ const closeBtn = document.createElement('button');
104
+ closeBtn.textContent = '×';
105
+ closeBtn.className = 'btn btn-sm btn-secondary';
106
+ closeBtn.addEventListener('click', onClose);
107
+ headerActions.appendChild(closeBtn);
108
+ }
109
+
110
+ modalHeader.appendChild(title);
111
+ modalHeader.appendChild(headerActions);
112
+
113
+ return modalHeader;
114
+ };
115
+
116
+ /**
117
+ * Create modal body element
118
+ * @param {Object} config - Configuration object
119
+ * @param {Function} onSearch - Search handler
120
+ * @returns {HTMLDivElement} Modal body element
121
+ */
122
+ const createModalBody = (config, onSearch) => {
123
+ const modalBody = document.createElement('div');
124
+ modalBody.className = 'modal-body';
125
+ modalBody.style.padding = '16px';
126
+ modalBody.style.flex = '1';
127
+ modalBody.style.overflow = 'hidden';
128
+ modalBody.style.display = 'flex';
129
+ modalBody.style.flexDirection = 'column';
130
+
131
+ if (config.searchEnabled) {
132
+ const searchContainer = document.createElement('div');
133
+ searchContainer.style.marginBottom = '16px';
134
+
135
+ const searchInput = document.createElement('input');
136
+ searchInput.type = 'text';
137
+ searchInput.placeholder = 'Search JSON...';
138
+ searchInput.className = 'search-input';
139
+ searchInput.style.width = '100%';
140
+ searchInput.style.padding = '8px 12px';
141
+ searchInput.style.border = '1px solid #d1d5db';
142
+ searchInput.style.borderRadius = '4px';
143
+ searchInput.addEventListener('input', onSearch);
144
+
145
+ searchContainer.appendChild(searchInput);
146
+ modalBody.appendChild(searchContainer);
147
+ }
148
+
149
+ const jsonContainer = document.createElement('div');
150
+ jsonContainer.className = 'json-container';
151
+ jsonContainer.style.fontFamily = 'Monaco, Menlo, "Ubuntu Mono", monospace';
152
+ jsonContainer.style.fontSize = '14px';
153
+ jsonContainer.style.lineHeight = '1.5';
154
+ jsonContainer.style.whiteSpace = 'pre-wrap';
155
+ jsonContainer.style.overflow = 'auto';
156
+
157
+ modalBody.appendChild(jsonContainer);
158
+
159
+ return modalBody;
160
+ };
161
+
162
+ /**
163
+ * Create modal element
164
+ * @param {Object} config - Configuration object
165
+ * @param {Function} onClose - Close handler
166
+ * @param {Function} onCopy - Copy handler
167
+ * @param {Function} onSearch - Search handler
168
+ * @returns {HTMLDivElement} Modal element
169
+ */
170
+ const createModalElement = (config, onClose, onCopy, onSearch) => {
171
+ const modal = document.createElement('div');
172
+ modal.className = `json-viewer-modal json-viewer-${config.theme}`;
173
+ modal.style.display = 'none';
174
+ modal.style.position = 'fixed';
175
+ modal.style.top = '0';
176
+ modal.style.left = '0';
177
+ modal.style.width = '100%';
178
+ modal.style.height = '100%';
179
+ modal.style.zIndex = '1000';
180
+
181
+ const modalContent = document.createElement('div');
182
+ modalContent.className = 'modal-content';
183
+ modalContent.style.position = 'relative';
184
+ modalContent.style.backgroundColor = '#fff';
185
+ modalContent.style.width = config.width;
186
+ modalContent.style.height = config.height;
187
+ modalContent.style.margin = '50px auto';
188
+ modalContent.style.borderRadius = '8px';
189
+ modalContent.style.boxShadow = '0 4px 20px rgba(0,0,0,0.15)';
190
+
191
+ const modalHeader = createModalHeader(config, onClose, onCopy);
192
+ const modalBody = createModalBody(config, onSearch);
193
+
194
+ modalContent.appendChild(modalHeader);
195
+ modalContent.appendChild(modalBody);
196
+ modal.appendChild(modalContent);
197
+
198
+ return modal;
199
+ };
200
+
201
+ // Global timeout registry for proper cleanup
202
+ const activeTimeouts = new Set();
203
+
204
+ /**
205
+ * Create notification element with proper timeout management
206
+ * @param {string} message - Notification message
207
+ * @param {string} type - Notification type ('success', 'error', 'info')
208
+ * @returns {number} Timeout reference for cleanup
209
+ */
210
+ const showNotification = (message, type = 'info') => {
211
+ const notification = document.createElement('div');
212
+ notification.textContent = message;
213
+ notification.style.position = 'fixed';
214
+ notification.style.top = '20px';
215
+ notification.style.right = '20px';
216
+ notification.style.padding = '12px 16px';
217
+ notification.style.borderRadius = '4px';
218
+ notification.style.zIndex = '2000';
219
+
220
+ if (type === 'success') {
221
+ notification.style.backgroundColor = '#10b981';
222
+ notification.style.color = 'white';
223
+ } else if (type === 'error') {
224
+ notification.style.backgroundColor = '#ef4444';
225
+ notification.style.color = 'white';
226
+ } else {
227
+ notification.style.backgroundColor = '#3b82f6';
228
+ notification.style.color = 'white';
229
+ }
230
+
231
+ document.body.appendChild(notification);
232
+
233
+ const timeoutId = setTimeout(() => {
234
+ notification.remove();
235
+ activeTimeouts.delete(timeoutId); // Clean up from registry
236
+ }, 3000);
237
+
238
+ activeTimeouts.add(timeoutId); // Track timeout for cleanup
239
+ return timeoutId;
240
+ };
241
+
242
+ /**
243
+ * Clear all active notification timeouts
244
+ * @returns {void}
245
+ */
246
+ const clearAllNotifications = () => {
247
+ activeTimeouts.forEach((timeoutId) => {
248
+ clearTimeout(timeoutId);
249
+ });
250
+ activeTimeouts.clear();
251
+ };
252
+
253
+ /**
254
+ * Create search handler for JSON viewer
255
+ * @param {HTMLElement} element - Modal element
256
+ * @param {Function} renderJson - Render function
257
+ * @returns {Function} Search handler function
258
+ */
259
+ const createSearchHandler = (element, renderJson) => {
260
+ return (event) => {
261
+ const searchTerm = event.target.value.toLowerCase();
262
+ const jsonContainer = element.querySelector('.json-container');
263
+
264
+ if (searchTerm) {
265
+ const regex = new RegExp(`(${searchTerm})`, 'gi');
266
+ jsonContainer.innerHTML = jsonContainer.innerHTML.replace(regex, '<mark>$1</mark>');
267
+ } else {
268
+ renderJson();
269
+ }
270
+ };
271
+ };
272
+
273
+ /**
274
+ * Create JSON viewer lifecycle functions
275
+ * @param {Object} config - Configuration object
276
+ * @param {*} initialData - Initial JSON data
277
+ * @returns {Object} Lifecycle functions
278
+ */
279
+ const createViewerLifecycle = (config, initialData) => {
280
+ let element;
281
+ let backdrop;
282
+ let isOpen = false;
283
+ let currentData = initialData;
284
+
285
+ const copyToClipboard = () => {
286
+ if (currentData) {
287
+ const jsonString = formatJsonData(currentData);
288
+ navigator.clipboard
289
+ .writeText(jsonString)
290
+ .then(() => {
291
+ showNotification('JSON copied to clipboard', 'success');
292
+ })
293
+ .catch(() => {
294
+ showNotification('Failed to copy JSON', 'error');
295
+ });
296
+ }
297
+ };
298
+
299
+ const renderJson = () => {
300
+ const jsonContainer = element.querySelector('.json-container');
301
+ if (currentData) {
302
+ const formattedJson = formatJsonData(currentData);
303
+ const highlightedJson = highlightJsonSyntax(formattedJson);
304
+ jsonContainer.innerHTML = highlightedJson;
305
+ }
306
+ };
307
+
308
+ const handleSearch = createSearchHandler(element, renderJson);
309
+
310
+ const open = (data) => {
311
+ currentData = data;
312
+ isOpen = true;
313
+
314
+ if (!element) {
315
+ element = createModalElement(config, close, copyToClipboard, handleSearch);
316
+ }
317
+
318
+ if (!backdrop && config.backdrop) {
319
+ backdrop = createBackdropElement();
320
+ }
321
+
322
+ renderJson();
323
+
324
+ if (backdrop) {
325
+ document.body.appendChild(backdrop);
326
+ }
327
+ document.body.appendChild(element);
328
+
329
+ element.style.display = 'block';
330
+ };
331
+
332
+ const close = () => {
333
+ if (isOpen) {
334
+ isOpen = false;
335
+
336
+ if (element) {
337
+ element.style.display = 'none';
338
+ element.remove();
339
+ }
340
+
341
+ if (backdrop) {
342
+ backdrop.remove();
343
+ }
344
+
345
+ currentData = null;
346
+ }
347
+ };
348
+
349
+ const destroy = () => {
350
+ close();
351
+ // Clear all active notification timeouts to prevent memory leaks
352
+ clearAllNotifications();
353
+ element = null;
354
+ backdrop = null;
355
+ };
356
+
357
+ return {
358
+ open,
359
+ close,
360
+ destroy,
361
+ /** @returns {boolean} Whether the modal is currently open */
362
+ isOpen: () => isOpen,
363
+ };
364
+ };
365
+
366
+ /**
367
+ * Create a JSON viewer modal
368
+ */
369
+ const createJsonViewer = (options = {}) => {
370
+ const currentData = null;
371
+ const config = { ...getDefaultOptions(), ...options };
372
+
373
+ const lifecycle = createViewerLifecycle(config, currentData);
374
+
375
+ return {
376
+ ...lifecycle,
377
+ /** @returns {boolean} Whether the modal is currently open */
378
+ isOpen: lifecycle.isOpen,
379
+ };
380
+ };
381
+
382
+ /**
383
+ * Sealed namespace for JsonViewer utilities
384
+ */
385
+ export const JsonViewer = Object.freeze({
386
+ create: createJsonViewer,
387
+ });
@@ -0,0 +1,178 @@
1
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
2
+ /* eslint-disable no-undef */
3
+ /**
4
+ * Worker Card Component
5
+ * Handles worker display with expand/collapse functionality
6
+ */
7
+
8
+ /**
9
+ * Create worker header element
10
+ * @param {Object} worker - Worker data
11
+ * @returns {HTMLDivElement} Header element
12
+ */
13
+ const createWorkerHeader = (worker) => {
14
+ const header = document.createElement('div');
15
+ header.className = 'worker-header';
16
+
17
+ const info = document.createElement('div');
18
+ info.className = 'worker-info';
19
+
20
+ const name = document.createElement('h3');
21
+ name.className = 'worker-name';
22
+ name.textContent = worker.name;
23
+
24
+ const status = document.createElement('span');
25
+ status.className = `worker-status status-${worker.status}`;
26
+ status.textContent = worker.status;
27
+
28
+ const queue = document.createElement('span');
29
+ queue.className = 'worker-queue';
30
+ queue.textContent = worker.queueName;
31
+
32
+ info.appendChild(name);
33
+ info.appendChild(status);
34
+ info.appendChild(queue);
35
+
36
+ const actions = document.createElement('div');
37
+ actions.className = 'worker-actions';
38
+
39
+ const expandBtn = document.createElement('button');
40
+ expandBtn.className = 'expand-btn';
41
+ expandBtn.dataset.workerId = worker.id;
42
+
43
+ const icon = document.createElement('i');
44
+ icon.className = 'fas fa-chevron-down';
45
+ expandBtn.appendChild(icon);
46
+
47
+ actions.appendChild(expandBtn);
48
+ header.appendChild(info);
49
+ header.appendChild(actions);
50
+
51
+ return header;
52
+ };
53
+
54
+ /**
55
+ * Create worker expand content element
56
+ * @param {Object} worker - Worker data
57
+ * @returns {HTMLDivElement} Expand content element
58
+ */
59
+ const createWorkerExpandContent = (worker) => {
60
+ const expandContent = document.createElement('div');
61
+ expandContent.className = 'worker-expand-content';
62
+ expandContent.id = `expand-${worker.id}`;
63
+ expandContent.style.display = 'none';
64
+ return expandContent;
65
+ };
66
+
67
+ /**
68
+ * Create worker card element
69
+ * @param {Object} worker - Worker data
70
+ * @returns {HTMLDivElement} Worker card element
71
+ */
72
+ const createWorkerElement = (worker) => {
73
+ const workerElement = document.createElement('div');
74
+ workerElement.className = 'worker-card';
75
+
76
+ const header = createWorkerHeader(worker);
77
+ const expandContent = createWorkerExpandContent(worker);
78
+
79
+ workerElement.appendChild(header);
80
+ workerElement.appendChild(expandContent);
81
+
82
+ return workerElement;
83
+ };
84
+
85
+ /**
86
+ * Create event handlers for worker card
87
+ * @param {Object} worker - Worker data
88
+ * @param {Function} toggleExpand - Toggle expand function
89
+ * @returns {Function} Event attachment function
90
+ */
91
+ const createEventHandlers = (worker, toggleExpand) => {
92
+ return () => {
93
+ const expandBtn = document.querySelector(`[data-worker-id="${worker.id}"]`);
94
+
95
+ if (expandBtn) {
96
+ expandBtn.addEventListener('click', (e) => {
97
+ e.stopPropagation();
98
+ toggleExpand();
99
+ });
100
+ }
101
+ };
102
+ };
103
+
104
+ /**
105
+ * Create a worker card element with expand/collapse functionality
106
+ */
107
+ const createWorkerCard = (worker, container) => {
108
+ let isExpanded = false;
109
+ let expandPanel = null;
110
+ let element;
111
+
112
+ const toggleExpand = () => {
113
+ isExpanded = !isExpanded;
114
+ const expandContent = element.querySelector('.worker-expand-content');
115
+ const expandBtn = element.querySelector('.expand-btn i');
116
+
117
+ if (isExpanded) {
118
+ expandContent.style.display = 'block';
119
+ expandBtn.className = 'fas fa-chevron-up';
120
+ renderExpandPanel();
121
+ } else {
122
+ expandContent.style.display = 'none';
123
+ expandBtn.className = 'fas fa-chevron-down';
124
+ }
125
+ };
126
+
127
+ const renderExpandPanel = () => {
128
+ const expandContent = element.querySelector('.worker-expand-content');
129
+
130
+ if (!expandPanel) {
131
+ expandPanel = WorkerExpandPanel.create(worker, expandContent);
132
+ }
133
+
134
+ expandPanel.render();
135
+ };
136
+
137
+ const updateWorker = (updatedWorker) => {
138
+ Object.assign(worker, updatedWorker);
139
+ render();
140
+ };
141
+
142
+ const attachEventListeners = createEventHandlers(worker, toggleExpand);
143
+
144
+ const render = () => {
145
+ if (element) {
146
+ element.remove();
147
+ }
148
+ element = createWorkerElement(worker);
149
+ container.appendChild(element);
150
+ attachEventListeners();
151
+ };
152
+
153
+ const destroy = () => {
154
+ if (expandPanel) {
155
+ expandPanel.destroy();
156
+ }
157
+ element.remove();
158
+ };
159
+
160
+ // Initialize
161
+ render();
162
+
163
+ return {
164
+ element,
165
+ worker,
166
+ isExpanded: () => isExpanded,
167
+ toggleExpand,
168
+ updateWorker,
169
+ destroy,
170
+ };
171
+ };
172
+
173
+ /**
174
+ * Sealed namespace for WorkerCard utilities
175
+ */
176
+ export const WorkerCard = Object.freeze({
177
+ create: createWorkerCard,
178
+ });