@coherent.js/express 1.0.0-beta.2

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/dist/index.cjs ADDED
@@ -0,0 +1,2583 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.js
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ expressEngine: () => expressEngine,
24
+ setupCoherent: () => setupCoherent
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // ../core/src/performance/monitor.js
29
+ function createPerformanceMonitor(options = {}) {
30
+ const opts = {
31
+ enabled: true,
32
+ metrics: {
33
+ custom: {}
34
+ },
35
+ sampling: {
36
+ enabled: false,
37
+ rate: 1,
38
+ strategy: "random"
39
+ },
40
+ reporting: {
41
+ enabled: false,
42
+ interval: 6e4,
43
+ format: "json",
44
+ batch: {
45
+ enabled: false,
46
+ maxSize: 100,
47
+ flushInterval: 5e3
48
+ },
49
+ onReport: null
50
+ },
51
+ alerts: {
52
+ enabled: true,
53
+ rules: []
54
+ },
55
+ resources: {
56
+ enabled: false,
57
+ track: ["memory"],
58
+ interval: 1e3
59
+ },
60
+ profiling: {
61
+ enabled: false,
62
+ mode: "production",
63
+ flamegraph: false,
64
+ tracing: {
65
+ enabled: false,
66
+ sampleRate: 0.01
67
+ }
68
+ },
69
+ ...options
70
+ };
71
+ opts.reporting.batch = {
72
+ enabled: false,
73
+ maxSize: 100,
74
+ flushInterval: 5e3,
75
+ ...options.reporting?.batch || {}
76
+ };
77
+ const metrics = {
78
+ builtin: {
79
+ renderTime: { type: "histogram", unit: "ms", values: [] },
80
+ componentCount: { type: "counter", unit: "renders", value: 0 },
81
+ errorCount: { type: "counter", unit: "errors", value: 0 },
82
+ memoryUsage: { type: "gauge", unit: "MB", values: [] }
83
+ },
84
+ custom: {}
85
+ };
86
+ Object.entries(opts.metrics.custom).forEach(([name, config]) => {
87
+ metrics.custom[name] = {
88
+ type: config.type || "counter",
89
+ unit: config.unit || "",
90
+ threshold: config.threshold,
91
+ values: config.type === "histogram" ? [] : void 0,
92
+ value: config.type === "counter" || config.type === "gauge" ? 0 : void 0
93
+ };
94
+ });
95
+ const samplingState = {
96
+ count: 0,
97
+ sampled: 0,
98
+ adaptiveRate: opts.sampling.rate
99
+ };
100
+ const reportingState = {
101
+ batch: [],
102
+ lastReport: Date.now(),
103
+ reportTimer: null,
104
+ flushTimer: null
105
+ };
106
+ const alertState = {
107
+ triggered: /* @__PURE__ */ new Map(),
108
+ history: []
109
+ };
110
+ const resourceState = {
111
+ samples: [],
112
+ timer: null
113
+ };
114
+ const profilingState = {
115
+ traces: [],
116
+ flamegraphData: []
117
+ };
118
+ const stats = {
119
+ metricsRecorded: 0,
120
+ sampleRate: opts.sampling.rate,
121
+ reportsGenerated: 0,
122
+ alertsTriggered: 0
123
+ };
124
+ function shouldSample() {
125
+ if (!opts.sampling.enabled) return true;
126
+ samplingState.count++;
127
+ if (opts.sampling.strategy === "random") {
128
+ return Math.random() < samplingState.adaptiveRate;
129
+ } else if (opts.sampling.strategy === "deterministic") {
130
+ return samplingState.count % Math.ceil(1 / samplingState.adaptiveRate) === 0;
131
+ } else if (opts.sampling.strategy === "adaptive") {
132
+ const recentRenderTimes = metrics.builtin.renderTime.values.slice(-10);
133
+ if (recentRenderTimes.length > 0) {
134
+ const avgTime = recentRenderTimes.reduce((a, b) => a + b, 0) / recentRenderTimes.length;
135
+ samplingState.adaptiveRate = avgTime > 16 ? Math.min(1, opts.sampling.rate * 2) : opts.sampling.rate;
136
+ }
137
+ return Math.random() < samplingState.adaptiveRate;
138
+ }
139
+ return true;
140
+ }
141
+ function recordMetric(name, value, metadata = {}) {
142
+ if (!opts.enabled) return;
143
+ if (!shouldSample()) return;
144
+ stats.metricsRecorded++;
145
+ const builtinMetric = metrics.builtin[name];
146
+ if (builtinMetric) {
147
+ if (builtinMetric.type === "histogram") {
148
+ builtinMetric.values.push(value);
149
+ if (builtinMetric.values.length > 1e3) {
150
+ builtinMetric.values = builtinMetric.values.slice(-1e3);
151
+ }
152
+ } else if (builtinMetric.type === "counter") {
153
+ builtinMetric.value += value;
154
+ } else if (builtinMetric.type === "gauge") {
155
+ builtinMetric.values.push(value);
156
+ if (builtinMetric.values.length > 100) {
157
+ builtinMetric.values = builtinMetric.values.slice(-100);
158
+ }
159
+ }
160
+ }
161
+ const customMetric = metrics.custom[name];
162
+ if (customMetric) {
163
+ if (customMetric.type === "histogram") {
164
+ customMetric.values = customMetric.values || [];
165
+ customMetric.values.push(value);
166
+ if (customMetric.values.length > 1e3) {
167
+ customMetric.values = customMetric.values.slice(-1e3);
168
+ }
169
+ } else if (customMetric.type === "counter") {
170
+ customMetric.value = (customMetric.value || 0) + value;
171
+ } else if (customMetric.type === "gauge") {
172
+ customMetric.values = customMetric.values || [];
173
+ customMetric.values.push(value);
174
+ if (customMetric.values.length > 100) {
175
+ customMetric.values = customMetric.values.slice(-100);
176
+ }
177
+ }
178
+ if (customMetric.threshold) {
179
+ const currentValue = customMetric.type === "histogram" || customMetric.type === "gauge" ? customMetric.values[customMetric.values.length - 1] : customMetric.value;
180
+ if (currentValue > customMetric.threshold) {
181
+ checkAlerts(name, currentValue);
182
+ }
183
+ }
184
+ }
185
+ if (opts.reporting.enabled && opts.reporting.batch.enabled) {
186
+ reportingState.batch.push({
187
+ metric: name,
188
+ value,
189
+ metadata,
190
+ timestamp: Date.now()
191
+ });
192
+ if (reportingState.batch.length >= opts.reporting.batch.maxSize) {
193
+ flushBatch();
194
+ }
195
+ }
196
+ checkAlerts(name, value);
197
+ }
198
+ function checkAlerts(metric, value) {
199
+ if (!opts.alerts.enabled) return;
200
+ opts.alerts.rules.forEach((rule) => {
201
+ if (rule.metric !== metric) return;
202
+ let triggered = false;
203
+ if (rule.condition === "exceeds" && value > rule.threshold) {
204
+ triggered = true;
205
+ } else if (rule.condition === "below" && value < rule.threshold) {
206
+ triggered = true;
207
+ } else if (rule.condition === "equals" && value === rule.threshold) {
208
+ triggered = true;
209
+ }
210
+ if (triggered) {
211
+ const alertKey = `${rule.metric}-${rule.condition}-${rule.threshold}`;
212
+ const lastTriggered = alertState.triggered.get(alertKey);
213
+ const now = Date.now();
214
+ if (!lastTriggered || now - lastTriggered > 5e3) {
215
+ alertState.triggered.set(alertKey, now);
216
+ alertState.history.push({
217
+ rule,
218
+ value,
219
+ timestamp: now
220
+ });
221
+ stats.alertsTriggered++;
222
+ if (rule.action) {
223
+ rule.action(value, rule);
224
+ }
225
+ }
226
+ }
227
+ });
228
+ }
229
+ function flushBatch() {
230
+ if (reportingState.batch.length === 0) return;
231
+ const batch = [...reportingState.batch];
232
+ reportingState.batch = [];
233
+ if (opts.reporting.onReport) {
234
+ opts.reporting.onReport({ type: "batch", data: batch });
235
+ }
236
+ }
237
+ function generateReport() {
238
+ const report = {
239
+ timestamp: Date.now(),
240
+ statistics: { ...stats },
241
+ metrics: {}
242
+ };
243
+ Object.entries(metrics.builtin).forEach(([name, metric]) => {
244
+ if (metric.type === "histogram") {
245
+ report.metrics[name] = {
246
+ type: "histogram",
247
+ unit: metric.unit,
248
+ count: metric.values.length,
249
+ min: metric.values.length > 0 ? Math.min(...metric.values) : 0,
250
+ max: metric.values.length > 0 ? Math.max(...metric.values) : 0,
251
+ avg: metric.values.length > 0 ? metric.values.reduce((a, b) => a + b, 0) / metric.values.length : 0,
252
+ p50: percentile(metric.values, 0.5),
253
+ p95: percentile(metric.values, 0.95),
254
+ p99: percentile(metric.values, 0.99)
255
+ };
256
+ } else if (metric.type === "counter") {
257
+ report.metrics[name] = {
258
+ type: "counter",
259
+ unit: metric.unit,
260
+ value: metric.value
261
+ };
262
+ } else if (metric.type === "gauge") {
263
+ report.metrics[name] = {
264
+ type: "gauge",
265
+ unit: metric.unit,
266
+ current: metric.values.length > 0 ? metric.values[metric.values.length - 1] : 0,
267
+ avg: metric.values.length > 0 ? metric.values.reduce((a, b) => a + b, 0) / metric.values.length : 0
268
+ };
269
+ }
270
+ });
271
+ Object.entries(metrics.custom).forEach(([name, metric]) => {
272
+ if (metric.type === "histogram") {
273
+ report.metrics[name] = {
274
+ type: "histogram",
275
+ unit: metric.unit,
276
+ count: metric.values?.length || 0,
277
+ min: metric.values?.length > 0 ? Math.min(...metric.values) : 0,
278
+ max: metric.values?.length > 0 ? Math.max(...metric.values) : 0,
279
+ avg: metric.values?.length > 0 ? metric.values.reduce((a, b) => a + b, 0) / metric.values.length : 0,
280
+ p95: percentile(metric.values || [], 0.95),
281
+ p99: percentile(metric.values || [], 0.99)
282
+ };
283
+ } else if (metric.type === "counter") {
284
+ report.metrics[name] = {
285
+ type: "counter",
286
+ unit: metric.unit,
287
+ value: metric.value || 0
288
+ };
289
+ } else if (metric.type === "gauge") {
290
+ report.metrics[name] = {
291
+ type: "gauge",
292
+ unit: metric.unit,
293
+ current: metric.values?.length > 0 ? metric.values[metric.values.length - 1] : 0,
294
+ avg: metric.values?.length > 0 ? metric.values.reduce((a, b) => a + b, 0) / metric.values.length : 0
295
+ };
296
+ }
297
+ });
298
+ report.alerts = {
299
+ total: alertState.history.length,
300
+ recent: alertState.history.slice(-10)
301
+ };
302
+ if (opts.resources.enabled) {
303
+ report.resources = {
304
+ samples: resourceState.samples.slice(-20)
305
+ };
306
+ }
307
+ stats.reportsGenerated++;
308
+ if (opts.reporting.onReport) {
309
+ opts.reporting.onReport({ type: "report", data: report });
310
+ }
311
+ return report;
312
+ }
313
+ function percentile(values, p) {
314
+ if (values.length === 0) return 0;
315
+ const sorted = [...values].sort((a, b) => a - b);
316
+ const index = Math.ceil(sorted.length * p) - 1;
317
+ return sorted[Math.max(0, index)];
318
+ }
319
+ function startResourceMonitoring() {
320
+ if (!opts.resources.enabled) return;
321
+ const collectResources = () => {
322
+ const sample = {
323
+ timestamp: Date.now()
324
+ };
325
+ if (opts.resources.track.includes("memory")) {
326
+ if (typeof process !== "undefined" && process.memoryUsage) {
327
+ const mem = process.memoryUsage();
328
+ sample.memory = {
329
+ heapUsed: mem.heapUsed / 1024 / 1024,
330
+ heapTotal: mem.heapTotal / 1024 / 1024,
331
+ external: mem.external / 1024 / 1024,
332
+ rss: mem.rss / 1024 / 1024
333
+ };
334
+ } else if (typeof performance !== "undefined" && performance.memory) {
335
+ sample.memory = {
336
+ heapUsed: performance.memory.usedJSHeapSize / 1024 / 1024,
337
+ heapTotal: performance.memory.totalJSHeapSize / 1024 / 1024
338
+ };
339
+ }
340
+ }
341
+ resourceState.samples.push(sample);
342
+ if (resourceState.samples.length > 100) {
343
+ resourceState.samples = resourceState.samples.slice(-100);
344
+ }
345
+ resourceState.timer = setTimeout(collectResources, opts.resources.interval);
346
+ };
347
+ collectResources();
348
+ }
349
+ function stopResourceMonitoring() {
350
+ if (resourceState.timer) {
351
+ clearTimeout(resourceState.timer);
352
+ resourceState.timer = null;
353
+ }
354
+ }
355
+ function startReporting() {
356
+ if (!opts.reporting.enabled) return;
357
+ reportingState.reportTimer = setInterval(() => {
358
+ generateReport();
359
+ }, opts.reporting.interval);
360
+ if (opts.reporting.batch.enabled) {
361
+ reportingState.flushTimer = setInterval(() => {
362
+ flushBatch();
363
+ }, opts.reporting.batch.flushInterval);
364
+ }
365
+ }
366
+ function stopReporting() {
367
+ if (reportingState.reportTimer) {
368
+ clearInterval(reportingState.reportTimer);
369
+ reportingState.reportTimer = null;
370
+ }
371
+ if (reportingState.flushTimer) {
372
+ clearInterval(reportingState.flushTimer);
373
+ reportingState.flushTimer = null;
374
+ }
375
+ flushBatch();
376
+ }
377
+ function startProfiling() {
378
+ if (!opts.profiling.enabled) return;
379
+ }
380
+ function recordTrace(name, duration, metadata = {}) {
381
+ if (!opts.profiling.enabled || !opts.profiling.tracing.enabled) return;
382
+ if (Math.random() < opts.profiling.tracing.sampleRate) {
383
+ profilingState.traces.push({
384
+ name,
385
+ duration,
386
+ metadata,
387
+ timestamp: Date.now()
388
+ });
389
+ if (profilingState.traces.length > 1e3) {
390
+ profilingState.traces = profilingState.traces.slice(-1e3);
391
+ }
392
+ }
393
+ }
394
+ function measure(name, fn, metadata = {}) {
395
+ if (!opts.enabled) return fn();
396
+ const start = performance.now();
397
+ try {
398
+ const result = fn();
399
+ const duration = performance.now() - start;
400
+ recordMetric("renderTime", duration, { name, ...metadata });
401
+ recordTrace(name, duration, metadata);
402
+ return result;
403
+ } catch (error) {
404
+ recordMetric("errorCount", 1, { name, error: error.message });
405
+ throw error;
406
+ }
407
+ }
408
+ async function measureAsync(name, fn, metadata = {}) {
409
+ if (!opts.enabled) return fn();
410
+ const start = performance.now();
411
+ try {
412
+ const result = await fn();
413
+ const duration = performance.now() - start;
414
+ recordMetric("renderTime", duration, { name, ...metadata });
415
+ recordTrace(name, duration, metadata);
416
+ return result;
417
+ } catch (error) {
418
+ recordMetric("errorCount", 1, { name, error: error.message });
419
+ throw error;
420
+ }
421
+ }
422
+ function addMetric(name, config) {
423
+ metrics.custom[name] = {
424
+ type: config.type || "counter",
425
+ unit: config.unit || "",
426
+ threshold: config.threshold,
427
+ values: config.type === "histogram" ? [] : void 0,
428
+ value: config.type === "counter" || config.type === "gauge" ? 0 : void 0
429
+ };
430
+ }
431
+ function addAlertRule(rule) {
432
+ opts.alerts.rules.push(rule);
433
+ }
434
+ function getStats() {
435
+ return {
436
+ ...stats,
437
+ sampleRate: samplingState.adaptiveRate,
438
+ batchSize: reportingState.batch.length,
439
+ resourceSamples: resourceState.samples.length,
440
+ traces: profilingState.traces.length,
441
+ alerts: {
442
+ total: alertState.history.length,
443
+ unique: alertState.triggered.size
444
+ }
445
+ };
446
+ }
447
+ function reset() {
448
+ Object.values(metrics.builtin).forEach((metric) => {
449
+ if (metric.type === "histogram" || metric.type === "gauge") {
450
+ metric.values = [];
451
+ } else if (metric.type === "counter") {
452
+ metric.value = 0;
453
+ }
454
+ });
455
+ Object.values(metrics.custom).forEach((metric) => {
456
+ if (metric.type === "histogram" || metric.type === "gauge") {
457
+ metric.values = [];
458
+ } else if (metric.type === "counter") {
459
+ metric.value = 0;
460
+ }
461
+ });
462
+ samplingState.count = 0;
463
+ samplingState.sampled = 0;
464
+ reportingState.batch = [];
465
+ alertState.history = [];
466
+ alertState.triggered.clear();
467
+ resourceState.samples = [];
468
+ profilingState.traces = [];
469
+ stats.metricsRecorded = 0;
470
+ stats.reportsGenerated = 0;
471
+ stats.alertsTriggered = 0;
472
+ }
473
+ if (opts.enabled) {
474
+ startResourceMonitoring();
475
+ startReporting();
476
+ startProfiling();
477
+ }
478
+ return {
479
+ recordMetric,
480
+ measure,
481
+ measureAsync,
482
+ addMetric,
483
+ addAlertRule,
484
+ generateReport,
485
+ getStats,
486
+ reset,
487
+ start() {
488
+ opts.enabled = true;
489
+ startResourceMonitoring();
490
+ startReporting();
491
+ startProfiling();
492
+ },
493
+ stop() {
494
+ opts.enabled = false;
495
+ stopResourceMonitoring();
496
+ stopReporting();
497
+ return generateReport();
498
+ }
499
+ };
500
+ }
501
+ var performanceMonitor = createPerformanceMonitor();
502
+
503
+ // ../core/src/core/object-utils.js
504
+ function deepClone(obj, seen = /* @__PURE__ */ new WeakMap()) {
505
+ if (obj === null || typeof obj !== "object") {
506
+ return obj;
507
+ }
508
+ if (seen.has(obj)) {
509
+ return seen.get(obj);
510
+ }
511
+ if (obj instanceof Date) {
512
+ return new Date(obj.getTime());
513
+ }
514
+ if (obj instanceof RegExp) {
515
+ return new RegExp(obj.source, obj.flags);
516
+ }
517
+ if (Array.isArray(obj)) {
518
+ const clonedArray = [];
519
+ seen.set(obj, clonedArray);
520
+ for (let i = 0; i < obj.length; i++) {
521
+ clonedArray[i] = deepClone(obj[i], seen);
522
+ }
523
+ return clonedArray;
524
+ }
525
+ if (typeof obj === "function") {
526
+ return obj;
527
+ }
528
+ if (obj instanceof Map) {
529
+ const clonedMap = /* @__PURE__ */ new Map();
530
+ seen.set(obj, clonedMap);
531
+ for (const [key, value] of obj) {
532
+ clonedMap.set(deepClone(key, seen), deepClone(value, seen));
533
+ }
534
+ return clonedMap;
535
+ }
536
+ if (obj instanceof Set) {
537
+ const clonedSet = /* @__PURE__ */ new Set();
538
+ seen.set(obj, clonedSet);
539
+ for (const value of obj) {
540
+ clonedSet.add(deepClone(value, seen));
541
+ }
542
+ return clonedSet;
543
+ }
544
+ if (obj instanceof WeakMap) {
545
+ return /* @__PURE__ */ new WeakMap();
546
+ }
547
+ if (obj instanceof WeakSet) {
548
+ return /* @__PURE__ */ new WeakSet();
549
+ }
550
+ const clonedObj = {};
551
+ seen.set(obj, clonedObj);
552
+ if (obj.constructor && obj.constructor !== Object) {
553
+ try {
554
+ clonedObj.__proto__ = obj.__proto__;
555
+ } catch {
556
+ Object.setPrototypeOf(clonedObj, Object.getPrototypeOf(obj));
557
+ }
558
+ }
559
+ for (const key in obj) {
560
+ if (obj.hasOwnProperty(key)) {
561
+ clonedObj[key] = deepClone(obj[key], seen);
562
+ }
563
+ }
564
+ const descriptors = Object.getOwnPropertyDescriptors(obj);
565
+ for (const key of Object.keys(descriptors)) {
566
+ if (!descriptors[key].enumerable && descriptors[key].configurable) {
567
+ try {
568
+ Object.defineProperty(clonedObj, key, {
569
+ ...descriptors[key],
570
+ value: deepClone(descriptors[key].value, seen)
571
+ });
572
+ } catch {
573
+ }
574
+ }
575
+ }
576
+ return clonedObj;
577
+ }
578
+ function validateComponent(component, path = "root") {
579
+ if (component === null || component === void 0) {
580
+ throw new Error(`Invalid component at ${path}: null or undefined`);
581
+ }
582
+ if (["string", "number", "boolean"].includes(typeof component)) {
583
+ return true;
584
+ }
585
+ if (typeof component === "function") {
586
+ return true;
587
+ }
588
+ if (Array.isArray(component)) {
589
+ component.forEach((child, index) => {
590
+ validateComponent(child, `${path}[${index}]`);
591
+ });
592
+ return true;
593
+ }
594
+ if (typeof component === "object") {
595
+ const keys = Object.keys(component);
596
+ if (keys.length === 0) {
597
+ throw new Error(`Empty object at ${path}`);
598
+ }
599
+ keys.forEach((key) => {
600
+ const value = component[key];
601
+ if (!/^[a-zA-Z][a-zA-Z0-9-]*$/.test(key) && key !== "text") {
602
+ console.warn(`Potentially invalid tag name at ${path}: ${key}`);
603
+ }
604
+ if (value && typeof value === "object" && !Array.isArray(value)) {
605
+ if (value.children) {
606
+ validateComponent(value.children, `${path}.${key}.children`);
607
+ }
608
+ } else if (value && typeof value !== "string" && typeof value !== "number" && typeof value !== "function") {
609
+ throw new Error(`Invalid value type at ${path}.${key}: ${typeof value}`);
610
+ }
611
+ });
612
+ return true;
613
+ }
614
+ throw new Error(`Invalid component type at ${path}: ${typeof component}`);
615
+ }
616
+
617
+ // ../core/src/components/component-system.js
618
+ var COMPONENT_METADATA = /* @__PURE__ */ new WeakMap();
619
+ var ComponentState = class {
620
+ constructor(initialState = {}) {
621
+ this.state = { ...initialState };
622
+ this.listeners = /* @__PURE__ */ new Set();
623
+ this.isUpdating = false;
624
+ }
625
+ /**
626
+ * Get state value by key or entire state
627
+ *
628
+ * @param {string} [key] - State key to retrieve
629
+ * @returns {*} State value or entire state object
630
+ */
631
+ get(key) {
632
+ return key ? this.state[key] : { ...this.state };
633
+ }
634
+ /**
635
+ * Update state with new values
636
+ *
637
+ * @param {Object} updates - State updates to apply
638
+ * @returns {ComponentState} This instance for chaining
639
+ */
640
+ set(updates) {
641
+ if (this.isUpdating) return this;
642
+ const oldState = { ...this.state };
643
+ if (typeof updates === "function") {
644
+ updates = updates(oldState);
645
+ }
646
+ this.state = { ...this.state, ...updates };
647
+ this.notifyListeners(oldState, this.state);
648
+ return this;
649
+ }
650
+ subscribe(listener) {
651
+ this.listeners.add(listener);
652
+ return () => this.listeners.delete(listener);
653
+ }
654
+ notifyListeners(oldState, newState) {
655
+ if (this.listeners.size === 0) return;
656
+ this.isUpdating = true;
657
+ this.listeners.forEach((listener) => {
658
+ try {
659
+ listener(newState, oldState);
660
+ } catch (_error) {
661
+ console.error("State listener _error:", _error);
662
+ }
663
+ });
664
+ this.isUpdating = false;
665
+ }
666
+ };
667
+ var Component = class _Component {
668
+ constructor(definition = {}) {
669
+ this.definition = definition;
670
+ this.name = definition.name || "AnonymousComponent";
671
+ this.props = {};
672
+ this.state = new ComponentState(definition.state || {});
673
+ this.children = [];
674
+ this.parent = null;
675
+ this.rendered = null;
676
+ this.isMounted = false;
677
+ this.isDestroyed = false;
678
+ this.hooks = {
679
+ beforeCreate: definition.beforeCreate || (() => {
680
+ }),
681
+ created: definition.created || (() => {
682
+ }),
683
+ beforeMount: definition.beforeMount || (() => {
684
+ }),
685
+ mounted: definition.mounted || (() => {
686
+ }),
687
+ beforeUpdate: definition.beforeUpdate || (() => {
688
+ }),
689
+ updated: definition.updated || (() => {
690
+ }),
691
+ beforeDestroy: definition.beforeDestroy || (() => {
692
+ }),
693
+ destroyed: definition.destroyed || (() => {
694
+ }),
695
+ errorCaptured: definition.errorCaptured || (() => {
696
+ })
697
+ };
698
+ this.methods = definition.methods || {};
699
+ Object.keys(this.methods).forEach((methodName) => {
700
+ if (typeof this.methods[methodName] === "function") {
701
+ this[methodName] = this.methods[methodName].bind(this);
702
+ }
703
+ });
704
+ this.computed = definition.computed || {};
705
+ this.computedCache = /* @__PURE__ */ new Map();
706
+ this.watchers = definition.watch || {};
707
+ this.setupWatchers();
708
+ COMPONENT_METADATA.set(this, {
709
+ createdAt: Date.now(),
710
+ updateCount: 0,
711
+ renderCount: 0
712
+ });
713
+ this.callHook("beforeCreate");
714
+ this.initialize();
715
+ this.callHook("created");
716
+ }
717
+ /**
718
+ * Initialize component
719
+ */
720
+ initialize() {
721
+ this.unsubscribeState = this.state.subscribe((newState, oldState) => {
722
+ this.onStateChange(newState, oldState);
723
+ });
724
+ this.initializeComputed();
725
+ }
726
+ /**
727
+ * Set up watchers for reactive data
728
+ */
729
+ setupWatchers() {
730
+ Object.keys(this.watchers).forEach((key) => {
731
+ const handler = this.watchers[key];
732
+ this.state.subscribe((newState, oldState) => {
733
+ if (newState[key] !== oldState[key]) {
734
+ handler.call(this, newState[key], oldState[key]);
735
+ }
736
+ });
737
+ });
738
+ }
739
+ /**
740
+ * Initialize computed properties
741
+ */
742
+ initializeComputed() {
743
+ Object.keys(this.computed).forEach((key) => {
744
+ Object.defineProperty(this, key, {
745
+ get: () => {
746
+ if (!this.computedCache.has(key)) {
747
+ const value = this.computed[key].call(this);
748
+ this.computedCache.set(key, value);
749
+ }
750
+ return this.computedCache.get(key);
751
+ },
752
+ enumerable: true
753
+ });
754
+ });
755
+ }
756
+ /**
757
+ * Handle state changes
758
+ */
759
+ onStateChange() {
760
+ if (this.isDestroyed) return;
761
+ this.computedCache.clear();
762
+ if (this.isMounted) {
763
+ this.update();
764
+ }
765
+ }
766
+ /**
767
+ * Call lifecycle hook
768
+ */
769
+ callHook(hookName, ...args) {
770
+ try {
771
+ if (this.hooks[hookName]) {
772
+ return this.hooks[hookName].call(this, ...args);
773
+ }
774
+ } catch (_error) {
775
+ this.handleError(_error, `${hookName} hook`);
776
+ }
777
+ }
778
+ /**
779
+ * Handle component errors
780
+ */
781
+ handleError(_error) {
782
+ console.error(`Component Error in ${this.name}:`, _error);
783
+ this.callHook("errorCaptured", _error);
784
+ if (this.parent && this.parent.handleError) {
785
+ this.parent.handleError(_error, `${this.name} -> ${context}`);
786
+ }
787
+ }
788
+ /**
789
+ * Render the component
790
+ */
791
+ render(props = {}) {
792
+ if (this.isDestroyed) {
793
+ console.warn(`Attempting to render destroyed component: ${this.name}`);
794
+ return null;
795
+ }
796
+ try {
797
+ const metadata = COMPONENT_METADATA.get(this);
798
+ if (metadata) {
799
+ metadata.renderCount++;
800
+ }
801
+ this.props = { ...props };
802
+ if (typeof this.definition.render === "function") {
803
+ this.rendered = this.definition.render.call(this, this.props, this.state.get());
804
+ } else if (typeof this.definition.template !== "undefined") {
805
+ this.rendered = this.processTemplate(this.definition.template, this.props, this.state.get());
806
+ } else {
807
+ throw new Error(`Component ${this.name} must have either render method or template`);
808
+ }
809
+ if (this.rendered !== null) {
810
+ validateComponent(this.rendered, this.name);
811
+ }
812
+ return this.rendered;
813
+ } catch (_error) {
814
+ this.handleError(_error);
815
+ return { div: { className: "component-_error", text: `Error in ${this.name}` } };
816
+ }
817
+ }
818
+ /**
819
+ * Process template with data
820
+ */
821
+ processTemplate(template, props, state) {
822
+ if (typeof template === "function") {
823
+ return template.call(this, props, state);
824
+ }
825
+ if (typeof template === "string") {
826
+ return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
827
+ return props[key] || state[key] || "";
828
+ });
829
+ }
830
+ const processed = deepClone(template);
831
+ this.interpolateObject(processed, { ...props, ...state });
832
+ return processed;
833
+ }
834
+ /**
835
+ * Interpolate object with data
836
+ */
837
+ interpolateObject(obj, data) {
838
+ if (typeof obj === "string") {
839
+ return obj.replace(/\{\{(\w+)\}\}/g, (match, key) => data[key] || "");
840
+ }
841
+ if (Array.isArray(obj)) {
842
+ return obj.map((item) => this.interpolateObject(item, data));
843
+ }
844
+ if (obj && typeof obj === "object") {
845
+ Object.keys(obj).forEach((key) => {
846
+ obj[key] = this.interpolateObject(obj[key], data);
847
+ });
848
+ }
849
+ return obj;
850
+ }
851
+ /**
852
+ * Mount the component
853
+ */
854
+ mount() {
855
+ if (this.isMounted || this.isDestroyed) return this;
856
+ this.callHook("beforeMount");
857
+ this.isMounted = true;
858
+ this.callHook("mounted");
859
+ return this;
860
+ }
861
+ /**
862
+ * Update the component
863
+ */
864
+ update() {
865
+ if (!this.isMounted || this.isDestroyed) return this;
866
+ const metadata = COMPONENT_METADATA.get(this);
867
+ if (metadata) {
868
+ metadata.updateCount++;
869
+ }
870
+ this.callHook("beforeUpdate");
871
+ this.callHook("updated");
872
+ return this;
873
+ }
874
+ /**
875
+ * Destroy the component
876
+ */
877
+ destroy() {
878
+ if (this.isDestroyed) return this;
879
+ this.callHook("beforeDestroy");
880
+ if (this.unsubscribeState) {
881
+ this.unsubscribeState();
882
+ }
883
+ this.children.forEach((child) => {
884
+ if (child.destroy) {
885
+ child.destroy();
886
+ }
887
+ });
888
+ this.isMounted = false;
889
+ this.isDestroyed = true;
890
+ this.children = [];
891
+ this.parent = null;
892
+ this.callHook("destroyed");
893
+ return this;
894
+ }
895
+ /**
896
+ * Get component metadata
897
+ */
898
+ getMetadata() {
899
+ return COMPONENT_METADATA.get(this) || {};
900
+ }
901
+ /**
902
+ * Clone component with new props/state
903
+ */
904
+ clone(overrides = {}) {
905
+ const newDefinition = { ...this.definition, ...overrides };
906
+ return new _Component(newDefinition);
907
+ }
908
+ };
909
+ if (performanceMonitor) {
910
+ const originalRender = Component.prototype.render;
911
+ Component.prototype.render = function(...args) {
912
+ const start = performance.now();
913
+ const result = originalRender.apply(this, args);
914
+ const duration = performance.now() - start;
915
+ performanceMonitor.recordMetric("renderTime", duration, {
916
+ type: "component",
917
+ name: this.name,
918
+ propsSize: JSON.stringify(this.props || {}).length,
919
+ hasState: Object.keys(this.state?.get() || {}).length > 0
920
+ });
921
+ return result;
922
+ };
923
+ }
924
+
925
+ // ../core/src/utils/error-handler.js
926
+ var CoherentError = class _CoherentError extends Error {
927
+ constructor(message, options = {}) {
928
+ super(message);
929
+ this.name = "CoherentError";
930
+ this.type = options.type || "generic";
931
+ this.component = options.component;
932
+ this.context = options.context;
933
+ this.suggestions = options.suggestions || [];
934
+ this.timestamp = Date.now();
935
+ if (Error.captureStackTrace) {
936
+ Error.captureStackTrace(this, _CoherentError);
937
+ }
938
+ }
939
+ toJSON() {
940
+ return {
941
+ name: this.name,
942
+ message: this.message,
943
+ type: this.type,
944
+ component: this.component,
945
+ context: this.context,
946
+ suggestions: this.suggestions,
947
+ timestamp: this.timestamp,
948
+ stack: this.stack
949
+ };
950
+ }
951
+ };
952
+ var ComponentValidationError = class extends CoherentError {
953
+ constructor(message, component, suggestions = []) {
954
+ super(message, {
955
+ type: "validation",
956
+ component,
957
+ suggestions: [
958
+ "Check component structure and syntax",
959
+ "Ensure all required properties are present",
960
+ "Validate prop types and values",
961
+ ...suggestions
962
+ ]
963
+ });
964
+ this.name = "ComponentValidationError";
965
+ }
966
+ };
967
+ var RenderingError = class extends CoherentError {
968
+ constructor(message, component, context2, suggestions = []) {
969
+ super(message, {
970
+ type: "rendering",
971
+ component,
972
+ context: context2,
973
+ suggestions: [
974
+ "Check for circular references",
975
+ "Validate component depth",
976
+ "Ensure all functions return valid components",
977
+ ...suggestions
978
+ ]
979
+ });
980
+ this.name = "RenderingError";
981
+ }
982
+ };
983
+ var PerformanceError = class extends CoherentError {
984
+ constructor(message, metrics, suggestions = []) {
985
+ super(message, {
986
+ type: "performance",
987
+ context: metrics,
988
+ suggestions: [
989
+ "Consider component memoization",
990
+ "Reduce component complexity",
991
+ "Enable caching",
992
+ ...suggestions
993
+ ]
994
+ });
995
+ this.name = "PerformanceError";
996
+ }
997
+ };
998
+ var StateError = class extends CoherentError {
999
+ constructor(message, state, suggestions = []) {
1000
+ super(message, {
1001
+ type: "state",
1002
+ context: state,
1003
+ suggestions: [
1004
+ "Check state mutations",
1005
+ "Ensure proper state initialization",
1006
+ "Validate state transitions",
1007
+ ...suggestions
1008
+ ]
1009
+ });
1010
+ this.name = "StateError";
1011
+ }
1012
+ };
1013
+ var ErrorHandler = class {
1014
+ constructor(options = {}) {
1015
+ this.options = {
1016
+ enableStackTrace: options.enableStackTrace !== false,
1017
+ enableSuggestions: options.enableSuggestions !== false,
1018
+ enableLogging: options.enableLogging !== false,
1019
+ logLevel: options.logLevel || "_error",
1020
+ maxErrorHistory: options.maxErrorHistory || 100,
1021
+ ...options
1022
+ };
1023
+ this.errorHistory = [];
1024
+ this.errorCounts = /* @__PURE__ */ new Map();
1025
+ this.suppressedErrors = /* @__PURE__ */ new Set();
1026
+ }
1027
+ /**
1028
+ * Handle and report errors with detailed context
1029
+ */
1030
+ handle(_error, context2 = {}) {
1031
+ const enhancedError = this.enhanceError(_error, context2);
1032
+ this.addToHistory(enhancedError);
1033
+ if (this.options.enableLogging) {
1034
+ this.logError(enhancedError);
1035
+ }
1036
+ return enhancedError;
1037
+ }
1038
+ /**
1039
+ * Enhance existing errors with more context
1040
+ */
1041
+ enhanceError(_error, context2 = {}) {
1042
+ if (_error instanceof CoherentError) {
1043
+ return _error;
1044
+ }
1045
+ const errorType = this.classifyError(_error, context2);
1046
+ switch (errorType) {
1047
+ case "validation":
1048
+ return new ComponentValidationError(
1049
+ _error.message,
1050
+ context2.component,
1051
+ this.generateSuggestions(_error, context2)
1052
+ );
1053
+ case "rendering":
1054
+ return new RenderingError(
1055
+ _error.message,
1056
+ context2.component,
1057
+ context2.renderContext,
1058
+ this.generateSuggestions(_error, context2)
1059
+ );
1060
+ case "performance":
1061
+ return new PerformanceError(
1062
+ _error.message,
1063
+ context2.metrics,
1064
+ this.generateSuggestions(_error, context2)
1065
+ );
1066
+ case "state":
1067
+ return new StateError(
1068
+ _error.message,
1069
+ context2.state,
1070
+ this.generateSuggestions(_error, context2)
1071
+ );
1072
+ default:
1073
+ return new CoherentError(_error.message, {
1074
+ type: errorType,
1075
+ component: context2.component,
1076
+ context: context2.context,
1077
+ suggestions: this.generateSuggestions(_error, context2)
1078
+ });
1079
+ }
1080
+ }
1081
+ /**
1082
+ * Classify _error type based on message and context
1083
+ */
1084
+ classifyError(_error, context2) {
1085
+ const message = _error.message.toLowerCase();
1086
+ if (message.includes("invalid") || message.includes("validation") || message.includes("required") || message.includes("type")) {
1087
+ return "validation";
1088
+ }
1089
+ if (message.includes("render") || message.includes("circular") || message.includes("depth") || message.includes("cannot render")) {
1090
+ return "rendering";
1091
+ }
1092
+ if (message.includes("slow") || message.includes("memory") || message.includes("performance") || message.includes("timeout")) {
1093
+ return "performance";
1094
+ }
1095
+ if (message.includes("state") || message.includes("mutation") || message.includes("store") || context2.state) {
1096
+ return "state";
1097
+ }
1098
+ if (context2.component) return "validation";
1099
+ if (context2.renderContext) return "rendering";
1100
+ if (context2.metrics) return "performance";
1101
+ return "generic";
1102
+ }
1103
+ /**
1104
+ * Generate helpful suggestions based on _error
1105
+ */
1106
+ generateSuggestions(_error, context2 = {}) {
1107
+ const suggestions = [];
1108
+ const message = _error.message.toLowerCase();
1109
+ const patterns = [
1110
+ {
1111
+ pattern: /cannot render|render.*failed/,
1112
+ suggestions: [
1113
+ "Check if component returns a valid object structure",
1114
+ "Ensure all properties are properly defined",
1115
+ "Look for undefined variables or null references"
1116
+ ]
1117
+ },
1118
+ {
1119
+ pattern: /circular.*reference/,
1120
+ suggestions: [
1121
+ "Remove circular references between components",
1122
+ "Use lazy loading or memoization to break cycles",
1123
+ "Check for self-referencing components"
1124
+ ]
1125
+ },
1126
+ {
1127
+ pattern: /maximum.*depth/,
1128
+ suggestions: [
1129
+ "Reduce component nesting depth",
1130
+ "Break complex components into smaller parts",
1131
+ "Check for infinite recursion in component functions"
1132
+ ]
1133
+ },
1134
+ {
1135
+ pattern: /invalid.*component/,
1136
+ suggestions: [
1137
+ "Ensure component follows the expected object structure",
1138
+ "Check property names and values for typos",
1139
+ "Verify component is not null or undefined"
1140
+ ]
1141
+ },
1142
+ {
1143
+ pattern: /performance|slow|timeout/,
1144
+ suggestions: [
1145
+ "Enable component caching",
1146
+ "Use memoization for expensive operations",
1147
+ "Reduce component complexity",
1148
+ "Consider lazy loading for large components"
1149
+ ]
1150
+ }
1151
+ ];
1152
+ patterns.forEach(({ pattern, suggestions: patternSuggestions }) => {
1153
+ if (pattern.test(message)) {
1154
+ suggestions.push(...patternSuggestions);
1155
+ }
1156
+ });
1157
+ if (context2.component) {
1158
+ const componentType = typeof context2.component;
1159
+ if (componentType === "function") {
1160
+ suggestions.push("Check function component return value");
1161
+ } else if (componentType === "object" && context2.component === null) {
1162
+ suggestions.push("Component is null - ensure proper initialization");
1163
+ } else if (Array.isArray(context2.component)) {
1164
+ suggestions.push("Arrays should contain valid component objects");
1165
+ }
1166
+ }
1167
+ if (suggestions.length === 0) {
1168
+ suggestions.push(
1169
+ "Enable development tools for more detailed debugging",
1170
+ "Check browser console for additional _error details",
1171
+ "Use component validation tools to identify issues"
1172
+ );
1173
+ }
1174
+ return [...new Set(suggestions)];
1175
+ }
1176
+ /**
1177
+ * Add _error to history with deduplication
1178
+ */
1179
+ addToHistory(_error) {
1180
+ const errorKey = `${_error.name}:${_error.message}`;
1181
+ this.errorCounts.set(errorKey, (this.errorCounts.get(errorKey) || 0) + 1);
1182
+ const historyEntry = {
1183
+ ..._error.toJSON(),
1184
+ count: this.errorCounts.get(errorKey),
1185
+ firstSeen: this.errorHistory.find((e) => e.key === errorKey)?.firstSeen || _error.timestamp,
1186
+ key: errorKey
1187
+ };
1188
+ this.errorHistory = this.errorHistory.filter((e) => e.key !== errorKey);
1189
+ this.errorHistory.unshift(historyEntry);
1190
+ if (this.errorHistory.length > this.options.maxErrorHistory) {
1191
+ this.errorHistory = this.errorHistory.slice(0, this.options.maxErrorHistory);
1192
+ }
1193
+ }
1194
+ /**
1195
+ * Log _error with enhanced formatting
1196
+ */
1197
+ logError(_error) {
1198
+ if (this.suppressedErrors.has(`${_error.name}:${_error.message}`)) {
1199
+ return;
1200
+ }
1201
+ const isRepeated = this.errorCounts.get(`${_error.name}:${_error.message}`) > 1;
1202
+ const errorGroup = `\u{1F6A8} ${_error.name}${isRepeated ? ` (\xD7${this.errorCounts.get(`${_error.name}:${_error.message}`)})` : ""}`;
1203
+ console.group(errorGroup);
1204
+ console.error(`\u274C ${_error.message}`);
1205
+ if (_error.component) {
1206
+ console.log("\u{1F50D} Component:", this.formatComponent(_error.component));
1207
+ }
1208
+ if (_error.context) {
1209
+ console.log("\u{1F4CB} Context:", _error.context);
1210
+ }
1211
+ if (this.options.enableSuggestions && _error.suggestions.length > 0) {
1212
+ console.group("\u{1F4A1} Suggestions:");
1213
+ _error.suggestions.forEach((suggestion, index) => {
1214
+ console.log(`${index + 1}. ${suggestion}`);
1215
+ });
1216
+ console.groupEnd();
1217
+ }
1218
+ if (this.options.enableStackTrace && _error.stack) {
1219
+ console.log("\u{1F4DA} Stack trace:", _error.stack);
1220
+ }
1221
+ console.groupEnd();
1222
+ }
1223
+ /**
1224
+ * Format component for logging
1225
+ */
1226
+ formatComponent(component, maxDepth = 2, currentDepth = 0) {
1227
+ if (currentDepth > maxDepth) {
1228
+ return "[...deep]";
1229
+ }
1230
+ if (typeof component === "function") {
1231
+ return `[Function: ${component.name || "anonymous"}]`;
1232
+ }
1233
+ if (Array.isArray(component)) {
1234
+ return component.slice(0, 3).map(
1235
+ (item) => this.formatComponent(item, maxDepth, currentDepth + 1)
1236
+ );
1237
+ }
1238
+ if (component && typeof component === "object") {
1239
+ const formatted = {};
1240
+ const keys = Object.keys(component).slice(0, 5);
1241
+ for (const key of keys) {
1242
+ if (key === "children" && component[key]) {
1243
+ formatted[key] = this.formatComponent(component[key], maxDepth, currentDepth + 1);
1244
+ } else {
1245
+ formatted[key] = component[key];
1246
+ }
1247
+ }
1248
+ if (Object.keys(component).length > 5) {
1249
+ formatted["..."] = `(${Object.keys(component).length - 5} more)`;
1250
+ }
1251
+ return formatted;
1252
+ }
1253
+ return component;
1254
+ }
1255
+ /**
1256
+ * Suppress specific _error types
1257
+ */
1258
+ suppress(errorPattern) {
1259
+ this.suppressedErrors.add(errorPattern);
1260
+ }
1261
+ /**
1262
+ * Clear _error history
1263
+ */
1264
+ clearHistory() {
1265
+ this.errorHistory = [];
1266
+ this.errorCounts.clear();
1267
+ }
1268
+ /**
1269
+ * Get _error statistics
1270
+ */
1271
+ getStats() {
1272
+ const errorsByType = {};
1273
+ const errorsByTime = {};
1274
+ this.errorHistory.forEach((_error) => {
1275
+ errorsByType[_error.type] = (errorsByType[_error.type] || 0) + _error.count;
1276
+ const hour = new Date(_error.timestamp).toISOString().slice(0, 13);
1277
+ errorsByTime[hour] = (errorsByTime[hour] || 0) + _error.count;
1278
+ });
1279
+ return {
1280
+ totalErrors: this.errorHistory.reduce((sum, e) => sum + e.count, 0),
1281
+ uniqueErrors: this.errorHistory.length,
1282
+ errorsByType,
1283
+ errorsByTime,
1284
+ mostCommonErrors: this.getMostCommonErrors(5),
1285
+ recentErrors: this.errorHistory.slice(0, 10)
1286
+ };
1287
+ }
1288
+ /**
1289
+ * Get most common errors
1290
+ */
1291
+ getMostCommonErrors(limit = 10) {
1292
+ return this.errorHistory.sort((a, b) => b.count - a.count).slice(0, limit).map(({ name, message, count, type }) => ({
1293
+ name,
1294
+ message,
1295
+ count,
1296
+ type
1297
+ }));
1298
+ }
1299
+ };
1300
+ var globalErrorHandler = new ErrorHandler();
1301
+
1302
+ // ../core/src/components/lifecycle.js
1303
+ var LIFECYCLE_PHASES = {
1304
+ BEFORE_CREATE: "beforeCreate",
1305
+ CREATED: "created",
1306
+ BEFORE_MOUNT: "beforeMount",
1307
+ MOUNTED: "mounted",
1308
+ BEFORE_UPDATE: "beforeUpdate",
1309
+ UPDATED: "updated",
1310
+ BEFORE_UNMOUNT: "beforeUnmount",
1311
+ UNMOUNTED: "unmounted",
1312
+ ERROR: "_error"
1313
+ };
1314
+ var componentInstances = /* @__PURE__ */ new WeakMap();
1315
+ var ComponentEventSystem = class {
1316
+ constructor() {
1317
+ this.events = /* @__PURE__ */ new Map();
1318
+ this.globalHandlers = /* @__PURE__ */ new Map();
1319
+ }
1320
+ /**
1321
+ * Emit event to component or globally
1322
+ */
1323
+ emit(eventName, data = {}, target = null) {
1324
+ const event = {
1325
+ name: eventName,
1326
+ data,
1327
+ target,
1328
+ timestamp: Date.now(),
1329
+ stopped: false,
1330
+ preventDefault: false
1331
+ };
1332
+ if (target) {
1333
+ const instance = componentInstances.get(target);
1334
+ if (instance) {
1335
+ this._notifyHandlers(instance.id, event);
1336
+ }
1337
+ } else {
1338
+ this._notifyGlobalHandlers(event);
1339
+ }
1340
+ return event;
1341
+ }
1342
+ /**
1343
+ * Listen for events on component or globally
1344
+ */
1345
+ on(eventName, handler, componentId = null) {
1346
+ if (componentId) {
1347
+ if (!this.events.has(componentId)) {
1348
+ this.events.set(componentId, /* @__PURE__ */ new Map());
1349
+ }
1350
+ const componentEvents = this.events.get(componentId);
1351
+ if (!componentEvents.has(eventName)) {
1352
+ componentEvents.set(eventName, /* @__PURE__ */ new Set());
1353
+ }
1354
+ componentEvents.get(eventName).add(handler);
1355
+ } else {
1356
+ if (!this.globalHandlers.has(eventName)) {
1357
+ this.globalHandlers.set(eventName, /* @__PURE__ */ new Set());
1358
+ }
1359
+ this.globalHandlers.get(eventName).add(handler);
1360
+ }
1361
+ return () => this.off(eventName, handler, componentId);
1362
+ }
1363
+ /**
1364
+ * Remove event handler
1365
+ */
1366
+ off(eventName, handler, componentId = null) {
1367
+ if (componentId) {
1368
+ const componentEvents = this.events.get(componentId);
1369
+ if (componentEvents && componentEvents.has(eventName)) {
1370
+ componentEvents.get(eventName).delete(handler);
1371
+ if (componentEvents.get(eventName).size === 0) {
1372
+ componentEvents.delete(eventName);
1373
+ if (componentEvents.size === 0) {
1374
+ this.events.delete(componentId);
1375
+ }
1376
+ }
1377
+ }
1378
+ } else {
1379
+ const handlers = this.globalHandlers.get(eventName);
1380
+ if (handlers) {
1381
+ handlers.delete(handler);
1382
+ if (handlers.size === 0) {
1383
+ this.globalHandlers.delete(eventName);
1384
+ }
1385
+ }
1386
+ }
1387
+ }
1388
+ /**
1389
+ * Listen once
1390
+ */
1391
+ once(eventName, handler, componentId = null) {
1392
+ const onceHandler = (event) => {
1393
+ handler(event);
1394
+ this.off(eventName, onceHandler, componentId);
1395
+ };
1396
+ return this.on(eventName, onceHandler, componentId);
1397
+ }
1398
+ /**
1399
+ * Notify component handlers
1400
+ */
1401
+ _notifyHandlers(componentId, event) {
1402
+ const componentEvents = this.events.get(componentId);
1403
+ if (componentEvents && componentEvents.has(event.name)) {
1404
+ const handlers = componentEvents.get(event.name);
1405
+ for (const handler of handlers) {
1406
+ if (event.stopped) break;
1407
+ try {
1408
+ handler(event);
1409
+ } catch (_error) {
1410
+ globalErrorHandler.handle(_error, {
1411
+ type: "event-handler-_error",
1412
+ context: { event, handler: handler.toString() }
1413
+ });
1414
+ }
1415
+ }
1416
+ }
1417
+ }
1418
+ /**
1419
+ * Notify global handlers
1420
+ */
1421
+ _notifyGlobalHandlers(event) {
1422
+ const handlers = this.globalHandlers.get(event.name);
1423
+ if (handlers) {
1424
+ for (const handler of handlers) {
1425
+ if (event.stopped) break;
1426
+ try {
1427
+ handler(event);
1428
+ } catch (_error) {
1429
+ globalErrorHandler.handle(_error, {
1430
+ type: "global-event-handler-_error",
1431
+ context: { event, handler: handler.toString() }
1432
+ });
1433
+ }
1434
+ }
1435
+ }
1436
+ }
1437
+ /**
1438
+ * Clean up events for a component
1439
+ */
1440
+ cleanup(componentId) {
1441
+ this.events.delete(componentId);
1442
+ }
1443
+ /**
1444
+ * Get event statistics
1445
+ */
1446
+ getStats() {
1447
+ return {
1448
+ componentEvents: this.events.size,
1449
+ globalEvents: this.globalHandlers.size,
1450
+ totalHandlers: Array.from(this.events.values()).reduce((sum, events) => {
1451
+ return sum + Array.from(events.values()).reduce((eventSum, handlers) => {
1452
+ return eventSum + handlers.size;
1453
+ }, 0);
1454
+ }, 0) + Array.from(this.globalHandlers.values()).reduce((sum, handlers) => {
1455
+ return sum + handlers.size;
1456
+ }, 0)
1457
+ };
1458
+ }
1459
+ };
1460
+ var eventSystem = new ComponentEventSystem();
1461
+ function createLifecycleHooks() {
1462
+ const hooks = {};
1463
+ Object.values(LIFECYCLE_PHASES).forEach((phase) => {
1464
+ hooks[phase] = (callback) => {
1465
+ const instance = getCurrentInstance();
1466
+ if (instance) {
1467
+ instance.hook(phase, callback);
1468
+ }
1469
+ };
1470
+ });
1471
+ return hooks;
1472
+ }
1473
+ var currentInstance = null;
1474
+ function getCurrentInstance() {
1475
+ return currentInstance;
1476
+ }
1477
+ var useHooks = createLifecycleHooks();
1478
+
1479
+ // ../core/src/events/event-bus.js
1480
+ function throttle(func, delay) {
1481
+ let lastCall = 0;
1482
+ let timeoutId = null;
1483
+ return function throttled(...args) {
1484
+ const now = Date.now();
1485
+ const timeSinceLastCall = now - lastCall;
1486
+ if (timeSinceLastCall >= delay) {
1487
+ lastCall = now;
1488
+ return func.apply(this, args);
1489
+ } else {
1490
+ if (timeoutId) clearTimeout(timeoutId);
1491
+ timeoutId = setTimeout(() => {
1492
+ lastCall = Date.now();
1493
+ func.apply(this, args);
1494
+ }, delay - timeSinceLastCall);
1495
+ }
1496
+ };
1497
+ }
1498
+ var EventBus = class {
1499
+ constructor(options = {}) {
1500
+ this.listeners = /* @__PURE__ */ new Map();
1501
+ this.handlers = /* @__PURE__ */ new Map();
1502
+ this.actionHandlers = /* @__PURE__ */ new Map();
1503
+ this.middleware = [];
1504
+ this.throttledEmitters = /* @__PURE__ */ new Map();
1505
+ this.debouncedEmitters = /* @__PURE__ */ new Map();
1506
+ this.options = {
1507
+ debug: false,
1508
+ performance: true,
1509
+ maxListeners: 100,
1510
+ enableWildcards: true,
1511
+ enableAsync: true,
1512
+ wildcardSeparator: ":",
1513
+ enablePriority: true,
1514
+ defaultPriority: 0,
1515
+ errorHandler: null,
1516
+ filters: {
1517
+ allowList: null,
1518
+ // null means allow all
1519
+ blockList: []
1520
+ },
1521
+ throttle: {
1522
+ enabled: false,
1523
+ defaultDelay: 100,
1524
+ events: {}
1525
+ },
1526
+ batching: {
1527
+ enabled: false,
1528
+ maxBatchSize: 10,
1529
+ flushInterval: 16
1530
+ },
1531
+ ...options
1532
+ };
1533
+ this.stats = {
1534
+ eventsEmitted: 0,
1535
+ listenersExecuted: 0,
1536
+ errorsOccurred: 0,
1537
+ averageEmitTime: 0,
1538
+ throttledEvents: 0,
1539
+ filteredEvents: 0
1540
+ };
1541
+ if (this.options.batching.enabled) {
1542
+ this.batchQueue = [];
1543
+ this.batchTimer = null;
1544
+ }
1545
+ if (this.options.debug) {
1546
+ this.use((event, data, next) => {
1547
+ console.log(`[EventBus] ${event}:`, data);
1548
+ next();
1549
+ });
1550
+ }
1551
+ }
1552
+ /**
1553
+ * Add middleware
1554
+ */
1555
+ use(middleware) {
1556
+ if (typeof middleware !== "function") {
1557
+ throw new Error("Middleware must be a function");
1558
+ }
1559
+ this.middleware.push(middleware);
1560
+ return this;
1561
+ }
1562
+ /**
1563
+ * Check if event passes filters
1564
+ */
1565
+ passesFilters(event) {
1566
+ const { allowList, blockList } = this.options.filters;
1567
+ if (blockList && blockList.length > 0) {
1568
+ for (const pattern of blockList) {
1569
+ if (this.matchPattern(pattern, event)) {
1570
+ this.stats.filteredEvents++;
1571
+ return false;
1572
+ }
1573
+ }
1574
+ }
1575
+ if (allowList && allowList.length > 0) {
1576
+ for (const pattern of allowList) {
1577
+ if (this.matchPattern(pattern, event)) {
1578
+ return true;
1579
+ }
1580
+ }
1581
+ this.stats.filteredEvents++;
1582
+ return false;
1583
+ }
1584
+ return true;
1585
+ }
1586
+ /**
1587
+ * Match event against pattern
1588
+ */
1589
+ matchPattern(pattern, event) {
1590
+ const sep = this.options.wildcardSeparator;
1591
+ const patternParts = pattern.split(sep);
1592
+ const eventParts = event.split(sep);
1593
+ if (pattern.includes("*")) {
1594
+ if (patternParts.length !== eventParts.length) {
1595
+ return false;
1596
+ }
1597
+ return patternParts.every((part, i) => part === "*" || part === eventParts[i]);
1598
+ }
1599
+ return pattern === event;
1600
+ }
1601
+ /**
1602
+ * Emit an event
1603
+ */
1604
+ async emit(event, data = null) {
1605
+ if (!this.passesFilters(event)) {
1606
+ if (this.options.debug) {
1607
+ console.warn(`[EventBus] Event filtered: ${event}`);
1608
+ }
1609
+ return;
1610
+ }
1611
+ if (this.options.batching.enabled) {
1612
+ return this.addToBatch(event, data);
1613
+ }
1614
+ if (this.options.throttle.enabled) {
1615
+ const throttleDelay = this.options.throttle.events && this.options.throttle.events[event] || this.options.throttle.defaultDelay;
1616
+ if (throttleDelay > 0) {
1617
+ return this.emitThrottled(event, data, throttleDelay);
1618
+ }
1619
+ }
1620
+ return this.emitImmediate(event, data);
1621
+ }
1622
+ /**
1623
+ * Emit immediately without throttling
1624
+ */
1625
+ async emitImmediate(event, data = null) {
1626
+ const startTime = this.options.performance ? performance.now() : 0;
1627
+ try {
1628
+ await this.runMiddleware(event, data);
1629
+ const listeners = this.getEventListeners(event);
1630
+ if (listeners.length === 0) {
1631
+ if (this.options.debug) {
1632
+ console.warn(`[EventBus] No listeners for event: ${event}`);
1633
+ }
1634
+ return;
1635
+ }
1636
+ const promises = listeners.map(
1637
+ (listenerObj) => this.executeListener(listenerObj.listener, event, data, listenerObj.options)
1638
+ );
1639
+ if (this.options.enableAsync) {
1640
+ await Promise.allSettled(promises);
1641
+ } else {
1642
+ for (const promise of promises) {
1643
+ await promise;
1644
+ }
1645
+ }
1646
+ this.stats.eventsEmitted++;
1647
+ this.stats.listenersExecuted += listeners.length;
1648
+ } catch (error) {
1649
+ this.stats.errorsOccurred++;
1650
+ this.handleError(error, event, data);
1651
+ } finally {
1652
+ if (this.options.performance) {
1653
+ const duration = performance.now() - startTime;
1654
+ this.updatePerformanceStats(duration);
1655
+ }
1656
+ }
1657
+ }
1658
+ /**
1659
+ * Emit with throttling
1660
+ */
1661
+ emitThrottled(event, data, delay) {
1662
+ if (!this.throttledEmitters.has(event)) {
1663
+ const throttled = throttle((evt, d) => this.emitImmediate(evt, d), delay);
1664
+ this.throttledEmitters.set(event, throttled);
1665
+ }
1666
+ this.stats.throttledEvents++;
1667
+ return this.throttledEmitters.get(event)(event, data);
1668
+ }
1669
+ /**
1670
+ * Add event to batch queue
1671
+ */
1672
+ addToBatch(event, data) {
1673
+ this.batchQueue.push({ event, data, timestamp: Date.now() });
1674
+ if (this.batchQueue.length >= this.options.batching.maxBatchSize) {
1675
+ this.flushBatch();
1676
+ } else if (!this.batchTimer) {
1677
+ this.batchTimer = setTimeout(() => {
1678
+ this.flushBatch();
1679
+ }, this.options.batching.flushInterval);
1680
+ }
1681
+ }
1682
+ /**
1683
+ * Flush batch queue
1684
+ */
1685
+ async flushBatch() {
1686
+ if (this.batchTimer) {
1687
+ clearTimeout(this.batchTimer);
1688
+ this.batchTimer = null;
1689
+ }
1690
+ const batch = this.batchQueue.splice(0);
1691
+ for (const { event, data } of batch) {
1692
+ await this.emitImmediate(event, data);
1693
+ }
1694
+ }
1695
+ /**
1696
+ * Register event listener with options
1697
+ */
1698
+ on(event, listener, options = {}) {
1699
+ if (typeof listener !== "function") {
1700
+ throw new Error("Listener must be a function");
1701
+ }
1702
+ if (!this.listeners.has(event)) {
1703
+ this.listeners.set(event, []);
1704
+ }
1705
+ const listeners = this.listeners.get(event);
1706
+ if (listeners.length >= this.options.maxListeners) {
1707
+ console.warn(`[EventBus] Max listeners (${this.options.maxListeners}) reached for event: ${event}`);
1708
+ }
1709
+ const listenerId = this.generateListenerId(event);
1710
+ const listenerObj = {
1711
+ listener,
1712
+ listenerId,
1713
+ priority: options.priority !== void 0 ? options.priority : this.options.defaultPriority,
1714
+ condition: options.condition || null,
1715
+ timeout: options.timeout || null,
1716
+ options
1717
+ };
1718
+ listener.__listenerId = listenerId;
1719
+ listener.__event = event;
1720
+ if (this.options.enablePriority) {
1721
+ const insertIndex = listeners.findIndex((l) => l.priority < listenerObj.priority);
1722
+ if (insertIndex === -1) {
1723
+ listeners.push(listenerObj);
1724
+ } else {
1725
+ listeners.splice(insertIndex, 0, listenerObj);
1726
+ }
1727
+ } else {
1728
+ listeners.push(listenerObj);
1729
+ }
1730
+ return listenerId;
1731
+ }
1732
+ /**
1733
+ * Register one-time listener
1734
+ */
1735
+ once(event, listener, options = {}) {
1736
+ const onceListener = (...args) => {
1737
+ this.off(event, onceListener.__listenerId);
1738
+ return listener.call(this, ...args);
1739
+ };
1740
+ if (options.timeout) {
1741
+ const timeoutId = setTimeout(() => {
1742
+ this.off(event, onceListener.__listenerId);
1743
+ if (this.options.debug) {
1744
+ console.warn(`[EventBus] Listener timeout for event: ${event}`);
1745
+ }
1746
+ }, options.timeout);
1747
+ onceListener.__cleanup = () => clearTimeout(timeoutId);
1748
+ }
1749
+ return this.on(event, onceListener, options);
1750
+ }
1751
+ /**
1752
+ * Remove listener
1753
+ */
1754
+ off(event, listenerId) {
1755
+ if (!this.listeners.has(event)) {
1756
+ return false;
1757
+ }
1758
+ const listeners = this.listeners.get(event);
1759
+ const index = listeners.findIndex((l) => l.listenerId === listenerId);
1760
+ if (index !== -1) {
1761
+ const listenerObj = listeners[index];
1762
+ if (listenerObj.listener.__cleanup) {
1763
+ listenerObj.listener.__cleanup();
1764
+ }
1765
+ listeners.splice(index, 1);
1766
+ if (listeners.length === 0) {
1767
+ this.listeners.delete(event);
1768
+ }
1769
+ return true;
1770
+ }
1771
+ return false;
1772
+ }
1773
+ /**
1774
+ * Remove all listeners for an event
1775
+ */
1776
+ removeAllListeners(event) {
1777
+ if (event) {
1778
+ this.listeners.delete(event);
1779
+ } else {
1780
+ this.listeners.clear();
1781
+ }
1782
+ }
1783
+ /**
1784
+ * Get event listeners with wildcard support
1785
+ */
1786
+ getEventListeners(event) {
1787
+ const listeners = [];
1788
+ if (this.listeners.has(event)) {
1789
+ listeners.push(...this.listeners.get(event));
1790
+ }
1791
+ if (this.options.enableWildcards) {
1792
+ for (const [pattern, patternListeners] of this.listeners) {
1793
+ if (pattern.includes("*") && this.matchPattern(pattern, event)) {
1794
+ listeners.push(...patternListeners);
1795
+ }
1796
+ }
1797
+ }
1798
+ if (this.options.enablePriority) {
1799
+ listeners.sort((a, b) => b.priority - a.priority);
1800
+ }
1801
+ return listeners;
1802
+ }
1803
+ /**
1804
+ * Execute listener with options
1805
+ */
1806
+ async executeListener(listener, event, data, options = {}) {
1807
+ try {
1808
+ if (options.condition && !options.condition(data)) {
1809
+ return;
1810
+ }
1811
+ const result = listener.call(this, data, event);
1812
+ if (result && typeof result.then === "function") {
1813
+ await result;
1814
+ }
1815
+ return result;
1816
+ } catch (error) {
1817
+ this.handleError(error, event, data);
1818
+ }
1819
+ }
1820
+ /**
1821
+ * Run middleware chain
1822
+ */
1823
+ async runMiddleware(event, data) {
1824
+ if (this.middleware.length === 0) return;
1825
+ let index = 0;
1826
+ const next = async () => {
1827
+ if (index < this.middleware.length) {
1828
+ const middleware = this.middleware[index++];
1829
+ await middleware(event, data, next);
1830
+ }
1831
+ };
1832
+ await next();
1833
+ }
1834
+ /**
1835
+ * Handle errors
1836
+ */
1837
+ handleError(error, event, data) {
1838
+ if (this.options.errorHandler) {
1839
+ this.options.errorHandler(error, event, data);
1840
+ } else if (this.options.debug) {
1841
+ console.error(`[EventBus] Error in event ${event}:`, error, data);
1842
+ }
1843
+ this.emitSync("eventbus:error", { error, event, data });
1844
+ }
1845
+ /**
1846
+ * Synchronous emit
1847
+ */
1848
+ emitSync(event, data = null) {
1849
+ try {
1850
+ const listeners = this.getEventListeners(event);
1851
+ listeners.forEach((listenerObj) => {
1852
+ try {
1853
+ if (!listenerObj.options.condition || listenerObj.options.condition(data)) {
1854
+ listenerObj.listener.call(this, data, event);
1855
+ }
1856
+ } catch (error) {
1857
+ this.handleError(error, event, data);
1858
+ }
1859
+ });
1860
+ this.stats.eventsEmitted++;
1861
+ this.stats.listenersExecuted += listeners.length;
1862
+ } catch (error) {
1863
+ this.stats.errorsOccurred++;
1864
+ this.handleError(error, event, data);
1865
+ }
1866
+ }
1867
+ /**
1868
+ * Register action handler
1869
+ */
1870
+ registerAction(action, handler) {
1871
+ if (typeof handler !== "function") {
1872
+ throw new Error("Action handler must be a function");
1873
+ }
1874
+ this.actionHandlers.set(action, handler);
1875
+ if (this.options.debug) {
1876
+ console.log(`[EventBus] Registered action: ${action}`);
1877
+ }
1878
+ }
1879
+ /**
1880
+ * Register multiple actions
1881
+ */
1882
+ registerActions(actions) {
1883
+ Object.entries(actions).forEach(([action, handler]) => {
1884
+ this.registerAction(action, handler);
1885
+ });
1886
+ }
1887
+ /**
1888
+ * Get registered actions
1889
+ */
1890
+ getRegisteredActions() {
1891
+ return Array.from(this.actionHandlers.keys());
1892
+ }
1893
+ /**
1894
+ * Handle action event (called by DOM integration)
1895
+ */
1896
+ handleAction(action, element, event, data) {
1897
+ const handler = this.actionHandlers.get(action);
1898
+ if (!handler) {
1899
+ if (this.options.debug) {
1900
+ console.warn(`[EventBus] No handler registered for action: ${action}`);
1901
+ }
1902
+ return;
1903
+ }
1904
+ try {
1905
+ handler.call(element, {
1906
+ element,
1907
+ event,
1908
+ data,
1909
+ emit: this.emit.bind(this),
1910
+ emitSync: this.emitSync.bind(this)
1911
+ });
1912
+ } catch (error) {
1913
+ this.handleError(error, `action:${action}`, { element, event, data });
1914
+ }
1915
+ }
1916
+ /**
1917
+ * Generate unique listener ID
1918
+ */
1919
+ generateListenerId(event) {
1920
+ return `${event}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1921
+ }
1922
+ /**
1923
+ * Update performance stats
1924
+ */
1925
+ updatePerformanceStats(duration) {
1926
+ const count = this.stats.eventsEmitted;
1927
+ this.stats.averageEmitTime = (this.stats.averageEmitTime * (count - 1) + duration) / count;
1928
+ }
1929
+ /**
1930
+ * Get statistics
1931
+ */
1932
+ getStats() {
1933
+ return { ...this.stats };
1934
+ }
1935
+ /**
1936
+ * Reset statistics
1937
+ */
1938
+ resetStats() {
1939
+ this.stats = {
1940
+ eventsEmitted: 0,
1941
+ listenersExecuted: 0,
1942
+ errorsOccurred: 0,
1943
+ averageEmitTime: 0,
1944
+ throttledEvents: 0,
1945
+ filteredEvents: 0
1946
+ };
1947
+ }
1948
+ /**
1949
+ * Destroy event bus
1950
+ */
1951
+ destroy() {
1952
+ this.removeAllListeners();
1953
+ this.actionHandlers.clear();
1954
+ this.handlers.clear();
1955
+ this.middleware = [];
1956
+ this.throttledEmitters.clear();
1957
+ this.debouncedEmitters.clear();
1958
+ if (this.batchTimer) {
1959
+ clearTimeout(this.batchTimer);
1960
+ }
1961
+ }
1962
+ };
1963
+ function createEventBus(options = {}) {
1964
+ return new EventBus(options);
1965
+ }
1966
+ var globalEventBus = createEventBus();
1967
+ var emit = globalEventBus.emit.bind(globalEventBus);
1968
+ var emitSync = globalEventBus.emitSync.bind(globalEventBus);
1969
+ var on = globalEventBus.on.bind(globalEventBus);
1970
+ var once = globalEventBus.once.bind(globalEventBus);
1971
+ var off = globalEventBus.off.bind(globalEventBus);
1972
+ var registerAction = globalEventBus.registerAction.bind(globalEventBus);
1973
+ var handleAction = globalEventBus.handleAction.bind(globalEventBus);
1974
+
1975
+ // ../core/src/events/dom-integration.js
1976
+ var DOMEventIntegration = class {
1977
+ constructor(eventBus = globalEventBus, options = {}) {
1978
+ this.eventBus = eventBus;
1979
+ this.options = {
1980
+ debug: false,
1981
+ debounceDelay: 150,
1982
+ throttleDelay: 100,
1983
+ enableDelegation: true,
1984
+ enableDebounce: true,
1985
+ enableThrottle: false,
1986
+ ...options
1987
+ };
1988
+ this.boundHandlers = /* @__PURE__ */ new Map();
1989
+ this.activeElement = null;
1990
+ this.isInitialized = false;
1991
+ this.handleClick = this.handleClick.bind(this);
1992
+ this.handleChange = this.handleChange.bind(this);
1993
+ this.handleInput = this.handleInput.bind(this);
1994
+ this.handleSubmit = this.handleSubmit.bind(this);
1995
+ this.handleKeydown = this.handleKeydown.bind(this);
1996
+ this.handleFocus = this.handleFocus.bind(this);
1997
+ this.handleBlur = this.handleBlur.bind(this);
1998
+ }
1999
+ /**
2000
+ * Initialize DOM event listeners
2001
+ * @param {HTMLElement} rootElement - Root element to attach listeners to (default: document)
2002
+ */
2003
+ initialize(rootElement = document) {
2004
+ if (this.isInitialized) {
2005
+ console.warn("[DOMEventIntegration] Already initialized");
2006
+ return;
2007
+ }
2008
+ if (typeof window === "undefined" || !rootElement) {
2009
+ console.warn("[DOMEventIntegration] Cannot initialize: no DOM environment");
2010
+ return;
2011
+ }
2012
+ this.rootElement = rootElement;
2013
+ this.setupDOMEventListeners();
2014
+ this.isInitialized = true;
2015
+ if (this.options.debug) {
2016
+ console.log("[DOMEventIntegration] Initialized with options:", this.options);
2017
+ }
2018
+ }
2019
+ /**
2020
+ * Set up delegated DOM event listeners
2021
+ * @private
2022
+ */
2023
+ setupDOMEventListeners() {
2024
+ const clickHandler = this.createDelegatedHandler("click", this.handleClick);
2025
+ this.rootElement.addEventListener("click", clickHandler, { passive: false });
2026
+ this.boundHandlers.set("click", clickHandler);
2027
+ const changeHandler = this.options.enableDebounce ? this.debounce(this.createDelegatedHandler("change", this.handleChange), this.options.debounceDelay) : this.createDelegatedHandler("change", this.handleChange);
2028
+ this.rootElement.addEventListener("change", changeHandler, { passive: true });
2029
+ this.boundHandlers.set("change", changeHandler);
2030
+ const inputHandler = this.options.enableDebounce ? this.debounce(this.createDelegatedHandler("input", this.handleInput), this.options.debounceDelay) : this.createDelegatedHandler("input", this.handleInput);
2031
+ this.rootElement.addEventListener("input", inputHandler, { passive: true });
2032
+ this.boundHandlers.set("input", inputHandler);
2033
+ const submitHandler = this.createDelegatedHandler("submit", this.handleSubmit);
2034
+ this.rootElement.addEventListener("submit", submitHandler, { passive: false });
2035
+ this.boundHandlers.set("submit", submitHandler);
2036
+ const keydownHandler = this.createDelegatedHandler("keydown", this.handleKeydown);
2037
+ this.rootElement.addEventListener("keydown", keydownHandler, { passive: false });
2038
+ this.boundHandlers.set("keydown", keydownHandler);
2039
+ const focusHandler = this.createDelegatedHandler("focus", this.handleFocus);
2040
+ this.rootElement.addEventListener("focus", focusHandler, { passive: true, capture: true });
2041
+ this.boundHandlers.set("focus", focusHandler);
2042
+ const blurHandler = this.createDelegatedHandler("blur", this.handleBlur);
2043
+ this.rootElement.addEventListener("blur", blurHandler, { passive: true, capture: true });
2044
+ this.boundHandlers.set("blur", blurHandler);
2045
+ }
2046
+ /**
2047
+ * Create a delegated event handler
2048
+ * @private
2049
+ */
2050
+ createDelegatedHandler(eventType, handler) {
2051
+ return (event) => {
2052
+ const target = event.target;
2053
+ if (!target) return;
2054
+ const actionElement = this.options.enableDelegation ? target.closest("[data-action]") : target.hasAttribute?.("data-action") ? target : null;
2055
+ if (actionElement) {
2056
+ handler(actionElement, event);
2057
+ } else {
2058
+ handler(target, event);
2059
+ }
2060
+ };
2061
+ }
2062
+ /**
2063
+ * Handle click events
2064
+ * @private
2065
+ */
2066
+ handleClick(element, event) {
2067
+ const action = element.getAttribute?.("data-action");
2068
+ if (action) {
2069
+ this.handleDataAction(element, event, action);
2070
+ }
2071
+ this.eventBus.emitSync("dom:click", {
2072
+ element,
2073
+ event,
2074
+ action,
2075
+ data: this.parseDataAttributes(element)
2076
+ });
2077
+ }
2078
+ /**
2079
+ * Handle change events
2080
+ * @private
2081
+ */
2082
+ handleChange(element, event) {
2083
+ const action = element.getAttribute?.("data-action");
2084
+ if (action) {
2085
+ this.handleDataAction(element, event, action);
2086
+ }
2087
+ this.eventBus.emitSync("dom:change", {
2088
+ element,
2089
+ event,
2090
+ value: element.value,
2091
+ action,
2092
+ data: this.parseDataAttributes(element)
2093
+ });
2094
+ }
2095
+ /**
2096
+ * Handle input events
2097
+ * @private
2098
+ */
2099
+ handleInput(element, event) {
2100
+ const action = element.getAttribute?.("data-action");
2101
+ if (action) {
2102
+ this.handleDataAction(element, event, action);
2103
+ }
2104
+ this.eventBus.emitSync("dom:input", {
2105
+ element,
2106
+ event,
2107
+ value: element.value,
2108
+ action,
2109
+ data: this.parseDataAttributes(element)
2110
+ });
2111
+ }
2112
+ /**
2113
+ * Handle submit events
2114
+ * @private
2115
+ */
2116
+ handleSubmit(element, event) {
2117
+ const action = element.getAttribute?.("data-action");
2118
+ if (action) {
2119
+ event.preventDefault();
2120
+ this.handleDataAction(element, event, action);
2121
+ }
2122
+ this.eventBus.emitSync("dom:submit", {
2123
+ element,
2124
+ event,
2125
+ action,
2126
+ formData: this.extractFormData(element),
2127
+ data: this.parseDataAttributes(element)
2128
+ });
2129
+ }
2130
+ /**
2131
+ * Handle keydown events
2132
+ * @private
2133
+ */
2134
+ handleKeydown(element, event) {
2135
+ const action = element.getAttribute?.("data-action");
2136
+ const keyAction = element.getAttribute?.(`data-key-${event.key.toLowerCase()}`);
2137
+ if (action && this.shouldTriggerKeyAction(event)) {
2138
+ this.handleDataAction(element, event, action);
2139
+ }
2140
+ if (keyAction) {
2141
+ this.handleDataAction(element, event, keyAction);
2142
+ }
2143
+ this.eventBus.emitSync("dom:keydown", {
2144
+ element,
2145
+ event,
2146
+ key: event.key,
2147
+ code: event.code,
2148
+ action,
2149
+ keyAction,
2150
+ data: this.parseDataAttributes(element)
2151
+ });
2152
+ }
2153
+ /**
2154
+ * Handle focus events
2155
+ * @private
2156
+ */
2157
+ handleFocus(element, event) {
2158
+ this.activeElement = element;
2159
+ this.eventBus.emitSync("dom:focus", {
2160
+ element,
2161
+ event,
2162
+ data: this.parseDataAttributes(element)
2163
+ });
2164
+ }
2165
+ /**
2166
+ * Handle blur events
2167
+ * @private
2168
+ */
2169
+ handleBlur(element, event) {
2170
+ if (this.activeElement === element) {
2171
+ this.activeElement = null;
2172
+ }
2173
+ this.eventBus.emitSync("dom:blur", {
2174
+ element,
2175
+ event,
2176
+ data: this.parseDataAttributes(element)
2177
+ });
2178
+ }
2179
+ /**
2180
+ * Handle data-action attributes
2181
+ * @private
2182
+ */
2183
+ handleDataAction(element, event, action) {
2184
+ if (!action) return;
2185
+ const data = this.parseDataAttributes(element);
2186
+ this.eventBus.emitSync("dom:action", {
2187
+ action,
2188
+ element,
2189
+ event,
2190
+ data
2191
+ });
2192
+ this.eventBus.handleAction(action, element, event, data);
2193
+ if (this.options.debug) {
2194
+ console.log(`[DOMEventIntegration] Action triggered: ${action}`, {
2195
+ element,
2196
+ event: event.type,
2197
+ data
2198
+ });
2199
+ }
2200
+ }
2201
+ /**
2202
+ * Parse data attributes from an element
2203
+ * @private
2204
+ */
2205
+ parseDataAttributes(element) {
2206
+ if (!element?.attributes) return {};
2207
+ const data = {};
2208
+ Array.from(element.attributes).forEach((attr) => {
2209
+ if (attr.name.startsWith("data-") && attr.name !== "data-action") {
2210
+ const key = attr.name.slice(5).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
2211
+ let value = attr.value;
2212
+ try {
2213
+ if (value === "true") value = true;
2214
+ else if (value === "false") value = false;
2215
+ else if (value === "null") value = null;
2216
+ else if (value === "undefined") value = void 0;
2217
+ else if (/^\d+$/.test(value)) value = parseInt(value, 10);
2218
+ else if (/^\d*\.\d+$/.test(value)) value = parseFloat(value);
2219
+ else if (value.startsWith("{") && value.endsWith("}") || value.startsWith("[") && value.endsWith("]")) {
2220
+ value = JSON.parse(value);
2221
+ }
2222
+ } catch {
2223
+ }
2224
+ data[key] = value;
2225
+ }
2226
+ });
2227
+ return data;
2228
+ }
2229
+ /**
2230
+ * Extract form data from a form element
2231
+ * @private
2232
+ */
2233
+ extractFormData(formElement) {
2234
+ if (!formElement || formElement.tagName !== "FORM") {
2235
+ return {};
2236
+ }
2237
+ const formData = new FormData(formElement);
2238
+ const data = {};
2239
+ for (const [key, value] of formData.entries()) {
2240
+ if (data[key]) {
2241
+ if (Array.isArray(data[key])) {
2242
+ data[key].push(value);
2243
+ } else {
2244
+ data[key] = [data[key], value];
2245
+ }
2246
+ } else {
2247
+ data[key] = value;
2248
+ }
2249
+ }
2250
+ return data;
2251
+ }
2252
+ /**
2253
+ * Check if a key event should trigger an action
2254
+ * @private
2255
+ */
2256
+ shouldTriggerKeyAction(event) {
2257
+ const triggerKeys = ["Enter", "Space", "Escape"];
2258
+ return triggerKeys.includes(event.key);
2259
+ }
2260
+ /**
2261
+ * Debounce utility function
2262
+ * @private
2263
+ */
2264
+ debounce(func, wait) {
2265
+ let timeout;
2266
+ return function executedFunction(...args) {
2267
+ const later = () => {
2268
+ clearTimeout(timeout);
2269
+ func.apply(this, args);
2270
+ };
2271
+ clearTimeout(timeout);
2272
+ timeout = setTimeout(later, wait);
2273
+ };
2274
+ }
2275
+ /**
2276
+ * Throttle utility function
2277
+ * @private
2278
+ */
2279
+ throttle(func, limit) {
2280
+ let inThrottle;
2281
+ return function executedFunction(...args) {
2282
+ if (!inThrottle) {
2283
+ func.apply(this, args);
2284
+ inThrottle = true;
2285
+ setTimeout(() => inThrottle = false, limit);
2286
+ }
2287
+ };
2288
+ }
2289
+ /**
2290
+ * Add custom event listener
2291
+ * @param {string} eventType - Event type
2292
+ * @param {Function} handler - Event handler
2293
+ * @param {Object} options - Event listener options
2294
+ */
2295
+ addCustomListener(eventType, handler, options = {}) {
2296
+ const wrappedHandler = this.createDelegatedHandler(eventType, handler);
2297
+ this.rootElement.addEventListener(eventType, wrappedHandler, options);
2298
+ this.boundHandlers.set(`custom:${eventType}`, wrappedHandler);
2299
+ }
2300
+ /**
2301
+ * Remove custom event listener
2302
+ * @param {string} eventType - Event type
2303
+ */
2304
+ removeCustomListener(eventType) {
2305
+ const handler = this.boundHandlers.get(`custom:${eventType}`);
2306
+ if (handler) {
2307
+ this.rootElement.removeEventListener(eventType, handler);
2308
+ this.boundHandlers.delete(`custom:${eventType}`);
2309
+ }
2310
+ }
2311
+ /**
2312
+ * Register action handlers in bulk
2313
+ * @param {Object} actions - Object mapping action names to handlers
2314
+ */
2315
+ registerActions(actions) {
2316
+ this.eventBus.registerActions(actions);
2317
+ }
2318
+ /**
2319
+ * Get the currently active (focused) element
2320
+ * @returns {HTMLElement|null}
2321
+ */
2322
+ getActiveElement() {
2323
+ return this.activeElement;
2324
+ }
2325
+ /**
2326
+ * Trigger an action programmatically
2327
+ * @param {string} action - Action name
2328
+ * @param {HTMLElement} element - Target element
2329
+ * @param {Object} data - Additional data
2330
+ */
2331
+ triggerAction(action, element, data = {}) {
2332
+ const syntheticEvent = new CustomEvent("synthetic", {
2333
+ bubbles: true,
2334
+ cancelable: true,
2335
+ detail: data
2336
+ });
2337
+ this.eventBus.handleAction(action, element, syntheticEvent, data);
2338
+ }
2339
+ /**
2340
+ * Clean up event listeners
2341
+ */
2342
+ destroy() {
2343
+ if (!this.isInitialized) return;
2344
+ this.boundHandlers.forEach((handler, eventType) => {
2345
+ this.rootElement.removeEventListener(
2346
+ eventType.replace("custom:", ""),
2347
+ handler
2348
+ );
2349
+ });
2350
+ this.boundHandlers.clear();
2351
+ this.activeElement = null;
2352
+ this.isInitialized = false;
2353
+ if (this.options.debug) {
2354
+ console.log("[DOMEventIntegration] Destroyed");
2355
+ }
2356
+ }
2357
+ };
2358
+ var globalDOMIntegration = new DOMEventIntegration(globalEventBus, {
2359
+ debug: typeof process !== "undefined" && true
2360
+ });
2361
+ if (typeof window !== "undefined") {
2362
+ if (document.readyState === "loading") {
2363
+ document.addEventListener("DOMContentLoaded", () => {
2364
+ globalDOMIntegration.initialize();
2365
+ });
2366
+ } else {
2367
+ globalDOMIntegration.initialize();
2368
+ }
2369
+ }
2370
+
2371
+ // ../core/src/events/index.js
2372
+ var eventSystem2 = {
2373
+ // Core bus
2374
+ bus: globalEventBus,
2375
+ dom: globalDOMIntegration,
2376
+ // Quick access methods
2377
+ emit: globalEventBus.emit.bind(globalEventBus),
2378
+ emitSync: globalEventBus.emitSync.bind(globalEventBus),
2379
+ on: globalEventBus.on.bind(globalEventBus),
2380
+ once: globalEventBus.once.bind(globalEventBus),
2381
+ off: globalEventBus.off.bind(globalEventBus),
2382
+ // Action methods
2383
+ registerAction: globalEventBus.registerAction.bind(globalEventBus),
2384
+ registerActions: globalEventBus.registerActions.bind(globalEventBus),
2385
+ handleAction: globalEventBus.handleAction.bind(globalEventBus),
2386
+ // Statistics and debugging
2387
+ getStats: globalEventBus.getStats.bind(globalEventBus),
2388
+ resetStats: globalEventBus.resetStats.bind(globalEventBus),
2389
+ // Lifecycle
2390
+ destroy() {
2391
+ globalEventBus.destroy();
2392
+ globalDOMIntegration.destroy();
2393
+ }
2394
+ };
2395
+
2396
+ // ../core/src/index.js
2397
+ var scopeCounter = { value: 0 };
2398
+ function generateScopeId() {
2399
+ return `coh-${scopeCounter.value++}`;
2400
+ }
2401
+ function scopeCSS(css, scopeId) {
2402
+ if (!css || typeof css !== "string") return css;
2403
+ return css.replace(/([^{}]*)\s*{/g, (match, selector) => {
2404
+ const selectors = selector.split(",").map((s) => {
2405
+ const trimmed = s.trim();
2406
+ if (!trimmed) return s;
2407
+ if (trimmed.includes(":")) {
2408
+ return trimmed.replace(/([^:]+)(:.*)?/, `$1[${scopeId}]$2`);
2409
+ }
2410
+ return `${trimmed}[${scopeId}]`;
2411
+ });
2412
+ return `${selectors.join(", ")} {`;
2413
+ });
2414
+ }
2415
+ function applyScopeToElement(element, scopeId) {
2416
+ if (typeof element === "string" || typeof element === "number" || !element) {
2417
+ return element;
2418
+ }
2419
+ if (Array.isArray(element)) {
2420
+ return element.map((item) => applyScopeToElement(item, scopeId));
2421
+ }
2422
+ if (typeof element === "object") {
2423
+ const scoped = {};
2424
+ for (const [tagName, props] of Object.entries(element)) {
2425
+ if (typeof props === "object" && props !== null) {
2426
+ const scopedProps = { ...props };
2427
+ scopedProps[scopeId] = "";
2428
+ if (scopedProps.children) {
2429
+ scopedProps.children = applyScopeToElement(scopedProps.children, scopeId);
2430
+ }
2431
+ scoped[tagName] = scopedProps;
2432
+ } else {
2433
+ scoped[tagName] = props;
2434
+ }
2435
+ }
2436
+ return scoped;
2437
+ }
2438
+ return element;
2439
+ }
2440
+ function escapeHtml(text) {
2441
+ if (typeof text !== "string") return text;
2442
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
2443
+ }
2444
+ function isTrustedContent(value) {
2445
+ return value && typeof value === "object" && value.__trusted === true && typeof value.__html === "string";
2446
+ }
2447
+ function isVoidElement(tagName) {
2448
+ const voidElements = /* @__PURE__ */ new Set([
2449
+ "area",
2450
+ "base",
2451
+ "br",
2452
+ "col",
2453
+ "embed",
2454
+ "hr",
2455
+ "img",
2456
+ "input",
2457
+ "link",
2458
+ "meta",
2459
+ "param",
2460
+ "source",
2461
+ "track",
2462
+ "wbr"
2463
+ ]);
2464
+ return voidElements.has(tagName.toLowerCase());
2465
+ }
2466
+ function formatAttributes(attrs) {
2467
+ if (!attrs || typeof attrs !== "object") return "";
2468
+ return Object.entries(attrs).filter(([, value]) => value !== null && value !== void 0 && value !== false).map(([key, value]) => {
2469
+ if (typeof value === "function") {
2470
+ value = value();
2471
+ }
2472
+ const attrName = key === "className" ? "class" : key;
2473
+ if (value === true) return attrName;
2474
+ return `${attrName}="${escapeHtml(String(value))}"`;
2475
+ }).join(" ");
2476
+ }
2477
+ function renderRaw(obj) {
2478
+ if (obj === null || obj === void 0) return "";
2479
+ if (typeof obj === "string" || typeof obj === "number") return escapeHtml(String(obj));
2480
+ if (Array.isArray(obj)) return obj.map(renderRaw).join("");
2481
+ if (typeof obj === "function") {
2482
+ const result = obj(renderRaw);
2483
+ return renderRaw(result);
2484
+ }
2485
+ if (typeof obj !== "object") return escapeHtml(String(obj));
2486
+ if (obj.text !== void 0) {
2487
+ return escapeHtml(String(obj.text));
2488
+ }
2489
+ for (const [tagName, props] of Object.entries(obj)) {
2490
+ if (typeof props === "object" && props !== null) {
2491
+ const { children, text, ...attributes } = props;
2492
+ const attrsStr = formatAttributes(attributes);
2493
+ const openTag = attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`;
2494
+ if (isVoidElement(tagName)) {
2495
+ return openTag.replace(">", " />");
2496
+ }
2497
+ let content = "";
2498
+ if (text !== void 0) {
2499
+ if (isTrustedContent(text)) {
2500
+ content = text.__html;
2501
+ } else {
2502
+ content = escapeHtml(String(text));
2503
+ }
2504
+ } else if (children) {
2505
+ content = renderRaw(children);
2506
+ }
2507
+ return `${openTag}${content}</${tagName}>`;
2508
+ } else if (typeof props === "string") {
2509
+ const content = isTrustedContent(props) ? props.__html : escapeHtml(props);
2510
+ return isVoidElement(tagName) ? `<${tagName} />` : `<${tagName}>${content}</${tagName}>`;
2511
+ }
2512
+ }
2513
+ return "";
2514
+ }
2515
+ function render(obj, options = {}) {
2516
+ const { scoped = false } = options;
2517
+ if (scoped) {
2518
+ return renderScopedComponent(obj);
2519
+ }
2520
+ return renderRaw(obj);
2521
+ }
2522
+ function renderScopedComponent(component) {
2523
+ const scopeId = generateScopeId();
2524
+ function processScopedElement(element) {
2525
+ if (!element || typeof element !== "object") {
2526
+ return element;
2527
+ }
2528
+ if (Array.isArray(element)) {
2529
+ return element.map(processScopedElement);
2530
+ }
2531
+ const result = {};
2532
+ for (const [tagName, props] of Object.entries(element)) {
2533
+ if (tagName === "style" && typeof props === "object" && props.text) {
2534
+ result[tagName] = {
2535
+ ...props,
2536
+ text: scopeCSS(props.text, scopeId)
2537
+ };
2538
+ } else if (typeof props === "object" && props !== null) {
2539
+ const scopedProps = { ...props };
2540
+ if (scopedProps.children) {
2541
+ scopedProps.children = processScopedElement(scopedProps.children);
2542
+ }
2543
+ result[tagName] = scopedProps;
2544
+ } else {
2545
+ result[tagName] = props;
2546
+ }
2547
+ }
2548
+ return result;
2549
+ }
2550
+ const processedComponent = processScopedElement(component);
2551
+ const scopedComponent = applyScopeToElement(processedComponent, scopeId);
2552
+ return renderRaw(scopedComponent);
2553
+ }
2554
+
2555
+ // src/index.js
2556
+ function expressEngine() {
2557
+ return (filePath, options, callback) => {
2558
+ try {
2559
+ const html = render(options);
2560
+ callback(null, html);
2561
+ } catch (_error) {
2562
+ callback(_error);
2563
+ }
2564
+ };
2565
+ }
2566
+ function setupCoherent(app) {
2567
+ app.engine("coherent", expressEngine());
2568
+ app.set("view engine", "coherent");
2569
+ }
2570
+ // Annotate the CommonJS export names for ESM import in node:
2571
+ 0 && (module.exports = {
2572
+ expressEngine,
2573
+ setupCoherent
2574
+ });
2575
+ /**
2576
+ * Coherent.js - Object-Based Rendering Framework
2577
+ * A pure JavaScript framework for server-side rendering using natural object syntax
2578
+ *
2579
+ * @version 2.0.0
2580
+ * @author Coherent Framework Team
2581
+ * @license MIT
2582
+ */
2583
+ //# sourceMappingURL=index.cjs.map