@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,565 @@
1
+ /* eslint-disable no-console */
2
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
3
+ /* eslint-disable no-restricted-imports */
4
+ /* eslint-disable no-undef */
5
+ /**
6
+ * Worker UI Integration
7
+ * Integrates new WorkerCard components with existing main.js
8
+ */
9
+
10
+ // Import the new components
11
+ import { WorkerCard } from '../components/WorkerCard.js';
12
+ import { WorkerExpandPanel } from '../components/WorkerExpandPanel.js';
13
+
14
+ /**
15
+ * Enhanced worker rendering using new components
16
+ */
17
+ function renderWorkersEnhanced(data) {
18
+ const tbody = document.getElementById('workers-tbody');
19
+ if (!tbody) return;
20
+
21
+ // Clear existing content safely
22
+ while (tbody.firstChild) {
23
+ tbody.firstChild.remove();
24
+ }
25
+
26
+ if (!data.workers || data.workers.length === 0) {
27
+ const noWorkersRow = document.createElement('tr');
28
+ const noWorkersCell = document.createElement('td');
29
+ noWorkersCell.colSpan = '7';
30
+ noWorkersCell.className = 'text-center p-4';
31
+ noWorkersCell.textContent = 'No workers found';
32
+ noWorkersRow.appendChild(noWorkersCell);
33
+ tbody.appendChild(noWorkersRow);
34
+
35
+ updateQueueSummary(data.queueData);
36
+ updateDriverFilter(data.drivers);
37
+ updateDriversList(data.drivers);
38
+ updatePagination(data.pagination);
39
+ return;
40
+ }
41
+
42
+ // Create a container for our new worker cards
43
+ const cardsContainer = document.createElement('div');
44
+ cardsContainer.className = 'workers-cards-container';
45
+ cardsContainer.style.cssText = `
46
+ display: grid;
47
+ gap: 16px;
48
+ padding: 16px;
49
+ `;
50
+
51
+ data.workers.forEach((worker) => {
52
+ // Create a table row that contains the worker card
53
+ const row = document.createElement('tr');
54
+ const cell = document.createElement('td');
55
+ cell.colSpan = '7';
56
+ cell.style.padding = '0';
57
+
58
+ // Create worker card container
59
+ const cardContainer = document.createElement('div');
60
+ cardContainer.className = 'worker-card-wrapper';
61
+
62
+ // Ensure worker has an ID for the expand functionality
63
+ if (!worker.id) {
64
+ worker.id = worker.name.replaceAll(/[^a-z0-9]/gi, '-');
65
+ }
66
+
67
+ // Initialize the new WorkerCard component
68
+ WorkerCard.create(worker, cardContainer);
69
+
70
+ cell.appendChild(cardContainer);
71
+ row.appendChild(cell);
72
+ tbody.appendChild(row);
73
+
74
+ // Create expandable detail row for this worker
75
+ const detailsId = `details-${worker.id}`;
76
+ const detailRow = createDetailRowEnhanced(worker, detailsId);
77
+ tbody.appendChild(detailRow);
78
+
79
+ // Connect the WorkerCard expand button to the table row toggle
80
+ // Use a more reliable approach without setTimeout
81
+ const observer = new MutationObserver(() => {
82
+ const expandBtn = cardContainer.querySelector('.expand-btn');
83
+ if (expandBtn && !expandBtn.hasAttribute('data-connected')) {
84
+ expandBtn.setAttribute('data-connected', 'true');
85
+ expandBtn.addEventListener('click', (e) => {
86
+ e.stopPropagation();
87
+ // Toggle the detail row instead of internal expand
88
+ globalThis.window.toggleDetails(detailsId);
89
+ });
90
+ observer.disconnect(); // Clean up observer
91
+ }
92
+ });
93
+
94
+ observer.observe(cardContainer, { childList: true, subtree: true });
95
+
96
+ // Fallback: try immediately in case the button already exists
97
+ const expandBtn = cardContainer.querySelector('.expand-btn');
98
+ if (expandBtn && !expandBtn.hasAttribute('data-connected')) {
99
+ expandBtn.setAttribute('data-connected', 'true');
100
+ expandBtn.addEventListener('click', (e) => {
101
+ e.stopPropagation();
102
+ globalThis.window.toggleDetails(detailsId);
103
+ });
104
+ observer.disconnect();
105
+ }
106
+ });
107
+
108
+ updateQueueSummary(data.queueData);
109
+ updateDriverFilter(data.drivers);
110
+ updateDriversList(data.drivers);
111
+ updatePagination(data.pagination);
112
+ }
113
+
114
+ /**
115
+ * Enhanced detail row with new components
116
+ */
117
+ function createDetailRowEnhanced(worker, detailsId) {
118
+ const detailRow = document.createElement('tr');
119
+ detailRow.id = `details-${detailsId}`;
120
+ detailRow.className = 'expandable-row';
121
+ detailRow.style.display = 'none';
122
+
123
+ const detailCell = document.createElement('td');
124
+ detailCell.colSpan = '7';
125
+ detailCell.style.padding = '0';
126
+ detailCell.style.backgroundColor = '#f8f9fa';
127
+
128
+ // Create enhanced detail panel container
129
+ const detailPanelContainer = document.createElement('div');
130
+ detailPanelContainer.className = 'detail-panel-container';
131
+ detailPanelContainer.style.cssText = `
132
+ padding: 20px;
133
+ min-height: 200px;
134
+ `;
135
+
136
+ // Initialize the new WorkerExpandPanel component
137
+ WorkerExpandPanel.create(worker, detailPanelContainer);
138
+
139
+ detailCell.appendChild(detailPanelContainer);
140
+ detailRow.appendChild(detailCell);
141
+
142
+ return detailRow;
143
+ }
144
+
145
+ /**
146
+ * Enhanced worker row with new styling
147
+ */
148
+ function createWorkerRowEnhanced(worker) {
149
+ const row = document.createElement('tr');
150
+ const detailsId = worker.name.replaceAll(/[^a-z0-9]/gi, '-');
151
+
152
+ // Status cell with enhanced styling
153
+ const statusCell = document.createElement('td');
154
+ const statusBadge = document.createElement('span');
155
+ statusBadge.className = `status-badge status-${worker.status}`;
156
+ statusBadge.textContent = worker.status;
157
+ statusBadge.style.cssText = `
158
+ padding: 4px 8px;
159
+ border-radius: 12px;
160
+ font-size: 12px;
161
+ font-weight: 500;
162
+ text-transform: uppercase;
163
+ `;
164
+ statusCell.appendChild(statusBadge);
165
+
166
+ // Name cell
167
+ const nameCell = document.createElement('td');
168
+ nameCell.textContent = worker.name;
169
+ nameCell.style.fontWeight = '500';
170
+
171
+ // Queue cell
172
+ const queueCell = document.createElement('td');
173
+ queueCell.textContent = worker.queueName;
174
+
175
+ // Driver cell
176
+ const driverCell = document.createElement('td');
177
+ driverCell.textContent = worker.driver;
178
+
179
+ // Concurrency cell
180
+ const concurrencyCell = document.createElement('td');
181
+ concurrencyCell.textContent = worker.concurrency || 1;
182
+
183
+ // Auto-start cell
184
+ const autoStartCell = document.createElement('td');
185
+ const autoStartBadge = document.createElement('span');
186
+ autoStartBadge.className = `badge ${worker.autoStart ? 'badge-success' : 'badge-secondary'}`;
187
+ autoStartBadge.textContent = worker.autoStart ? 'Yes' : 'No';
188
+ autoStartBadge.style.cssText = `
189
+ padding: 2px 6px;
190
+ border-radius: 4px;
191
+ font-size: 11px;
192
+ `;
193
+ autoStartCell.appendChild(autoStartBadge);
194
+
195
+ // Actions cell with expand button
196
+ const actionsCell = document.createElement('td');
197
+ const expandBtn = document.createElement('button');
198
+ expandBtn.className = 'btn btn-sm btn-outline-primary expand-btn';
199
+ expandBtn.style.cssText = `
200
+ padding: 4px 8px;
201
+ font-size: 12px;
202
+ `;
203
+
204
+ // Create icon element safely instead of using innerHTML
205
+ const icon = document.createElement('i');
206
+ icon.className = 'fas fa-chevron-down';
207
+ expandBtn.appendChild(icon);
208
+
209
+ expandBtn.addEventListener('click', () => toggleWorkerDetails(detailsId));
210
+ actionsCell.appendChild(expandBtn);
211
+
212
+ row.appendChild(statusCell);
213
+ row.appendChild(nameCell);
214
+ row.appendChild(queueCell);
215
+ row.appendChild(driverCell);
216
+ row.appendChild(concurrencyCell);
217
+ row.appendChild(autoStartCell);
218
+ row.appendChild(actionsCell);
219
+
220
+ return { row, detailsId };
221
+ }
222
+
223
+ /**
224
+ * Toggle worker details with enhanced animation
225
+ */
226
+ function toggleWorkerDetails(detailsId) {
227
+ const detailRow = document.getElementById(`details-${detailsId}`);
228
+ if (!detailRow) return;
229
+
230
+ const expandBtn =
231
+ document.querySelector(`[onclick*="${detailsId}"]`) || document.querySelector(`.expand-btn`);
232
+
233
+ if (detailRow.style.display === 'none') {
234
+ detailRow.style.display = 'table-row';
235
+ detailRow.classList.add('open');
236
+ if (expandBtn) {
237
+ // Clear existing content safely and add chevron-up icon
238
+ expandBtn.textContent = '';
239
+ const upIcon = document.createElement('i');
240
+ upIcon.className = 'fas fa-chevron-up';
241
+ expandBtn.appendChild(upIcon);
242
+ }
243
+ } else {
244
+ detailRow.style.display = 'none';
245
+ detailRow.classList.remove('open');
246
+ if (expandBtn) {
247
+ // Clear existing content safely and add chevron-down icon
248
+ expandBtn.textContent = '';
249
+ const downIcon = document.createElement('i');
250
+ downIcon.className = 'fas fa-chevron-down';
251
+ expandBtn.appendChild(downIcon);
252
+ }
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Get worker card styles
258
+ */
259
+ function getWorkerCardStyles() {
260
+ return `
261
+ .worker-card {
262
+ border: 1px solid #e5e7eb;
263
+ border-radius: 8px;
264
+ margin-bottom: 8px;
265
+ background: white;
266
+ transition: all 0.2s ease;
267
+ }
268
+
269
+ .worker-card:hover {
270
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
271
+ }
272
+
273
+ .worker-header {
274
+ display: flex;
275
+ justify-content: space-between;
276
+ align-items: center;
277
+ padding: 16px;
278
+ cursor: pointer;
279
+ }
280
+
281
+ .worker-info {
282
+ display: flex;
283
+ align-items: center;
284
+ gap: 12px;
285
+ }
286
+
287
+ .worker-name {
288
+ margin: 0;
289
+ font-size: 16px;
290
+ font-weight: 600;
291
+ }
292
+
293
+ .worker-status {
294
+ padding: 4px 8px;
295
+ border-radius: 12px;
296
+ font-size: 12px;
297
+ font-weight: 500;
298
+ text-transform: uppercase;
299
+ }
300
+
301
+ .status-running { background: #d1fae5; color: #065f46; }
302
+ .status-stopped { background: #fee2e2; color: #991b1b; }
303
+ .status-failed { background: #fef2f2; color: #7f1d1d; }
304
+ .status-paused { background: #fef3c7; color: #92400e; }
305
+ `;
306
+ }
307
+
308
+ /**
309
+ * Get worker actions and expand panel styles
310
+ */
311
+ function getWorkerActionsStyles() {
312
+ return `
313
+ .worker-actions {
314
+ display: flex;
315
+ gap: 8px;
316
+ }
317
+
318
+ .expand-btn {
319
+ background: none;
320
+ border: none;
321
+ cursor: pointer;
322
+ padding: 4px;
323
+ border-radius: 4px;
324
+ transition: transform 0.2s ease;
325
+ }
326
+
327
+ .expand-btn:hover {
328
+ background: #f3f4f6;
329
+ }
330
+
331
+ .expand-btn.expanded {
332
+ transform: rotate(180deg);
333
+ }
334
+
335
+ .worker-expand-panel {
336
+ border-top: 1px solid #e5e7eb;
337
+ background: #f9fafb;
338
+ padding: 16px;
339
+ }
340
+
341
+ .config-summary,
342
+ .worker-metrics {
343
+ margin-bottom: 16px;
344
+ }
345
+
346
+ .config-grid,
347
+ .metrics-grid {
348
+ display: grid;
349
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
350
+ gap: 12px;
351
+ margin-top: 8px;
352
+ }
353
+
354
+ .config-item,
355
+ .metric-item {
356
+ display: flex;
357
+ justify-content: space-between;
358
+ padding: 8px;
359
+ background: white;
360
+ border-radius: 4px;
361
+ border: 1px solid #e5e7eb;
362
+ }
363
+
364
+ .config-label,
365
+ .metric-label {
366
+ font-weight: 500;
367
+ color: #374151;
368
+ }
369
+
370
+ .config-value,
371
+ .metric-value {
372
+ color: #6b7280;
373
+ }
374
+ `;
375
+ }
376
+
377
+ /**
378
+ * Get modal styles for JSON viewer/editor
379
+ */
380
+ function getModalStyles() {
381
+ return `
382
+ .modal-overlay {
383
+ position: fixed;
384
+ top: 0;
385
+ left: 0;
386
+ right: 0;
387
+ bottom: 0;
388
+ background: rgba(0, 0, 0, 0.5);
389
+ display: flex;
390
+ align-items: center;
391
+ justify-content: center;
392
+ z-index: 1000;
393
+ }
394
+
395
+ .modal {
396
+ background: white;
397
+ border-radius: 8px;
398
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
399
+ max-width: 90vw;
400
+ max-height: 90vh;
401
+ overflow: hidden;
402
+ }
403
+
404
+ .modal-header {
405
+ display: flex;
406
+ justify-content: space-between;
407
+ align-items: center;
408
+ padding: 16px;
409
+ border-bottom: 1px solid #e5e7eb;
410
+ }
411
+
412
+ .modal-title {
413
+ margin: 0;
414
+ font-size: 18px;
415
+ font-weight: 600;
416
+ }
417
+
418
+ .modal-body {
419
+ padding: 16px;
420
+ overflow-y: auto;
421
+ }
422
+
423
+ .modal-footer {
424
+ display: flex;
425
+ justify-content: flex-end;
426
+ gap: 8px;
427
+ padding: 16px;
428
+ border-top: 1px solid #e5e7eb;
429
+ }
430
+
431
+ .json-viewer-modal,
432
+ .json-editor-modal {
433
+ font-family: Monaco, Menlo, 'Ubuntu Mono', monospace;
434
+ }
435
+ `;
436
+ }
437
+
438
+ /**
439
+ * Get JSON syntax highlighting styles
440
+ */
441
+ function getJsonHighlightStyles() {
442
+ return `
443
+ .json-string { color: #0d9488; }
444
+ .json-number { color: #2563eb; }
445
+ .json-boolean { color: #dc2626; }
446
+ .json-null { color: #6b7280; }
447
+ .json-key { color: #7c3aed; }
448
+
449
+ mark {
450
+ background: #fef3c7;
451
+ padding: 1px 2px;
452
+ border-radius: 2px;
453
+ }
454
+ `;
455
+ }
456
+
457
+ /**
458
+ * Get button and notification styles
459
+ */
460
+ function getButtonAndNotificationStyles() {
461
+ return `
462
+ .btn {
463
+ padding: 8px 16px;
464
+ border: 1px solid #d1d5db;
465
+ border-radius: 4px;
466
+ background: white;
467
+ cursor: pointer;
468
+ font-size: 14px;
469
+ transition: all 0.2s ease;
470
+ }
471
+
472
+ .btn:hover {
473
+ background: #f9fafb;
474
+ }
475
+
476
+ .btn-primary {
477
+ background: #3b82f6;
478
+ color: white;
479
+ border-color: #3b82f6;
480
+ }
481
+
482
+ .btn-primary:hover {
483
+ background: #2563eb;
484
+ }
485
+
486
+ .btn-secondary {
487
+ background: #6b7280;
488
+ color: white;
489
+ border-color: #6b7280;
490
+ }
491
+
492
+ .btn-secondary:hover {
493
+ background: #4b5563;
494
+ }
495
+
496
+ .btn-sm {
497
+ padding: 4px 8px;
498
+ font-size: 12px;
499
+ }
500
+
501
+ .notification {
502
+ position: fixed;
503
+ top: 20px;
504
+ right: 20px;
505
+ padding: 12px 16px;
506
+ border-radius: 4px;
507
+ z-index: 2000;
508
+ animation: slideIn 0.3s ease;
509
+ }
510
+
511
+ @keyframes slideIn {
512
+ from { transform: translateX(100%); opacity: 0; }
513
+ to { transform: translateX(0); opacity: 1; }
514
+ }
515
+ `;
516
+ }
517
+
518
+ /**
519
+ * Add CSS styles for the enhanced components
520
+ */
521
+ function addEnhancedStyles() {
522
+ const styleId = 'worker-ui-enhanced-styles';
523
+ if (document.getElementById(styleId)) return;
524
+
525
+ const style = document.createElement('style');
526
+ style.id = styleId;
527
+ style.textContent = [
528
+ getWorkerCardStyles(),
529
+ getWorkerActionsStyles(),
530
+ getModalStyles(),
531
+ getJsonHighlightStyles(),
532
+ getButtonAndNotificationStyles(),
533
+ ].join('\n');
534
+
535
+ document.head.appendChild(style);
536
+ }
537
+
538
+ /**
539
+ * Initialize the enhanced UI
540
+ */
541
+ function initializeEnhancedUI() {
542
+ // Add enhanced styles
543
+ addEnhancedStyles();
544
+
545
+ // Override the createDetailRow function
546
+ globalThis.window.createDetailRow = createDetailRowEnhanced;
547
+
548
+ // Override the createWorkerRow function
549
+ globalThis.window.createWorkerRow = createWorkerRowEnhanced;
550
+
551
+ // Make renderWorkersEnhanced globally available
552
+ globalThis.window.renderWorkersEnhanced = renderWorkersEnhanced;
553
+
554
+ console.log('Enhanced Worker UI initialized');
555
+ }
556
+
557
+ // Auto-initialize when DOM is ready
558
+ if (document.readyState === 'loading') {
559
+ document.addEventListener('DOMContentLoaded', initializeEnhancedUI);
560
+ } else {
561
+ initializeEnhancedUI();
562
+ }
563
+
564
+ // Export for manual initialization
565
+ export { initializeEnhancedUI, renderWorkersEnhanced };
@@ -0,0 +1,99 @@
1
+ import type { IRouter } from '@zintrust/core';
2
+ import { Logger, MIME_TYPES, NodeSingletons, Router } from '@zintrust/core';
3
+
4
+ export const uiResolver = async (uiBasePath: string): Promise<string> => {
5
+ // Resolve base path for UI assets
6
+ // const __filename = NodeSingletons.url.fileURLToPath(import.meta.url);
7
+ // const __dirname = NodeSingletons.path.dirname(__filename);
8
+ const uiPath = NodeSingletons.path.resolve(uiBasePath, 'workers/index.html');
9
+ const html = await NodeSingletons.fs.readFile(uiPath, 'utf8');
10
+
11
+ return html;
12
+ };
13
+
14
+ // MIME type mapping for static files
15
+ const getMimeType = (filePath: string): string => {
16
+ const ext = NodeSingletons.path.extname(filePath).toLowerCase();
17
+ const mimeTypes: Record<string, string> = {
18
+ '.css': MIME_TYPES.CSS,
19
+ '.js': MIME_TYPES.JS,
20
+ '.html': MIME_TYPES.HTML,
21
+ '.json': MIME_TYPES.JSON,
22
+ '.png': MIME_TYPES.PNG,
23
+ '.jpg': MIME_TYPES.JPG,
24
+ '.jpeg': MIME_TYPES.JPG,
25
+ '.gif': MIME_TYPES.GIF,
26
+ '.svg': MIME_TYPES.SVG,
27
+ '.ico': MIME_TYPES.ICO,
28
+ '.ipa': MIME_TYPES.IPA,
29
+ };
30
+ return mimeTypes[ext] || MIME_TYPES.IPA;
31
+ };
32
+
33
+ let uiBasePath = '';
34
+ const getUiBase = (): string => {
35
+ // Resolve base path for UI assets
36
+ if (uiBasePath.length > 0) return uiBasePath;
37
+
38
+ const __filename = NodeSingletons.url.fileURLToPath(import.meta.url);
39
+ const __dirname = NodeSingletons.path.dirname(__filename);
40
+ uiBasePath = NodeSingletons.path.resolve(__dirname, '../');
41
+ return uiBasePath;
42
+ };
43
+ const serveStaticFile = async (
44
+ req: { getPath: () => string },
45
+ res: {
46
+ setHeader: (name: string, value: string) => void;
47
+ send: (data: Buffer) => void;
48
+ setStatus: (code: number) => void;
49
+ }
50
+ ): Promise<void> => {
51
+ try {
52
+ const filePath = req.getPath();
53
+ const fullPath = NodeSingletons.path.resolve(getUiBase(), filePath.replace(/^\//, ''));
54
+
55
+ // Security check - prevent directory traversal
56
+ if (!fullPath.startsWith(uiBasePath)) {
57
+ res.setStatus(403);
58
+ res.send(Buffer.from('Forbidden'));
59
+ return;
60
+ }
61
+
62
+ const content = await NodeSingletons.fs.readFile(fullPath);
63
+ const mimeType = getMimeType(filePath);
64
+
65
+ res.setHeader('Content-Type', mimeType);
66
+ res.setHeader('Cache-Control', 'public, max-age=3600'); // 1 hour cache
67
+ res.send(content);
68
+ } catch (err) {
69
+ Logger.warn(`Static file not found: ${req.getPath()}`, err);
70
+ res.setStatus(404);
71
+ res.send(Buffer.from('Not Found'));
72
+ }
73
+ };
74
+
75
+ // Static file serving for workers assets
76
+ export const registerStaticAssets = (router: IRouter, middleware: ReadonlyArray<string>): void => {
77
+ const handler = async (_req: unknown, res: { html: (value: string) => void }): Promise<void> => {
78
+ try {
79
+ const html = await uiResolver(getUiBase());
80
+ res.html(html);
81
+ } catch (err) {
82
+ Logger.error('Failed to load static UI page', err);
83
+ // Fallback to generated dashboard if static file unavailable
84
+ }
85
+ };
86
+
87
+ Router.group(router, '/workers', (r: IRouter) => {
88
+ Router.get(r, '/', handler, { middleware });
89
+ // Serve workers CSS and JS files
90
+ Router.get(r, '/styles.css', serveStaticFile);
91
+ Router.get(r, '/main.js', serveStaticFile);
92
+ Router.get(r, '/:filename', serveStaticFile);
93
+ Router.get(r, '/integration/:filename', serveStaticFile);
94
+
95
+ // Serve components CSS files
96
+ Router.get(r, '/components/styles.css', serveStaticFile);
97
+ Router.get(r, '/components/:filename', serveStaticFile);
98
+ });
99
+ };