@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,670 @@
1
+ /* eslint-disable no-console */
2
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
3
+ /* eslint-disable no-undef */
4
+ /**
5
+ * JSON Editor Modal Component
6
+ * Allows editing JSON data with real-time validation
7
+ */
8
+
9
+ /**
10
+ * Create modal element with header, body, and footer
11
+ * @param {Object} config - Configuration object
12
+ * @param {Function} formatJson - Format JSON function
13
+ * @param {Function} validateJson - Validate JSON function
14
+ * @param {Function} handleSave - Save handler function
15
+ * @param {Function} handleClose - Close handler function
16
+ * @returns {HTMLDivElement} Modal element
17
+ */
18
+ const createModalElement = (config, formatJson, validateJson, handleSave, handleClose) => {
19
+ const modal = document.createElement('div');
20
+ modal.className = `json-editor-modal json-editor-${config.theme}`;
21
+ modal.style.display = 'none';
22
+ modal.style.position = 'fixed';
23
+ modal.style.top = '0';
24
+ modal.style.left = '0';
25
+ modal.style.width = '100%';
26
+ modal.style.height = '100%';
27
+ modal.style.zIndex = '1000';
28
+
29
+ const modalContent = document.createElement('div');
30
+ modalContent.className = 'modal-content';
31
+ modalContent.style.position = 'relative';
32
+ modalContent.style.backgroundColor = '#fff';
33
+ modalContent.style.width = config.width;
34
+ modalContent.style.height = config.height;
35
+ modalContent.style.margin = '30px auto';
36
+ modalContent.style.borderRadius = '8px';
37
+ modalContent.style.boxShadow = '0 4px 20px rgba(0,0,0,0.15)';
38
+ modalContent.style.display = 'flex';
39
+ modalContent.style.flexDirection = 'column';
40
+
41
+ // Create header
42
+ const modalHeader = createModalHeader(config, formatJson, handleClose);
43
+ modalContent.appendChild(modalHeader);
44
+
45
+ // Create body
46
+ const modalBody = createModalBody(config, validateJson);
47
+ modalContent.appendChild(modalBody);
48
+
49
+ // Create footer
50
+ const modalFooter = createModalFooter(handleSave, handleClose);
51
+ modalContent.appendChild(modalFooter);
52
+
53
+ modal.appendChild(modalContent);
54
+ return modal;
55
+ };
56
+
57
+ /**
58
+ * Create modal header with title and actions
59
+ * @param {Object} config - Configuration object
60
+ * @param {Function} formatJson - Format JSON function
61
+ * @param {Function} handleClose - Close handler function
62
+ * @returns {HTMLDivElement} Modal header element
63
+ */
64
+ const createModalHeader = (config, formatJson, handleClose) => {
65
+ const modalHeader = document.createElement('div');
66
+ modalHeader.className = 'modal-header';
67
+ modalHeader.style.padding = '16px 20px';
68
+ modalHeader.style.borderBottom = '1px solid #e5e7eb';
69
+ modalHeader.style.display = 'flex';
70
+ modalHeader.style.justifyContent = 'space-between';
71
+ modalHeader.style.alignItems = 'center';
72
+
73
+ const title = document.createElement('h3');
74
+ title.textContent = config.title;
75
+ title.style.margin = '0';
76
+ title.style.fontSize = '18px';
77
+ title.style.fontWeight = '600';
78
+
79
+ const headerActions = document.createElement('div');
80
+ headerActions.style.display = 'flex';
81
+ headerActions.style.gap = '8px';
82
+
83
+ const formatBtn = document.createElement('button');
84
+ formatBtn.className = 'btn btn-sm btn-secondary format-btn';
85
+
86
+ const formatIcon = document.createElement('i');
87
+ formatIcon.className = 'fas fa-code';
88
+ formatBtn.appendChild(formatIcon);
89
+ formatBtn.appendChild(document.createTextNode(' Format'));
90
+ formatBtn.addEventListener('click', formatJson);
91
+
92
+ const validateBtn = document.createElement('button');
93
+ validateBtn.className = 'btn btn-sm btn-info validate-btn';
94
+
95
+ const validateIcon = document.createElement('i');
96
+ validateIcon.className = 'fas fa-check';
97
+ validateBtn.appendChild(validateIcon);
98
+ validateBtn.appendChild(document.createTextNode(' Validate'));
99
+ validateBtn.addEventListener('click', validateJson);
100
+
101
+ if (config.closable) {
102
+ const closeBtn = document.createElement('button');
103
+ closeBtn.className = 'btn btn-sm btn-secondary close-btn';
104
+
105
+ const closeIcon = document.createElement('i');
106
+ closeIcon.className = 'fas fa-times';
107
+ closeBtn.appendChild(closeIcon);
108
+ closeBtn.addEventListener('click', handleClose);
109
+ headerActions.appendChild(closeBtn);
110
+ }
111
+
112
+ headerActions.appendChild(formatBtn);
113
+ headerActions.appendChild(validateBtn);
114
+
115
+ modalHeader.appendChild(title);
116
+ modalHeader.appendChild(headerActions);
117
+
118
+ return modalHeader;
119
+ };
120
+
121
+ /**
122
+ * Create modal body with textarea and validation container
123
+ * @param {Object} config - Configuration object
124
+ * @param {Function} validateJson - Validate JSON function
125
+ * @returns {HTMLDivElement} Modal body element
126
+ */
127
+ const createModalBody = (config, validateJson) => {
128
+ const modalBody = document.createElement('div');
129
+ modalBody.className = 'modal-body';
130
+ modalBody.style.padding = '16px';
131
+ modalBody.style.flex = '1';
132
+ modalBody.style.overflow = 'hidden';
133
+ modalBody.style.display = 'flex';
134
+ modalBody.style.flexDirection = 'column';
135
+
136
+ const textarea = document.createElement('textarea');
137
+ textarea.className = 'json-editor-textarea';
138
+ textarea.style.width = '100%';
139
+ textarea.style.height = '100%';
140
+ textarea.style.padding = '12px';
141
+ textarea.style.border = '1px solid #d1d5db';
142
+ textarea.style.borderRadius = '4px';
143
+ textarea.style.fontFamily = 'Monaco, Menlo, "Ubuntu Mono", monospace';
144
+ textarea.style.fontSize = `${config.fontSize}px`;
145
+ textarea.style.lineHeight = '1.4';
146
+ textarea.style.resize = 'vertical';
147
+ textarea.style.outline = 'none';
148
+ textarea.style.wordWrap = config.wordWrap ? 'break-word' : 'normal';
149
+
150
+ if (config.validateOnChange) {
151
+ textarea.addEventListener('input', validateJson);
152
+ }
153
+
154
+ const validationContainer = document.createElement('div');
155
+ validationContainer.className = 'validation-container';
156
+ validationContainer.style.marginTop = '12px';
157
+ validationContainer.style.padding = '12px';
158
+ validationContainer.style.borderRadius = '4px';
159
+ validationContainer.style.border = '1px solid #d1d5db';
160
+ validationContainer.style.display = 'none';
161
+
162
+ const validationContent = document.createElement('div');
163
+ validationContent.className = 'validation-content';
164
+ validationContent.style.fontSize = '13px';
165
+ validationContent.style.lineHeight = '1.4';
166
+
167
+ validationContainer.appendChild(validationContent);
168
+ modalBody.appendChild(textarea);
169
+ modalBody.appendChild(validationContainer);
170
+
171
+ return modalBody;
172
+ };
173
+
174
+ /**
175
+ * Create modal footer with action buttons
176
+ * @param {Function} handleSave - Save handler function
177
+ * @param {Function} handleClose - Close handler function
178
+ * @returns {HTMLDivElement} Modal footer element
179
+ */
180
+ const createModalFooter = (handleSave, handleClose) => {
181
+ const modalFooter = document.createElement('div');
182
+ modalFooter.className = 'modal-footer';
183
+ modalFooter.style.display = 'flex';
184
+ modalFooter.style.justifyContent = 'flex-end';
185
+ modalFooter.style.gap = '8px';
186
+ modalFooter.style.padding = '16px';
187
+ modalFooter.style.borderTop = '1px solid #e5e7eb';
188
+
189
+ const cancelBtn = document.createElement('button');
190
+ cancelBtn.className = 'btn btn-secondary';
191
+ cancelBtn.textContent = 'Cancel';
192
+ cancelBtn.addEventListener('click', handleClose);
193
+
194
+ const saveBtn = document.createElement('button');
195
+ saveBtn.className = 'btn btn-primary save-btn';
196
+
197
+ const saveIcon = document.createElement('i');
198
+ saveIcon.className = 'fas fa-save';
199
+ saveBtn.appendChild(saveIcon);
200
+ saveBtn.appendChild(document.createTextNode(' Save'));
201
+ saveBtn.addEventListener('click', handleSave);
202
+
203
+ modalFooter.appendChild(cancelBtn);
204
+ modalFooter.appendChild(saveBtn);
205
+
206
+ return modalFooter;
207
+ };
208
+
209
+ /**
210
+ * Create validation success message
211
+ * @param {HTMLElement} validationContent - Validation content element
212
+ * @returns {void}
213
+ */
214
+ const createValidationSuccess = (validationContent) => {
215
+ const successDiv = document.createElement('div');
216
+ successDiv.style.color = '#10b981';
217
+ successDiv.style.fontWeight = '600';
218
+
219
+ const successIcon = document.createElement('i');
220
+ successIcon.className = 'fas fa-check-circle';
221
+ successDiv.appendChild(successIcon);
222
+ successDiv.appendChild(document.createTextNode(' Valid JSON and worker data'));
223
+
224
+ validationContent.appendChild(successDiv);
225
+ };
226
+
227
+ /**
228
+ * Create validation error messages
229
+ * @param {HTMLElement} validationContent - Validation content element
230
+ * @param {Array} errors - Array of error objects
231
+ * @returns {void}
232
+ */
233
+ const createValidationErrors = (validationContent, errors) => {
234
+ const errorHeader = document.createElement('div');
235
+ errorHeader.style.color = '#ef4444';
236
+ errorHeader.style.fontWeight = '600';
237
+ errorHeader.style.marginBottom = '8px';
238
+
239
+ const errorIcon = document.createElement('i');
240
+ errorIcon.className = 'fas fa-exclamation-triangle';
241
+ errorHeader.appendChild(errorIcon);
242
+ errorHeader.appendChild(document.createTextNode(' Validation Errors:'));
243
+
244
+ validationContent.appendChild(errorHeader);
245
+
246
+ errors.forEach((error) => {
247
+ const errorDiv = document.createElement('div');
248
+ errorDiv.style.color = '#ef4444';
249
+ errorDiv.style.marginBottom = '4px';
250
+ errorDiv.textContent = `• ${error.path}: ${error.message}`;
251
+ validationContent.appendChild(errorDiv);
252
+ });
253
+ };
254
+
255
+ /**
256
+ * Create JSON parse error message
257
+ * @param {HTMLElement} validationContent - Validation content element
258
+ * @param {string} errorMessage - Error message
259
+ * @returns {void}
260
+ */
261
+ const createParseError = (validationContent, errorMessage) => {
262
+ const invalidDiv = document.createElement('div');
263
+ invalidDiv.style.color = '#ef4444';
264
+ invalidDiv.style.fontWeight = '600';
265
+
266
+ const invalidIcon = document.createElement('i');
267
+ invalidIcon.className = 'fas fa-exclamation-circle';
268
+ invalidDiv.appendChild(invalidIcon);
269
+ invalidDiv.appendChild(document.createTextNode(` Invalid JSON: ${errorMessage}`));
270
+
271
+ validationContent.appendChild(invalidDiv);
272
+ };
273
+
274
+ /**
275
+ * Clear validation content
276
+ * @param {HTMLElement} validationContent - Validation content element
277
+ * @returns {void}
278
+ */
279
+ const clearValidationContent = (validationContent) => {
280
+ while (validationContent.firstChild) {
281
+ validationContent.firstChild.remove();
282
+ }
283
+ };
284
+
285
+ /**
286
+ * Format JSON in textarea
287
+ * @param {HTMLElement} element - Modal element
288
+ * @param {Function} validateJson - Validate function
289
+ * @returns {void}
290
+ */
291
+ const createFormatHandler = (element, validateJson) => {
292
+ return () => {
293
+ const textarea = element.querySelector('.json-editor-textarea');
294
+ try {
295
+ const data = JSON.parse(textarea.value);
296
+ textarea.value = JSON.stringify(data, null, 2);
297
+ } catch (error) {
298
+ console.log('error :', error);
299
+ // Show validation error
300
+ validateJson();
301
+ }
302
+ };
303
+ };
304
+
305
+ /**
306
+ * Create JSON validator function
307
+ * @param {HTMLElement} element - Modal element
308
+ * @returns {Function} Validator function
309
+ */
310
+ const createValidator = (element) => {
311
+ return () => {
312
+ const textarea = element.querySelector('.json-editor-textarea');
313
+ const validationContainer = element.querySelector('.validation-container');
314
+ const validationContent = element.querySelector('.validation-content');
315
+
316
+ try {
317
+ const data = JSON.parse(textarea.value);
318
+ const validationResult = validateWorkerData(data);
319
+
320
+ validationContainer.style.display = 'block';
321
+ clearValidationContent(validationContent);
322
+
323
+ if (validationResult.isValid) {
324
+ createValidationSuccess(validationContent);
325
+ } else {
326
+ createValidationErrors(validationContent, validationResult.errors);
327
+ }
328
+ } catch (error) {
329
+ validationContainer.style.display = 'block';
330
+ clearValidationContent(validationContent);
331
+ createParseError(validationContent, error.message);
332
+ }
333
+ };
334
+ };
335
+
336
+ /**
337
+ * Create save handler
338
+ * @param {HTMLElement} element - Modal element
339
+ * @param {Function} onSaveCallback - Save callback function
340
+ * @param {Function} validateJson - Validate function
341
+ * @param {Function} close - Close function
342
+ * @returns {Function} Save handler function
343
+ */
344
+ const createSaveHandler = (element, onSaveCallback, validateJson, close) => {
345
+ return () => {
346
+ const textarea = element.querySelector('.json-editor-textarea');
347
+ try {
348
+ const data = JSON.parse(textarea.value);
349
+ const validationResult = validateWorkerData(data);
350
+
351
+ if (validationResult.isValid) {
352
+ if (onSaveCallback) {
353
+ onSaveCallback(data);
354
+ }
355
+ close();
356
+ } else {
357
+ validateJson();
358
+ }
359
+ } catch {
360
+ validateJson();
361
+ }
362
+ };
363
+ };
364
+
365
+ /**
366
+ * Create close handler
367
+ * @param {Function} close - Close function
368
+ * @returns {Function} Close handler function
369
+ */
370
+ const createCloseHandler = (close) => {
371
+ return () => {
372
+ close();
373
+ };
374
+ };
375
+
376
+ /**
377
+ * Create modal management functions
378
+ * @param {HTMLElement} element - Modal element
379
+ * @param {Object} config - Configuration object
380
+ * @param {Function} formatJson - Format function
381
+ * @param {Function} validateJson - Validate function
382
+ * @param {Function} handleSave - Save handler
383
+ * @param {Function} handleClose - Close handler
384
+ * @returns {Object} Modal management functions
385
+ */
386
+ const createModalManagement = (
387
+ element,
388
+ config,
389
+ formatJson,
390
+ validateJson,
391
+ handleSave,
392
+ handleClose
393
+ ) => {
394
+ let isOpen = false;
395
+ let backdrop = null;
396
+
397
+ const close = () => {
398
+ if (isOpen) {
399
+ isOpen = false;
400
+
401
+ if (element) {
402
+ element.style.display = 'none';
403
+ element.remove();
404
+ }
405
+
406
+ if (backdrop) {
407
+ backdrop.remove();
408
+ }
409
+
410
+ // Clean up state
411
+ }
412
+ };
413
+
414
+ const open = (data) => {
415
+ isOpen = true;
416
+
417
+ if (!element) {
418
+ const modalElement = createModalElement(
419
+ config,
420
+ formatJson,
421
+ validateJson,
422
+ handleSave,
423
+ handleClose
424
+ );
425
+ // Replace the element reference
426
+ Object.assign(element, modalElement);
427
+ }
428
+
429
+ if (!backdrop && config.backdrop) {
430
+ backdrop = createBackdropElement();
431
+ }
432
+
433
+ const textarea = element.querySelector('.json-editor-textarea');
434
+ textarea.value = JSON.stringify(data, null, 2);
435
+
436
+ if (backdrop) {
437
+ document.body.appendChild(backdrop);
438
+ }
439
+ document.body.appendChild(element);
440
+
441
+ element.style.display = 'block';
442
+ textarea.focus();
443
+ };
444
+
445
+ return {
446
+ open,
447
+ close,
448
+ /** @returns {boolean} Whether the modal is currently open */
449
+ isOpen: () => isOpen,
450
+ };
451
+ };
452
+
453
+ /**
454
+ * Create JSON data management functions
455
+ * @param {HTMLElement} element - Modal element
456
+ * @returns {Object} Data management functions
457
+ */
458
+ const createDataManagement = (element) => {
459
+ const getJsonData = () => {
460
+ const textarea = element.querySelector('.json-editor-textarea');
461
+ try {
462
+ return JSON.parse(textarea.value);
463
+ } catch {
464
+ return null;
465
+ }
466
+ };
467
+
468
+ const setJsonData = (data) => {
469
+ const textarea = element.querySelector('.json-editor-textarea');
470
+ textarea.value = JSON.stringify(data, null, 2);
471
+ };
472
+
473
+ const validate = () => {
474
+ const textarea = element.querySelector('.json-editor-textarea');
475
+ try {
476
+ const data = JSON.parse(textarea.value);
477
+ return validateWorkerData(data);
478
+ } catch (error) {
479
+ return {
480
+ isValid: false,
481
+ errors: [{ path: 'json', message: error.message }],
482
+ };
483
+ }
484
+ };
485
+
486
+ return {
487
+ getJsonData,
488
+ setJsonData,
489
+ validate,
490
+ };
491
+ };
492
+
493
+ /**
494
+ * Create JSON editor event handlers
495
+ * @param {HTMLElement} element - Modal element
496
+ * @param {Object} config - Configuration object
497
+ * @param {Function} onSaveCallback - Save callback function
498
+ * @returns {Object} Event handlers object
499
+ */
500
+ const createEventHandlers = (element, config, onSaveCallback) => {
501
+ // Create local copy to avoid parameter reassignment
502
+ let callbackRef = onSaveCallback;
503
+
504
+ const validateJson = createValidator(element);
505
+ const formatJson = createFormatHandler(element, validateJson);
506
+
507
+ const handleSave = createSaveHandler(element, callbackRef, validateJson, () => {});
508
+ const handleClose = createCloseHandler(() => {});
509
+
510
+ const modalManagement = createModalManagement(
511
+ element,
512
+ config,
513
+ formatJson,
514
+ validateJson,
515
+ handleSave,
516
+ handleClose
517
+ );
518
+ const dataManagement = createDataManagement(element);
519
+
520
+ // Update handlers with actual close function
521
+ const actualHandleSave = createSaveHandler(
522
+ element,
523
+ callbackRef,
524
+ validateJson,
525
+ modalManagement.close
526
+ );
527
+ const actualHandleClose = createCloseHandler(modalManagement.close);
528
+
529
+ const destroy = () => {
530
+ modalManagement.close();
531
+ // Note: element and backdrop cleanup handled in modalManagement
532
+ callbackRef = null;
533
+ };
534
+
535
+ return {
536
+ ...modalManagement,
537
+ ...dataManagement,
538
+ formatJson,
539
+ validateJson,
540
+ handleSave: actualHandleSave,
541
+ handleClose: actualHandleClose,
542
+ destroy,
543
+ };
544
+ };
545
+
546
+ /**
547
+ * Create backdrop element
548
+ * @returns {HTMLDivElement} Backdrop element
549
+ */
550
+ const createBackdropElement = () => {
551
+ const backdrop = document.createElement('div');
552
+ backdrop.style.position = 'fixed';
553
+ backdrop.style.top = '0';
554
+ backdrop.style.left = '0';
555
+ backdrop.style.width = '100%';
556
+ backdrop.style.height = '100%';
557
+ backdrop.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
558
+ backdrop.style.zIndex = '999';
559
+ return backdrop;
560
+ };
561
+
562
+ /**
563
+ * Create JSON editor lifecycle functions
564
+ * @param {HTMLElement} element - Modal element
565
+ * @param {Object} config - Configuration object
566
+ * @param {Object} eventHandlers - Event handlers object
567
+ * @returns {Object} Lifecycle functions
568
+ */
569
+ const createEditorLifecycle = (element, config, eventHandlers) => {
570
+ let isOpen = false;
571
+ let backdrop = null;
572
+ let modalElement = element; // Use local variable to avoid parameter reassignment
573
+
574
+ const open = (data) => {
575
+ isOpen = true;
576
+
577
+ if (!modalElement) {
578
+ modalElement = createModalElement(
579
+ config,
580
+ eventHandlers.formatJson,
581
+ eventHandlers.validateJson,
582
+ eventHandlers.handleSave,
583
+ eventHandlers.handleClose
584
+ );
585
+ }
586
+
587
+ if (!backdrop && config.backdrop) {
588
+ backdrop = createBackdropElement();
589
+ }
590
+
591
+ const textarea = modalElement.querySelector('.json-editor-textarea');
592
+ textarea.value = JSON.stringify(data, null, 2);
593
+
594
+ if (backdrop) {
595
+ document.body.appendChild(backdrop);
596
+ }
597
+ document.body.appendChild(modalElement);
598
+
599
+ modalElement.style.display = 'block';
600
+ textarea.focus();
601
+ };
602
+
603
+ const close = () => {
604
+ if (isOpen) {
605
+ isOpen = false;
606
+
607
+ if (modalElement) {
608
+ modalElement.style.display = 'none';
609
+ modalElement.remove();
610
+ }
611
+
612
+ if (backdrop) {
613
+ backdrop.remove();
614
+ }
615
+
616
+ // Clean up state
617
+ }
618
+ };
619
+
620
+ const destroy = () => {
621
+ close();
622
+ modalElement = null;
623
+ backdrop = null;
624
+ };
625
+
626
+ return {
627
+ open,
628
+ close,
629
+ destroy,
630
+ /** @returns {boolean} Whether the modal is currently open */
631
+ isOpen: () => isOpen,
632
+ };
633
+ };
634
+
635
+ /**
636
+ * Create JSON editor instance
637
+ * @param {Object} config - Configuration object
638
+ * @param {Function} onSaveCallback - Save callback function
639
+ * @returns {Object} JSON editor instance with methods
640
+ */
641
+ const createJsonEditor = (config, onSaveCallback) => {
642
+ const element = null;
643
+
644
+ const eventHandlers = createEventHandlers(
645
+ {
646
+ querySelector: (selector) => element?.querySelector(selector),
647
+ },
648
+ config,
649
+ onSaveCallback
650
+ );
651
+
652
+ const lifecycle = createEditorLifecycle(element, config, eventHandlers);
653
+ const data = createDataManagement(element);
654
+
655
+ return {
656
+ ...lifecycle,
657
+ ...data,
658
+ formatJson: eventHandlers.formatJson,
659
+ validateJson: eventHandlers.validateJson,
660
+ handleSave: eventHandlers.handleSave,
661
+ handleClose: eventHandlers.handleClose,
662
+ };
663
+ };
664
+
665
+ /**
666
+ * Sealed namespace for JsonEditor utilities
667
+ */
668
+ export const JsonEditor = Object.freeze({
669
+ create: createJsonEditor,
670
+ });