@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.
- package/README.md +861 -0
- package/dist/AnomalyDetection.d.ts +102 -0
- package/dist/AnomalyDetection.js +321 -0
- package/dist/AutoScaler.d.ts +127 -0
- package/dist/AutoScaler.js +425 -0
- package/dist/BroadcastWorker.d.ts +21 -0
- package/dist/BroadcastWorker.js +24 -0
- package/dist/CanaryController.d.ts +103 -0
- package/dist/CanaryController.js +380 -0
- package/dist/ChaosEngineering.d.ts +79 -0
- package/dist/ChaosEngineering.js +216 -0
- package/dist/CircuitBreaker.d.ts +106 -0
- package/dist/CircuitBreaker.js +374 -0
- package/dist/ClusterLock.d.ts +90 -0
- package/dist/ClusterLock.js +385 -0
- package/dist/ComplianceManager.d.ts +177 -0
- package/dist/ComplianceManager.js +556 -0
- package/dist/DatacenterOrchestrator.d.ts +133 -0
- package/dist/DatacenterOrchestrator.js +404 -0
- package/dist/DeadLetterQueue.d.ts +122 -0
- package/dist/DeadLetterQueue.js +539 -0
- package/dist/HealthMonitor.d.ts +42 -0
- package/dist/HealthMonitor.js +301 -0
- package/dist/MultiQueueWorker.d.ts +89 -0
- package/dist/MultiQueueWorker.js +277 -0
- package/dist/NotificationWorker.d.ts +21 -0
- package/dist/NotificationWorker.js +23 -0
- package/dist/Observability.d.ts +153 -0
- package/dist/Observability.js +530 -0
- package/dist/PluginManager.d.ts +123 -0
- package/dist/PluginManager.js +392 -0
- package/dist/PriorityQueue.d.ts +117 -0
- package/dist/PriorityQueue.js +244 -0
- package/dist/ResourceMonitor.d.ts +164 -0
- package/dist/ResourceMonitor.js +605 -0
- package/dist/SLAMonitor.d.ts +110 -0
- package/dist/SLAMonitor.js +274 -0
- package/dist/WorkerFactory.d.ts +193 -0
- package/dist/WorkerFactory.js +1507 -0
- package/dist/WorkerInit.d.ts +85 -0
- package/dist/WorkerInit.js +223 -0
- package/dist/WorkerMetrics.d.ts +114 -0
- package/dist/WorkerMetrics.js +509 -0
- package/dist/WorkerRegistry.d.ts +145 -0
- package/dist/WorkerRegistry.js +319 -0
- package/dist/WorkerShutdown.d.ts +61 -0
- package/dist/WorkerShutdown.js +159 -0
- package/dist/WorkerVersioning.d.ts +107 -0
- package/dist/WorkerVersioning.js +300 -0
- package/dist/build-manifest.json +462 -0
- package/dist/config/workerConfig.d.ts +3 -0
- package/dist/config/workerConfig.js +19 -0
- package/dist/createQueueWorker.d.ts +23 -0
- package/dist/createQueueWorker.js +113 -0
- package/dist/dashboard/index.d.ts +1 -0
- package/dist/dashboard/index.js +1 -0
- package/dist/dashboard/types.d.ts +117 -0
- package/dist/dashboard/types.js +1 -0
- package/dist/dashboard/workers-api.d.ts +4 -0
- package/dist/dashboard/workers-api.js +638 -0
- package/dist/dashboard/workers-dashboard-ui.d.ts +3 -0
- package/dist/dashboard/workers-dashboard-ui.js +1026 -0
- package/dist/dashboard/workers-dashboard.d.ts +4 -0
- package/dist/dashboard/workers-dashboard.js +904 -0
- package/dist/helper/index.d.ts +5 -0
- package/dist/helper/index.js +10 -0
- package/dist/http/WorkerApiController.d.ts +38 -0
- package/dist/http/WorkerApiController.js +312 -0
- package/dist/http/WorkerController.d.ts +374 -0
- package/dist/http/WorkerController.js +1351 -0
- package/dist/http/middleware/CustomValidation.d.ts +92 -0
- package/dist/http/middleware/CustomValidation.js +270 -0
- package/dist/http/middleware/DatacenterValidator.d.ts +3 -0
- package/dist/http/middleware/DatacenterValidator.js +94 -0
- package/dist/http/middleware/EditWorkerValidation.d.ts +7 -0
- package/dist/http/middleware/EditWorkerValidation.js +55 -0
- package/dist/http/middleware/FeaturesValidator.d.ts +3 -0
- package/dist/http/middleware/FeaturesValidator.js +60 -0
- package/dist/http/middleware/InfrastructureValidator.d.ts +31 -0
- package/dist/http/middleware/InfrastructureValidator.js +226 -0
- package/dist/http/middleware/OptionsValidator.d.ts +3 -0
- package/dist/http/middleware/OptionsValidator.js +112 -0
- package/dist/http/middleware/PayloadSanitizer.d.ts +7 -0
- package/dist/http/middleware/PayloadSanitizer.js +42 -0
- package/dist/http/middleware/ProcessorPathSanitizer.d.ts +3 -0
- package/dist/http/middleware/ProcessorPathSanitizer.js +74 -0
- package/dist/http/middleware/QueueNameSanitizer.d.ts +3 -0
- package/dist/http/middleware/QueueNameSanitizer.js +45 -0
- package/dist/http/middleware/ValidateDriver.d.ts +7 -0
- package/dist/http/middleware/ValidateDriver.js +20 -0
- package/dist/http/middleware/VersionSanitizer.d.ts +3 -0
- package/dist/http/middleware/VersionSanitizer.js +25 -0
- package/dist/http/middleware/WorkerNameSanitizer.d.ts +3 -0
- package/dist/http/middleware/WorkerNameSanitizer.js +46 -0
- package/dist/http/middleware/WorkerValidationChain.d.ts +27 -0
- package/dist/http/middleware/WorkerValidationChain.js +185 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +48 -0
- package/dist/routes/workers.d.ts +12 -0
- package/dist/routes/workers.js +81 -0
- package/dist/storage/WorkerStore.d.ts +45 -0
- package/dist/storage/WorkerStore.js +195 -0
- package/dist/type.d.ts +76 -0
- package/dist/type.js +1 -0
- package/dist/ui/router/ui.d.ts +3 -0
- package/dist/ui/router/ui.js +83 -0
- package/dist/ui/types/worker-ui.d.ts +229 -0
- package/dist/ui/types/worker-ui.js +5 -0
- package/package.json +53 -0
- package/src/AnomalyDetection.ts +434 -0
- package/src/AutoScaler.ts +654 -0
- package/src/BroadcastWorker.ts +34 -0
- package/src/CanaryController.ts +531 -0
- package/src/ChaosEngineering.ts +301 -0
- package/src/CircuitBreaker.ts +495 -0
- package/src/ClusterLock.ts +499 -0
- package/src/ComplianceManager.ts +815 -0
- package/src/DatacenterOrchestrator.ts +561 -0
- package/src/DeadLetterQueue.ts +733 -0
- package/src/HealthMonitor.ts +390 -0
- package/src/MultiQueueWorker.ts +431 -0
- package/src/NotificationWorker.ts +33 -0
- package/src/Observability.ts +696 -0
- package/src/PluginManager.ts +551 -0
- package/src/PriorityQueue.ts +351 -0
- package/src/ResourceMonitor.ts +769 -0
- package/src/SLAMonitor.ts +408 -0
- package/src/WorkerFactory.ts +2108 -0
- package/src/WorkerInit.ts +313 -0
- package/src/WorkerMetrics.ts +709 -0
- package/src/WorkerRegistry.ts +443 -0
- package/src/WorkerShutdown.ts +210 -0
- package/src/WorkerVersioning.ts +422 -0
- package/src/config/workerConfig.ts +25 -0
- package/src/createQueueWorker.ts +174 -0
- package/src/dashboard/index.ts +6 -0
- package/src/dashboard/types.ts +141 -0
- package/src/dashboard/workers-api.ts +785 -0
- package/src/dashboard/zintrust.svg +30 -0
- package/src/helper/index.ts +11 -0
- package/src/http/WorkerApiController.ts +369 -0
- package/src/http/WorkerController.ts +1512 -0
- package/src/http/middleware/CustomValidation.ts +360 -0
- package/src/http/middleware/DatacenterValidator.ts +124 -0
- package/src/http/middleware/EditWorkerValidation.ts +74 -0
- package/src/http/middleware/FeaturesValidator.ts +82 -0
- package/src/http/middleware/InfrastructureValidator.ts +295 -0
- package/src/http/middleware/OptionsValidator.ts +144 -0
- package/src/http/middleware/PayloadSanitizer.ts +52 -0
- package/src/http/middleware/ProcessorPathSanitizer.ts +86 -0
- package/src/http/middleware/QueueNameSanitizer.ts +55 -0
- package/src/http/middleware/ValidateDriver.ts +29 -0
- package/src/http/middleware/VersionSanitizer.ts +30 -0
- package/src/http/middleware/WorkerNameSanitizer.ts +56 -0
- package/src/http/middleware/WorkerValidationChain.ts +230 -0
- package/src/index.ts +98 -0
- package/src/routes/workers.ts +154 -0
- package/src/storage/WorkerStore.ts +240 -0
- package/src/type.ts +89 -0
- package/src/types/queue-monitor.d.ts +38 -0
- package/src/types/queue-redis.d.ts +38 -0
- package/src/ui/README.md +13 -0
- package/src/ui/components/JsonEditor.js +670 -0
- package/src/ui/components/JsonViewer.js +387 -0
- package/src/ui/components/WorkerCard.js +178 -0
- package/src/ui/components/WorkerExpandPanel.js +257 -0
- package/src/ui/components/fetcher.js +42 -0
- package/src/ui/components/sla-scorecard.js +32 -0
- package/src/ui/components/styles.css +30 -0
- package/src/ui/components/table-expander.js +34 -0
- package/src/ui/integration/worker-ui-integration.js +565 -0
- package/src/ui/router/ui.ts +99 -0
- package/src/ui/services/workerApi.js +240 -0
- package/src/ui/types/worker-ui.ts +283 -0
- package/src/ui/utils/jsonValidator.js +444 -0
- package/src/ui/workers/index.html +202 -0
- package/src/ui/workers/main.js +1781 -0
- 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
|
+
});
|