@coherent.js/devtools 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.js ADDED
@@ -0,0 +1,2117 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/inspector.js
9
+ var ComponentInspector = class {
10
+ constructor(options = {}) {
11
+ this.options = {
12
+ trackHistory: true,
13
+ maxHistory: 100,
14
+ verbose: false,
15
+ ...options
16
+ };
17
+ this.components = /* @__PURE__ */ new Map();
18
+ this.history = [];
19
+ this.inspectionCount = 0;
20
+ }
21
+ /**
22
+ * Inspect a component
23
+ *
24
+ * @param {Object} component - Component to inspect
25
+ * @param {Object} [metadata] - Additional metadata
26
+ * @returns {Object} Inspection result
27
+ */
28
+ inspect(component, metadata = {}) {
29
+ this.inspectionCount++;
30
+ const startTime = performance.now();
31
+ const analysis = this.analyzeComponent(component);
32
+ const tree = this.buildComponentTree(component);
33
+ const stats = this.calculateStats(component);
34
+ const endTime = performance.now();
35
+ const inspection = {
36
+ id: this.generateId(),
37
+ timestamp: Date.now(),
38
+ inspectionTime: endTime - startTime,
39
+ component,
40
+ metadata,
41
+ // Flatten analysis results to top level for easier access
42
+ type: analysis.type,
43
+ structure: component,
44
+ props: this.extractProps(component),
45
+ depth: stats.depth || 0,
46
+ // Use stats.depth, not tree.depth
47
+ childCount: stats.elementCount || 0,
48
+ complexity: stats.complexity || 0,
49
+ nodeCount: stats.nodeCount || 0,
50
+ // Keep nested data for detailed inspection
51
+ analysis,
52
+ tree,
53
+ stats,
54
+ valid: analysis.valid,
55
+ issues: analysis.issues || [],
56
+ errors: analysis.issues || [],
57
+ // Alias for compatibility
58
+ warnings: analysis.warnings || []
59
+ };
60
+ if (this.options.trackHistory) {
61
+ this.history.push(inspection);
62
+ if (this.history.length > this.options.maxHistory) {
63
+ this.history.shift();
64
+ }
65
+ }
66
+ this.components.set(inspection.id, inspection);
67
+ if (this.options.verbose) {
68
+ console.log("[Inspector] Component inspected:", inspection.id);
69
+ }
70
+ return inspection;
71
+ }
72
+ /**
73
+ * Extract props from component
74
+ */
75
+ extractProps(component) {
76
+ const props = [];
77
+ if (!component || typeof component !== "object") {
78
+ return props;
79
+ }
80
+ Object.keys(component).forEach((key) => {
81
+ const element = component[key];
82
+ if (element && typeof element === "object") {
83
+ Object.keys(element).forEach((prop) => {
84
+ if (!props.includes(prop) && prop !== "children" && prop !== "text") {
85
+ props.push(prop);
86
+ }
87
+ });
88
+ }
89
+ });
90
+ return props;
91
+ }
92
+ /**
93
+ * Analyze component structure
94
+ */
95
+ analyzeComponent(component) {
96
+ if (!component || typeof component !== "object") {
97
+ return {
98
+ type: typeof component,
99
+ valid: false,
100
+ issues: ["Component is not an object"]
101
+ };
102
+ }
103
+ const issues = [];
104
+ const warnings = [];
105
+ const info = [];
106
+ const seen = /* @__PURE__ */ new WeakSet();
107
+ const checkCircular = (obj, path2 = []) => {
108
+ if (obj === null || typeof obj !== "object") {
109
+ return;
110
+ }
111
+ if (seen.has(obj)) {
112
+ warnings.push(`circular reference detected at ${path2.join(".")}`);
113
+ return;
114
+ }
115
+ seen.add(obj);
116
+ if (Array.isArray(obj)) {
117
+ obj.forEach((item, index) => checkCircular(item, [...path2, `[${index}]`]));
118
+ } else {
119
+ Object.keys(obj).forEach((key) => {
120
+ checkCircular(obj[key], [...path2, key]);
121
+ });
122
+ }
123
+ };
124
+ checkCircular(component, ["root"]);
125
+ const keys = Object.keys(component);
126
+ if (keys.length === 0) {
127
+ issues.push("Component is empty");
128
+ }
129
+ if (keys.length > 1) {
130
+ warnings.push("Component has multiple root elements");
131
+ }
132
+ keys.forEach((key) => {
133
+ const element = component[key];
134
+ if (typeof element === "object" && element !== null) {
135
+ if (element.children && !Array.isArray(element.children)) {
136
+ issues.push(`Children of ${key} should be an array`);
137
+ }
138
+ if (element.className && typeof element.className !== "string") {
139
+ warnings.push(`className of ${key} should be a string`);
140
+ }
141
+ if (element.style && typeof element.style !== "object") {
142
+ warnings.push(`style of ${key} should be an object`);
143
+ }
144
+ const eventHandlers = Object.keys(element).filter((k) => k.startsWith("on"));
145
+ if (eventHandlers.length > 0) {
146
+ info.push(`${key} has ${eventHandlers.length} event handler(s): ${eventHandlers.join(", ")}`);
147
+ }
148
+ }
149
+ });
150
+ return {
151
+ type: "component",
152
+ valid: issues.length === 0,
153
+ rootElements: keys,
154
+ issues,
155
+ warnings,
156
+ info
157
+ };
158
+ }
159
+ /**
160
+ * Build component tree structure
161
+ */
162
+ buildComponentTree(component, depth = 0, maxDepth = 10) {
163
+ if (depth > maxDepth) {
164
+ return { _truncated: true, reason: "Max depth reached" };
165
+ }
166
+ if (!component || typeof component !== "object") {
167
+ return { type: typeof component, value: component };
168
+ }
169
+ if (Array.isArray(component)) {
170
+ return component.map((child) => this.buildComponentTree(child, depth + 1, maxDepth));
171
+ }
172
+ const tree = {};
173
+ for (const [key, value] of Object.entries(component)) {
174
+ if (typeof value === "object" && value !== null) {
175
+ tree[key] = {
176
+ type: "element",
177
+ props: {},
178
+ children: []
179
+ };
180
+ for (const [prop, propValue] of Object.entries(value)) {
181
+ if (prop === "children") {
182
+ tree[key].children = this.buildComponentTree(propValue, depth + 1, maxDepth);
183
+ } else {
184
+ tree[key].props[prop] = propValue;
185
+ }
186
+ }
187
+ } else {
188
+ tree[key] = { type: typeof value, value };
189
+ }
190
+ }
191
+ return tree;
192
+ }
193
+ /**
194
+ * Calculate component statistics
195
+ */
196
+ calculateStats(component) {
197
+ const stats = {
198
+ elementCount: 0,
199
+ depth: 0,
200
+ textNodes: 0,
201
+ eventHandlers: 0,
202
+ hasStyles: false,
203
+ hasClasses: false,
204
+ complexity: 0
205
+ };
206
+ const traverse = (node, currentDepth = 1) => {
207
+ if (!node || typeof node !== "object") {
208
+ if (node !== null && node !== void 0) {
209
+ stats.textNodes++;
210
+ }
211
+ return;
212
+ }
213
+ if (Array.isArray(node)) {
214
+ node.forEach((child) => traverse(child, currentDepth));
215
+ return;
216
+ }
217
+ stats.elementCount++;
218
+ stats.depth = Math.max(stats.depth, currentDepth);
219
+ for (const [_key, value] of Object.entries(node)) {
220
+ if (typeof value === "object" && value !== null) {
221
+ if (value.style) stats.hasStyles = true;
222
+ if (value.className) stats.hasClasses = true;
223
+ const handlers = Object.keys(value).filter((k) => k.startsWith("on"));
224
+ stats.eventHandlers += handlers.length;
225
+ if (value.children) {
226
+ traverse(value.children, currentDepth + 1);
227
+ }
228
+ }
229
+ }
230
+ };
231
+ traverse(component);
232
+ stats.complexity = stats.elementCount * 10 + // Base complexity from element count
233
+ stats.depth * 5 + // Depth adds complexity
234
+ stats.eventHandlers * 3 + // Event handlers add complexity
235
+ stats.textNodes + // Text nodes add minimal complexity
236
+ (stats.hasStyles ? 5 : 0) + // Styles add complexity
237
+ (stats.hasClasses ? 3 : 0);
238
+ return stats;
239
+ }
240
+ /**
241
+ * Get component by ID
242
+ */
243
+ getComponent(id) {
244
+ return this.components.get(id);
245
+ }
246
+ /**
247
+ * Get inspection history
248
+ */
249
+ getHistory() {
250
+ return [...this.history];
251
+ }
252
+ /**
253
+ * Search components by criteria
254
+ */
255
+ search(criteria) {
256
+ const results = [];
257
+ for (const [id, inspection] of this.components.entries()) {
258
+ let matches = true;
259
+ if (criteria.hasIssues && inspection.analysis.issues.length === 0) {
260
+ matches = false;
261
+ }
262
+ if (criteria.hasWarnings && inspection.analysis.warnings.length === 0) {
263
+ matches = false;
264
+ }
265
+ if (criteria.minElements && inspection.stats.elementCount < criteria.minElements) {
266
+ matches = false;
267
+ }
268
+ if (criteria.maxElements && inspection.stats.elementCount > criteria.maxElements) {
269
+ matches = false;
270
+ }
271
+ if (matches) {
272
+ results.push({ id, inspection });
273
+ }
274
+ }
275
+ return results;
276
+ }
277
+ /**
278
+ * Compare two components
279
+ */
280
+ compare(componentA, componentB) {
281
+ const inspectionA = typeof componentA === "string" ? this.getComponent(componentA) : this.inspect(componentA);
282
+ const inspectionB = typeof componentB === "string" ? this.getComponent(componentB) : this.inspect(componentB);
283
+ return {
284
+ statsComparison: {
285
+ elementCount: {
286
+ a: inspectionA.stats.elementCount,
287
+ b: inspectionB.stats.elementCount,
288
+ diff: inspectionB.stats.elementCount - inspectionA.stats.elementCount
289
+ },
290
+ depth: {
291
+ a: inspectionA.stats.depth,
292
+ b: inspectionB.stats.depth,
293
+ diff: inspectionB.stats.depth - inspectionA.stats.depth
294
+ },
295
+ textNodes: {
296
+ a: inspectionA.stats.textNodes,
297
+ b: inspectionB.stats.textNodes,
298
+ diff: inspectionB.stats.textNodes - inspectionA.stats.textNodes
299
+ }
300
+ },
301
+ structureMatch: JSON.stringify(inspectionA.tree) === JSON.stringify(inspectionB.tree),
302
+ issuesComparison: {
303
+ a: inspectionA.analysis.issues.length,
304
+ b: inspectionB.analysis.issues.length
305
+ }
306
+ };
307
+ }
308
+ /**
309
+ * Generate report
310
+ */
311
+ generateReport() {
312
+ return {
313
+ totalInspections: this.inspectionCount,
314
+ componentsTracked: this.components.size,
315
+ historySize: this.history.length,
316
+ summary: {
317
+ totalElements: Array.from(this.components.values()).reduce((sum, c) => sum + c.stats.elementCount, 0),
318
+ averageDepth: Array.from(this.components.values()).reduce((sum, c) => sum + c.stats.depth, 0) / this.components.size || 0,
319
+ componentsWithIssues: Array.from(this.components.values()).filter((c) => c.analysis.issues.length > 0).length,
320
+ componentsWithWarnings: Array.from(this.components.values()).filter((c) => c.analysis.warnings.length > 0).length
321
+ }
322
+ };
323
+ }
324
+ /**
325
+ * Clear all data
326
+ */
327
+ clear() {
328
+ this.components.clear();
329
+ this.history = [];
330
+ this.inspectionCount = 0;
331
+ }
332
+ /**
333
+ * Clear history only
334
+ */
335
+ clearHistory() {
336
+ this.history = [];
337
+ }
338
+ /**
339
+ * Get inspection statistics
340
+ */
341
+ getStats() {
342
+ return {
343
+ totalInspections: this.inspectionCount,
344
+ componentsTracked: this.components.size,
345
+ historySize: this.history.length
346
+ };
347
+ }
348
+ /**
349
+ * Export inspection data
350
+ */
351
+ export() {
352
+ return {
353
+ inspections: this.history.map((h) => ({
354
+ id: h.id,
355
+ timestamp: h.timestamp,
356
+ type: h.type,
357
+ complexity: h.complexity,
358
+ depth: h.depth,
359
+ issues: h.issues,
360
+ warnings: h.warnings
361
+ })),
362
+ stats: this.getStats(),
363
+ exportedAt: Date.now()
364
+ };
365
+ }
366
+ /**
367
+ * Generate unique ID
368
+ */
369
+ generateId() {
370
+ return `inspect-${Date.now()}-${Math.random().toString(36).substring(7)}`;
371
+ }
372
+ };
373
+ function createInspector(options = {}) {
374
+ return new ComponentInspector(options);
375
+ }
376
+ function inspect(component, options = {}) {
377
+ const inspector = new ComponentInspector(options);
378
+ return inspector.inspect(component);
379
+ }
380
+ function validateComponent(component) {
381
+ const inspector = new ComponentInspector();
382
+ const inspection = inspector.inspect(component);
383
+ return {
384
+ valid: inspection.valid,
385
+ errors: inspection.issues || [],
386
+ issues: inspection.issues || [],
387
+ warnings: inspection.warnings || [],
388
+ stats: inspection.stats
389
+ };
390
+ }
391
+
392
+ // src/profiler.js
393
+ var PerformanceProfiler = class {
394
+ constructor(options = {}) {
395
+ this.options = {
396
+ enabled: true,
397
+ sampleRate: 1,
398
+ // 1.0 = 100% sampling
399
+ slowThreshold: 16,
400
+ // 16ms = 60fps
401
+ trackMemory: typeof performance !== "undefined" && performance.memory,
402
+ maxSamples: options.maxSamples || 1e3,
403
+ ...options
404
+ };
405
+ this.measurements = [];
406
+ this.sessions = /* @__PURE__ */ new Map();
407
+ this.currentSession = null;
408
+ this.marks = /* @__PURE__ */ new Map();
409
+ }
410
+ /**
411
+ * Start a profiling session
412
+ */
413
+ start(name = "default") {
414
+ if (!this.options.enabled) {
415
+ return null;
416
+ }
417
+ if (this.options.sampleRate < 1 && Math.random() > this.options.sampleRate) {
418
+ return null;
419
+ }
420
+ const session = {
421
+ id: this.generateId(),
422
+ name,
423
+ startTime: Date.now(),
424
+ measurements: [],
425
+ marks: [],
426
+ active: true
427
+ };
428
+ this.sessions.set(session.id, session);
429
+ this.currentSession = session;
430
+ if (typeof performance !== "undefined" && performance.mark) {
431
+ performance.mark(`coherent-session-start-${session.id}`);
432
+ }
433
+ return session.id;
434
+ }
435
+ /**
436
+ * Stop a profiling session
437
+ */
438
+ stop(sessionId) {
439
+ if (!sessionId) {
440
+ return null;
441
+ }
442
+ const session = this.sessions.get(sessionId);
443
+ if (!session) {
444
+ return null;
445
+ }
446
+ session.endTime = Date.now();
447
+ session.duration = session.endTime - session.startTime;
448
+ session.active = false;
449
+ if (typeof performance !== "undefined" && performance.mark) {
450
+ performance.mark(`coherent-session-end-${session.id}`);
451
+ }
452
+ if (this.currentSession === session) {
453
+ this.currentSession = null;
454
+ }
455
+ this.measurements.push(session);
456
+ if (this.measurements.length > this.options.maxSamples) {
457
+ this.measurements.shift();
458
+ }
459
+ return this.analyzeSession(session);
460
+ }
461
+ /**
462
+ * Start measuring a render
463
+ */
464
+ startRender(componentName, props = {}) {
465
+ if (!this.options.enabled) return null;
466
+ if (Math.random() > this.options.sampleRate) return null;
467
+ const measurementId = this.generateId();
468
+ const measurement = {
469
+ id: measurementId,
470
+ componentName,
471
+ props,
472
+ startTime: Date.now(),
473
+ startMemory: this.getMemoryUsage(),
474
+ phase: "render"
475
+ };
476
+ this.marks.set(measurementId, measurement);
477
+ if (typeof performance !== "undefined" && performance.mark) {
478
+ performance.mark(`coherent-render-start-${measurementId}`);
479
+ }
480
+ return measurementId;
481
+ }
482
+ /**
483
+ * End measuring a render
484
+ */
485
+ endRender(measurementId, result = {}) {
486
+ if (!measurementId || !this.marks.has(measurementId)) return null;
487
+ const measurement = this.marks.get(measurementId);
488
+ measurement.endTime = Date.now();
489
+ measurement.duration = measurement.endTime - measurement.startTime;
490
+ measurement.endMemory = this.getMemoryUsage();
491
+ measurement.memoryDelta = measurement.endMemory - measurement.startMemory;
492
+ measurement.result = result;
493
+ measurement.slow = measurement.duration > this.options.slowThreshold;
494
+ if (typeof performance !== "undefined" && performance.mark) {
495
+ performance.mark(`coherent-render-end-${measurementId}`);
496
+ if (performance.measure) {
497
+ try {
498
+ performance.measure(
499
+ `coherent-render-${measurementId}`,
500
+ `coherent-render-start-${measurementId}`,
501
+ `coherent-render-end-${measurementId}`
502
+ );
503
+ } catch {
504
+ }
505
+ }
506
+ }
507
+ this.measurements.push(measurement);
508
+ if (this.currentSession) {
509
+ this.currentSession.measurements.push(measurement);
510
+ }
511
+ this.marks.delete(measurementId);
512
+ return measurement;
513
+ }
514
+ /**
515
+ * Mark a point in time
516
+ */
517
+ mark(name, data = {}) {
518
+ const mark = {
519
+ name,
520
+ timestamp: Date.now(),
521
+ data,
522
+ memory: this.getMemoryUsage()
523
+ };
524
+ if (this.currentSession) {
525
+ this.currentSession.marks.push(mark);
526
+ }
527
+ if (typeof performance !== "undefined" && performance.mark) {
528
+ performance.mark(`coherent-mark-${name}`);
529
+ }
530
+ return mark;
531
+ }
532
+ /**
533
+ * Measure time between two marks
534
+ */
535
+ measure(startMark, endMark) {
536
+ const start = this.findMark(startMark);
537
+ const end = this.findMark(endMark);
538
+ if (!start || !end) {
539
+ throw new Error("Mark not found");
540
+ }
541
+ return {
542
+ duration: end.timestamp - start.timestamp,
543
+ startMark: start.name,
544
+ endMark: end.name
545
+ };
546
+ }
547
+ /**
548
+ * Get memory usage
549
+ */
550
+ getMemoryUsage() {
551
+ if (typeof performance !== "undefined" && performance.memory) {
552
+ return {
553
+ used: performance.memory.usedJSHeapSize,
554
+ total: performance.memory.totalJSHeapSize,
555
+ limit: performance.memory.jsHeapSizeLimit
556
+ };
557
+ }
558
+ return null;
559
+ }
560
+ /**
561
+ * Find a mark by name
562
+ */
563
+ findMark(name) {
564
+ if (!this.currentSession) return null;
565
+ return this.currentSession.marks.find((m) => m.name === name);
566
+ }
567
+ /**
568
+ * Get all measurements
569
+ */
570
+ getMeasurements(filter = {}) {
571
+ let results = [...this.measurements];
572
+ if (filter.componentName) {
573
+ results = results.filter((m) => m.componentName === filter.componentName);
574
+ }
575
+ if (filter.slow) {
576
+ results = results.filter((m) => m.slow);
577
+ }
578
+ if (filter.minDuration) {
579
+ results = results.filter((m) => m.duration >= filter.minDuration);
580
+ }
581
+ if (filter.limit) {
582
+ results = results.slice(0, filter.limit);
583
+ }
584
+ return results;
585
+ }
586
+ /**
587
+ * Analyze a session
588
+ */
589
+ analyzeSession(session) {
590
+ const measurements = session.measurements;
591
+ if (measurements.length === 0) {
592
+ return {
593
+ session: session.id,
594
+ duration: session.duration,
595
+ measurements: 0,
596
+ analysis: null
597
+ };
598
+ }
599
+ const durations = measurements.map((m) => m.duration);
600
+ const sorted = [...durations].sort((a, b) => a - b);
601
+ return {
602
+ session: session.id,
603
+ name: session.name,
604
+ duration: session.duration,
605
+ measurements: measurements.length,
606
+ analysis: {
607
+ total: durations.reduce((a, b) => a + b, 0),
608
+ average: durations.reduce((a, b) => a + b, 0) / durations.length,
609
+ median: sorted[Math.floor(sorted.length / 2)],
610
+ min: Math.min(...durations),
611
+ max: Math.max(...durations),
612
+ p95: sorted[Math.floor(sorted.length * 0.95)],
613
+ p99: sorted[Math.floor(sorted.length * 0.99)],
614
+ slowRenders: measurements.filter((m) => m.slow).length,
615
+ slowPercentage: measurements.filter((m) => m.slow).length / measurements.length * 100
616
+ },
617
+ byComponent: this.groupByComponent(measurements),
618
+ slowest: measurements.sort((a, b) => b.duration - a.duration).slice(0, 10).map((m) => ({
619
+ component: m.componentName,
620
+ duration: m.duration,
621
+ timestamp: m.startTime
622
+ }))
623
+ };
624
+ }
625
+ /**
626
+ * Group measurements by component
627
+ */
628
+ groupByComponent(measurements) {
629
+ const groups = {};
630
+ measurements.forEach((m) => {
631
+ if (!groups[m.componentName]) {
632
+ groups[m.componentName] = {
633
+ count: 0,
634
+ totalDuration: 0,
635
+ durations: []
636
+ };
637
+ }
638
+ groups[m.componentName].count++;
639
+ groups[m.componentName].totalDuration += m.duration;
640
+ groups[m.componentName].durations.push(m.duration);
641
+ });
642
+ Object.keys(groups).forEach((name) => {
643
+ const group = groups[name];
644
+ group.average = group.totalDuration / group.count;
645
+ group.min = Math.min(...group.durations);
646
+ group.max = Math.max(...group.durations);
647
+ });
648
+ return groups;
649
+ }
650
+ /**
651
+ * Get performance summary
652
+ */
653
+ getSummary() {
654
+ const allMeasurements = this.measurements;
655
+ if (allMeasurements.length === 0) {
656
+ return {
657
+ totalMeasurements: 0,
658
+ totalSessions: this.sessions.size,
659
+ analysis: null
660
+ };
661
+ }
662
+ const durations = allMeasurements.map((m) => m.duration);
663
+ return {
664
+ totalMeasurements: allMeasurements.length,
665
+ totalSessions: this.sessions.size,
666
+ slowRenders: allMeasurements.filter((m) => m.slow).length,
667
+ analysis: {
668
+ average: durations.reduce((a, b) => a + b, 0) / durations.length,
669
+ min: Math.min(...durations),
670
+ max: Math.max(...durations),
671
+ slowPercentage: allMeasurements.filter((m) => m.slow).length / allMeasurements.length * 100
672
+ },
673
+ byComponent: this.groupByComponent(allMeasurements),
674
+ recentSlow: allMeasurements.filter((m) => m.slow).slice(-10).map((m) => ({
675
+ component: m.componentName,
676
+ duration: m.duration,
677
+ timestamp: m.startTime
678
+ }))
679
+ };
680
+ }
681
+ /**
682
+ * Get statistics
683
+ */
684
+ getStatistics() {
685
+ if (this.measurements.length === 0) {
686
+ return { mean: 0, median: 0, min: 0, max: 0, stdDev: 0 };
687
+ }
688
+ const durations = this.measurements.map((m) => m.duration);
689
+ const sum = durations.reduce((a, b) => a + b, 0);
690
+ const mean = sum / durations.length;
691
+ const sorted = [...durations].sort((a, b) => a - b);
692
+ const median = sorted[Math.floor(sorted.length / 2)];
693
+ const variance = durations.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / durations.length;
694
+ const stdDev = Math.sqrt(variance);
695
+ return {
696
+ mean,
697
+ median,
698
+ min: Math.min(...durations),
699
+ max: Math.max(...durations),
700
+ stdDev
701
+ };
702
+ }
703
+ /**
704
+ * Get bottlenecks
705
+ */
706
+ getBottlenecks(threshold = null) {
707
+ const slowThreshold = threshold || this.options.slowThreshold;
708
+ return this.measurements.filter((m) => m.duration > slowThreshold).sort((a, b) => b.duration - a.duration).map((m) => ({
709
+ name: m.name,
710
+ duration: m.duration,
711
+ timestamp: m.startTime
712
+ }));
713
+ }
714
+ /**
715
+ * Get metrics
716
+ */
717
+ getMetrics() {
718
+ const operationCounts = {};
719
+ this.measurements.forEach((m) => {
720
+ operationCounts[m.name] = (operationCounts[m.name] || 0) + 1;
721
+ });
722
+ const totalDuration = this.measurements.reduce((sum, m) => sum + m.duration, 0);
723
+ return {
724
+ totalOperations: this.measurements.length,
725
+ totalDuration,
726
+ operationCounts,
727
+ averageDuration: this.measurements.length > 0 ? totalDuration / this.measurements.length : 0,
728
+ memoryUsage: this.options.trackMemory && typeof performance !== "undefined" && performance.memory ? performance.memory.usedJSHeapSize : null
729
+ };
730
+ }
731
+ /**
732
+ * Generate report
733
+ */
734
+ generateReport() {
735
+ const stats = this.getStatistics();
736
+ const metrics = this.getMetrics();
737
+ const bottlenecks = this.getBottlenecks();
738
+ const recommendations = this.getRecommendations();
739
+ return {
740
+ summary: {
741
+ totalOperations: metrics.totalOperations,
742
+ averageDuration: metrics.averageDuration,
743
+ slowOperations: bottlenecks.length
744
+ },
745
+ statistics: stats,
746
+ operations: this.measurements.map((m) => ({
747
+ name: m.name,
748
+ duration: m.duration,
749
+ timestamp: m.startTime
750
+ })),
751
+ bottlenecks: bottlenecks.slice(0, 10),
752
+ recommendations,
753
+ timestamp: Date.now()
754
+ };
755
+ }
756
+ /**
757
+ * Export profiling data
758
+ */
759
+ export() {
760
+ return {
761
+ sessions: Array.from(this.sessions.values()),
762
+ measurements: this.measurements,
763
+ metrics: this.getMetrics(),
764
+ statistics: this.getStatistics(),
765
+ exportedAt: Date.now()
766
+ };
767
+ }
768
+ /**
769
+ * Format metrics for display
770
+ */
771
+ formatMetrics() {
772
+ const metrics = this.getMetrics();
773
+ const stats = this.getStatistics();
774
+ let output = `Performance Metrics
775
+ `;
776
+ output += `==================
777
+ `;
778
+ output += `Total Operations: ${metrics.totalOperations}
779
+ `;
780
+ output += `Average Duration: ${metrics.averageDuration.toFixed(2)}ms
781
+ `;
782
+ output += `Mean: ${stats.mean.toFixed(2)}ms
783
+ `;
784
+ output += `Median: ${stats.median.toFixed(2)}ms
785
+ `;
786
+ output += `Min: ${stats.min.toFixed(2)}ms
787
+ `;
788
+ output += `Max: ${stats.max.toFixed(2)}ms
789
+ `;
790
+ return output;
791
+ }
792
+ /**
793
+ * Compare two profiles
794
+ */
795
+ compare(profileId1, profileId2) {
796
+ const session1 = this.sessions.get(profileId1);
797
+ const session2 = this.sessions.get(profileId2);
798
+ if (!session1 || !session2) {
799
+ return null;
800
+ }
801
+ return {
802
+ difference: session2.duration - session1.duration,
803
+ percentChange: (session2.duration - session1.duration) / session1.duration * 100,
804
+ profile1: { name: session1.name, duration: session1.duration },
805
+ profile2: { name: session2.name, duration: session2.duration }
806
+ };
807
+ }
808
+ /**
809
+ * Get performance recommendations
810
+ */
811
+ getRecommendations() {
812
+ const recommendations = [];
813
+ const bottlenecks = this.getBottlenecks();
814
+ const stats = this.getStatistics();
815
+ if (bottlenecks.length > 0) {
816
+ bottlenecks.slice(0, 5).forEach((bottleneck) => {
817
+ recommendations.push({
818
+ type: "bottleneck",
819
+ operation: bottleneck.name,
820
+ suggestion: `Optimize ${bottleneck.name} - duration: ${bottleneck.duration.toFixed(2)}ms exceeds threshold`,
821
+ severity: "high",
822
+ message: `Found slow operation exceeding ${this.options.slowThreshold}ms`
823
+ });
824
+ });
825
+ }
826
+ if (stats.max > this.options.slowThreshold * 2) {
827
+ recommendations.push({
828
+ type: "performance",
829
+ operation: "general",
830
+ suggestion: `Review operations with high duration`,
831
+ message: `Maximum duration (${stats.max.toFixed(2)}ms) is significantly high`,
832
+ severity: "medium"
833
+ });
834
+ }
835
+ return recommendations;
836
+ }
837
+ /**
838
+ * Clear all data
839
+ */
840
+ clear() {
841
+ this.measurements = [];
842
+ this.sessions.clear();
843
+ this.currentSession = null;
844
+ this.marks.clear();
845
+ }
846
+ /**
847
+ * Enable profiler
848
+ */
849
+ enable() {
850
+ this.options.enabled = true;
851
+ }
852
+ /**
853
+ * Disable profiler
854
+ */
855
+ disable() {
856
+ this.options.enabled = false;
857
+ }
858
+ /**
859
+ * Generate unique ID
860
+ */
861
+ generateId() {
862
+ return `prof-${Date.now()}-${Math.random().toString(36).substring(7)}`;
863
+ }
864
+ };
865
+ function createProfiler(options = {}) {
866
+ return new PerformanceProfiler(options);
867
+ }
868
+ async function measure(name, fn, profiler = null) {
869
+ const prof = profiler || new PerformanceProfiler();
870
+ const sessionId = prof.start(name);
871
+ try {
872
+ const value = await fn();
873
+ const result = prof.stop(sessionId);
874
+ return { value, duration: result?.duration || 0 };
875
+ } catch (error) {
876
+ const result = prof.stop(sessionId);
877
+ throw { error, duration: result?.duration || 0 };
878
+ }
879
+ }
880
+ function profile(fn) {
881
+ return function(...args) {
882
+ const result = fn(...args);
883
+ return result;
884
+ };
885
+ }
886
+
887
+ // src/logger.js
888
+ var LogLevel = {
889
+ TRACE: 0,
890
+ DEBUG: 1,
891
+ INFO: 2,
892
+ WARN: 3,
893
+ ERROR: 4,
894
+ FATAL: 5
895
+ };
896
+ var DevLogger = class _DevLogger {
897
+ constructor(options = {}) {
898
+ this.options = {
899
+ level: options.level !== void 0 ? options.level : LogLevel.INFO,
900
+ prefix: "[Coherent]",
901
+ timestamp: true,
902
+ colors: true,
903
+ maxLogs: 1e3,
904
+ maxBufferSize: options.maxBufferSize || 1e3,
905
+ grouping: true,
906
+ buffer: options.buffer || false,
907
+ sampleRate: options.sampleRate !== void 0 ? options.sampleRate : 1,
908
+ silent: options.silent || false,
909
+ output: options.output || null,
910
+ categories: options.categories || null,
911
+ filter: options.filter || null,
912
+ ...options
913
+ };
914
+ this.logs = [];
915
+ this.groups = [];
916
+ this.filters = [];
917
+ this.handlers = [];
918
+ this.context = {};
919
+ }
920
+ /**
921
+ * Generic log method (supports category logging)
922
+ */
923
+ log(categoryOrLevel, messageOrData, data) {
924
+ if (typeof categoryOrLevel === "string" && typeof messageOrData === "string") {
925
+ return this.logWithLevel(LogLevel.INFO, messageOrData, { category: categoryOrLevel, ...data });
926
+ }
927
+ return this.logWithLevel(categoryOrLevel, messageOrData, data);
928
+ }
929
+ /**
930
+ * Log a trace message
931
+ */
932
+ trace(message, data = {}) {
933
+ return this.logWithLevel(LogLevel.TRACE, message, data);
934
+ }
935
+ /**
936
+ * Log a debug message
937
+ */
938
+ debug(message, data = {}) {
939
+ return this.log(LogLevel.DEBUG, message, data);
940
+ }
941
+ /**
942
+ * Log an info message
943
+ */
944
+ info(message, data = {}) {
945
+ return this.log(LogLevel.INFO, message, data);
946
+ }
947
+ /**
948
+ * Log a warning
949
+ */
950
+ warn(message, data = {}) {
951
+ return this.log(LogLevel.WARN, message, data);
952
+ }
953
+ /**
954
+ * Log an error
955
+ */
956
+ error(message, data = {}) {
957
+ if (data instanceof Error) {
958
+ data = {
959
+ message: data.message,
960
+ stack: data.stack,
961
+ name: data.name,
962
+ ...data
963
+ };
964
+ }
965
+ return this.logWithLevel(LogLevel.ERROR, message, data);
966
+ }
967
+ /**
968
+ * Log a fatal error
969
+ */
970
+ fatal(message, data = {}) {
971
+ return this.log(LogLevel.FATAL, message, data);
972
+ }
973
+ /**
974
+ * Core logging function
975
+ */
976
+ logWithLevel(level, message, data = {}) {
977
+ if (this.options.sampleRate < 1 && Math.random() > this.options.sampleRate) {
978
+ return;
979
+ }
980
+ if (level < this.options.level) {
981
+ return;
982
+ }
983
+ if (!this.shouldLog(level, message, data)) {
984
+ return;
985
+ }
986
+ const mergedData = { ...this.context, ...data };
987
+ const logEntry = {
988
+ id: this.generateId(),
989
+ level,
990
+ levelName: this.getLevelName(level),
991
+ message,
992
+ data: mergedData,
993
+ timestamp: Date.now(),
994
+ group: this.groups.length > 0 ? this.groups[this.groups.length - 1] : null,
995
+ stack: level >= LogLevel.ERROR ? new Error().stack : null
996
+ };
997
+ this.logs.push(logEntry);
998
+ const maxSize = this.options.buffer ? this.options.maxBufferSize : this.options.maxLogs;
999
+ if (this.logs.length > maxSize) {
1000
+ this.logs.shift();
1001
+ }
1002
+ this.handlers.forEach((handler) => {
1003
+ try {
1004
+ handler(logEntry);
1005
+ } catch (error) {
1006
+ console.error("Error in log handler:", error);
1007
+ }
1008
+ });
1009
+ this.output(logEntry);
1010
+ return logEntry;
1011
+ }
1012
+ /**
1013
+ * Output log to console
1014
+ */
1015
+ output(logEntry) {
1016
+ const parts = [];
1017
+ if (this.options.timestamp) {
1018
+ const date = new Date(logEntry.timestamp);
1019
+ parts.push(`[${date.toISOString()}]`);
1020
+ }
1021
+ if (this.options.prefix) {
1022
+ parts.push(this.options.prefix);
1023
+ }
1024
+ parts.push(`[${logEntry.levelName}]`);
1025
+ if (logEntry.group) {
1026
+ parts.push(`[${logEntry.group}]`);
1027
+ }
1028
+ parts.push(logEntry.message);
1029
+ const contextKeys = Object.keys(logEntry.data);
1030
+ if (contextKeys.length > 0) {
1031
+ const contextStr = contextKeys.map((key) => `${key}=${logEntry.data[key]}`).join(" ");
1032
+ parts.push(`{${contextStr}}`);
1033
+ }
1034
+ const output = parts.join(" ");
1035
+ if (this.options.silent) {
1036
+ return;
1037
+ }
1038
+ if (this.options.output) {
1039
+ this.options.output(logEntry);
1040
+ return;
1041
+ }
1042
+ if (typeof console !== "undefined") {
1043
+ switch (logEntry.level) {
1044
+ case LogLevel.TRACE:
1045
+ case LogLevel.DEBUG:
1046
+ case LogLevel.INFO:
1047
+ console.log(output, logEntry.data);
1048
+ break;
1049
+ case LogLevel.WARN:
1050
+ console.warn(output, logEntry.data);
1051
+ break;
1052
+ case LogLevel.ERROR:
1053
+ case LogLevel.FATAL:
1054
+ console.error(output, logEntry.data);
1055
+ if (logEntry.stack) {
1056
+ console.error(logEntry.stack);
1057
+ }
1058
+ break;
1059
+ }
1060
+ } else {
1061
+ console.log(output, logEntry.data);
1062
+ }
1063
+ }
1064
+ /**
1065
+ * Get color style for log level
1066
+ */
1067
+ getColorStyle(level) {
1068
+ const styles = {
1069
+ [LogLevel.TRACE]: "color: gray",
1070
+ [LogLevel.DEBUG]: "color: blue",
1071
+ [LogLevel.INFO]: "color: green",
1072
+ [LogLevel.WARN]: "color: orange",
1073
+ [LogLevel.ERROR]: "color: red",
1074
+ [LogLevel.FATAL]: "color: red; font-weight: bold"
1075
+ };
1076
+ return styles[level] || "";
1077
+ }
1078
+ /**
1079
+ * Get level name
1080
+ */
1081
+ getLevelName(level) {
1082
+ const names = {
1083
+ [LogLevel.TRACE]: "TRACE",
1084
+ [LogLevel.DEBUG]: "DEBUG",
1085
+ [LogLevel.INFO]: "INFO",
1086
+ [LogLevel.WARN]: "WARN",
1087
+ [LogLevel.ERROR]: "ERROR",
1088
+ [LogLevel.FATAL]: "FATAL"
1089
+ };
1090
+ return names[level] || "UNKNOWN";
1091
+ }
1092
+ /**
1093
+ * Check if log should be output
1094
+ */
1095
+ shouldLog(level, message, data) {
1096
+ if (this.options.filter && !this.options.filter(message, data)) {
1097
+ return false;
1098
+ }
1099
+ if (this.options.categories && data.category) {
1100
+ if (!this.options.categories.includes(data.category)) {
1101
+ return false;
1102
+ }
1103
+ }
1104
+ if (this.filters.length > 0) {
1105
+ return this.filters.every((filter) => filter(level, message, data));
1106
+ }
1107
+ return true;
1108
+ }
1109
+ /**
1110
+ * Add a filter
1111
+ */
1112
+ addFilter(filter) {
1113
+ this.filters.push(filter);
1114
+ }
1115
+ /**
1116
+ * Remove a filter
1117
+ */
1118
+ removeFilter(filter) {
1119
+ const index = this.filters.indexOf(filter);
1120
+ if (index > -1) {
1121
+ this.filters.splice(index, 1);
1122
+ }
1123
+ }
1124
+ /**
1125
+ * Add a log handler
1126
+ */
1127
+ addHandler(handler) {
1128
+ this.handlers.push(handler);
1129
+ }
1130
+ /**
1131
+ * Remove a log handler
1132
+ */
1133
+ removeHandler(handler) {
1134
+ const index = this.handlers.indexOf(handler);
1135
+ if (index > -1) {
1136
+ this.handlers.splice(index, 1);
1137
+ }
1138
+ }
1139
+ /**
1140
+ * Start a log group
1141
+ */
1142
+ group(name) {
1143
+ this.groups.push(name);
1144
+ if (typeof console !== "undefined" && console.group) {
1145
+ console.group(name);
1146
+ }
1147
+ }
1148
+ /**
1149
+ * End a log group
1150
+ */
1151
+ groupEnd() {
1152
+ this.groups.pop();
1153
+ if (typeof console !== "undefined" && console.groupEnd) {
1154
+ console.groupEnd();
1155
+ }
1156
+ }
1157
+ /**
1158
+ * Get all logs
1159
+ */
1160
+ getLogs(filter = {}) {
1161
+ let results = [...this.logs];
1162
+ if (filter.level !== void 0) {
1163
+ results = results.filter((log) => log.level >= filter.level);
1164
+ }
1165
+ if (filter.group) {
1166
+ results = results.filter((log) => log.group === filter.group);
1167
+ }
1168
+ if (filter.search) {
1169
+ const search = filter.search.toLowerCase();
1170
+ results = results.filter(
1171
+ (log) => log.message.toLowerCase().includes(search) || JSON.stringify(log.data).toLowerCase().includes(search)
1172
+ );
1173
+ }
1174
+ if (filter.limit) {
1175
+ results = results.slice(-filter.limit);
1176
+ }
1177
+ return results;
1178
+ }
1179
+ /**
1180
+ * Get log statistics
1181
+ */
1182
+ getStats() {
1183
+ const byLevel = {};
1184
+ Object.values(LogLevel).forEach((level) => {
1185
+ byLevel[this.getLevelName(level)] = 0;
1186
+ });
1187
+ this.logs.forEach((log) => {
1188
+ byLevel[log.levelName]++;
1189
+ });
1190
+ return {
1191
+ total: this.logs.length,
1192
+ byLevel,
1193
+ groups: [...new Set(this.logs.map((l) => l.group).filter(Boolean))],
1194
+ timeRange: this.logs.length > 0 ? {
1195
+ start: this.logs[0].timestamp,
1196
+ end: this.logs[this.logs.length - 1].timestamp,
1197
+ duration: this.logs[this.logs.length - 1].timestamp - this.logs[0].timestamp
1198
+ } : null
1199
+ };
1200
+ }
1201
+ /**
1202
+ * Clear all logs
1203
+ */
1204
+ clear() {
1205
+ this.logs = [];
1206
+ this.groups = [];
1207
+ }
1208
+ /**
1209
+ * Set log level
1210
+ */
1211
+ setLevel(level) {
1212
+ this.options.level = level;
1213
+ }
1214
+ /**
1215
+ * Export logs
1216
+ */
1217
+ export(format = "array") {
1218
+ if (format === "array" || !format) {
1219
+ return this.logs.map((log) => ({
1220
+ level: log.levelName,
1221
+ message: log.message,
1222
+ timestamp: log.timestamp,
1223
+ data: log.data
1224
+ }));
1225
+ }
1226
+ switch (format) {
1227
+ case "json":
1228
+ return JSON.stringify(this.logs, null, 2);
1229
+ case "csv":
1230
+ const headers = ["timestamp", "level", "group", "message", "data"];
1231
+ const rows = this.logs.map((log) => [
1232
+ new Date(log.timestamp).toISOString(),
1233
+ log.levelName,
1234
+ log.group || "",
1235
+ log.message,
1236
+ JSON.stringify(log.data)
1237
+ ]);
1238
+ return [headers, ...rows].map((row) => row.join(",")).join("\n");
1239
+ case "text":
1240
+ return this.logs.map((log) => {
1241
+ const date = new Date(log.timestamp).toISOString();
1242
+ const group = log.group ? `[${log.group}]` : "";
1243
+ return `${date} [${log.levelName}] ${group} ${log.message} ${JSON.stringify(log.data)}`;
1244
+ }).join("\n");
1245
+ default:
1246
+ throw new Error(`Unknown export format: ${format}`);
1247
+ }
1248
+ }
1249
+ /**
1250
+ * Create a logger with additional context
1251
+ */
1252
+ withContext(context) {
1253
+ const contextLogger = new _DevLogger(this.options);
1254
+ contextLogger.context = { ...this.context, ...context };
1255
+ contextLogger.logs = this.logs;
1256
+ contextLogger.groups = this.groups;
1257
+ contextLogger.filters = this.filters;
1258
+ contextLogger.handlers = this.handlers;
1259
+ return contextLogger;
1260
+ }
1261
+ /**
1262
+ * Log a table
1263
+ */
1264
+ table(data) {
1265
+ if (typeof console !== "undefined" && console.table) {
1266
+ console.table(data);
1267
+ } else {
1268
+ console.log(JSON.stringify(data, null, 2));
1269
+ }
1270
+ }
1271
+ /**
1272
+ * Start a timer
1273
+ */
1274
+ time(label) {
1275
+ if (typeof console !== "undefined" && console.time) {
1276
+ console.time(label);
1277
+ }
1278
+ }
1279
+ /**
1280
+ * End a timer
1281
+ */
1282
+ timeEnd(label) {
1283
+ if (typeof console !== "undefined" && console.timeEnd) {
1284
+ console.timeEnd(label);
1285
+ }
1286
+ }
1287
+ /**
1288
+ * Get log buffer
1289
+ */
1290
+ getBuffer() {
1291
+ return this.logs;
1292
+ }
1293
+ /**
1294
+ * Flush buffered logs
1295
+ */
1296
+ flush() {
1297
+ this.logs.forEach((log) => {
1298
+ this.output(log);
1299
+ });
1300
+ }
1301
+ /**
1302
+ * Clear buffer
1303
+ */
1304
+ clearBuffer() {
1305
+ this.logs = [];
1306
+ }
1307
+ /**
1308
+ * Generate unique ID
1309
+ */
1310
+ generateId() {
1311
+ return `log-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1312
+ }
1313
+ };
1314
+ function createLogger(options = {}) {
1315
+ return new DevLogger(options);
1316
+ }
1317
+ function createComponentLogger(componentName, options = {}) {
1318
+ const logger = new DevLogger({
1319
+ prefix: `[${componentName}]`,
1320
+ ...options
1321
+ });
1322
+ logger.perf = (operation, duration) => {
1323
+ logger.info(`${operation} completed in ${duration}ms`);
1324
+ };
1325
+ logger.lifecycle = (event) => {
1326
+ logger.info(`Lifecycle: ${event}`);
1327
+ };
1328
+ return logger;
1329
+ }
1330
+ function createConsoleLogger(prefix = "") {
1331
+ return {
1332
+ trace: (...args) => console.debug(prefix, ...args),
1333
+ debug: (...args) => console.debug(prefix, ...args),
1334
+ info: (...args) => console.info(prefix, ...args),
1335
+ warn: (...args) => console.warn(prefix, ...args),
1336
+ error: (...args) => console.error(prefix, ...args),
1337
+ fatal: (...args) => console.error(prefix, "FATAL:", ...args)
1338
+ };
1339
+ }
1340
+
1341
+ // src/dev-tools.js
1342
+ import { performanceMonitor } from "@coherent.js/core/src/performance/monitor.js";
1343
+ import { validateComponent as validateComponent2, isCoherentObject } from "@coherent.js/core/src/core/object-utils.js";
1344
+ var DevTools = class {
1345
+ constructor(coherentInstance) {
1346
+ this.coherent = coherentInstance;
1347
+ this.isEnabled = this.shouldEnable();
1348
+ this.renderHistory = [];
1349
+ this.componentRegistry = /* @__PURE__ */ new Map();
1350
+ this.warnings = [];
1351
+ this.errors = [];
1352
+ this.hotReloadEnabled = false;
1353
+ if (this.isEnabled) {
1354
+ this.initialize();
1355
+ }
1356
+ }
1357
+ /**
1358
+ * Check if dev tools should be enabled
1359
+ */
1360
+ shouldEnable() {
1361
+ if (typeof process !== "undefined") {
1362
+ return process.env.NODE_ENV === "development";
1363
+ }
1364
+ if (typeof window !== "undefined") {
1365
+ return window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.search.includes("dev=true");
1366
+ }
1367
+ return false;
1368
+ }
1369
+ /**
1370
+ * Initialize dev tools
1371
+ */
1372
+ initialize() {
1373
+ console.log("\u{1F6E0}\uFE0F Coherent.js Dev Tools Enabled");
1374
+ this.setupGlobalHelpers();
1375
+ this.setupRenderInterception();
1376
+ this.setupErrorHandling();
1377
+ this.setupHotReload();
1378
+ this.setupComponentInspector();
1379
+ if (typeof window !== "undefined") {
1380
+ this.setupBrowserDevTools();
1381
+ }
1382
+ if (typeof process !== "undefined") {
1383
+ this.setupNodeDevTools();
1384
+ }
1385
+ }
1386
+ /**
1387
+ * Set up global helper functions
1388
+ */
1389
+ setupGlobalHelpers() {
1390
+ const helpers = {
1391
+ // Inspect any component
1392
+ $inspect: (component) => this.inspectComponent(component),
1393
+ // Get render history
1394
+ $history: () => this.renderHistory,
1395
+ // Get performance stats
1396
+ $perf: () => this.getPerformanceInsights(),
1397
+ // Validate component structure
1398
+ $validate: (component) => this.validateComponent(component),
1399
+ // Get component registry
1400
+ $registry: () => Array.from(this.componentRegistry.entries()),
1401
+ // Clear dev data
1402
+ $clear: () => this.clearDevData(),
1403
+ // Enable/disable features
1404
+ $toggle: (feature) => this.toggleFeature(feature),
1405
+ // Get warnings and errors
1406
+ $issues: () => ({ warnings: this.warnings, errors: this.errors })
1407
+ };
1408
+ if (typeof window !== "undefined") {
1409
+ Object.assign(window, helpers);
1410
+ } else if (typeof global !== "undefined") {
1411
+ Object.assign(global, helpers);
1412
+ }
1413
+ }
1414
+ /**
1415
+ * Intercept render calls for debugging
1416
+ */
1417
+ setupRenderInterception() {
1418
+ const originalRender = this.coherent.render;
1419
+ this.coherent.render = (component, context = {}, options = {}) => {
1420
+ const renderStart = performance.now();
1421
+ const renderId = this.generateRenderId();
1422
+ try {
1423
+ this.preRenderAnalysis(component, context, renderId);
1424
+ const result = originalRender.call(this.coherent, component, context, {
1425
+ ...options,
1426
+ _devRenderId: renderId
1427
+ });
1428
+ const renderTime = performance.now() - renderStart;
1429
+ this.postRenderAnalysis(component, result, renderTime, renderId);
1430
+ return result;
1431
+ } catch (_error) {
1432
+ this.handleRenderError(_error, component, context, renderId);
1433
+ throw _error;
1434
+ }
1435
+ };
1436
+ }
1437
+ /**
1438
+ * Pre-render analysis and validation
1439
+ */
1440
+ preRenderAnalysis(component, context, renderId) {
1441
+ const validation = this.deepValidateComponent(component);
1442
+ if (!validation.isValid) {
1443
+ this.warnings.push({
1444
+ type: "validation",
1445
+ message: validation.message,
1446
+ component: this.serializeComponent(component),
1447
+ renderId,
1448
+ timestamp: Date.now()
1449
+ });
1450
+ }
1451
+ const complexity = this.analyzeComplexity(component);
1452
+ if (complexity > 1e3) {
1453
+ this.warnings.push({
1454
+ type: "performance",
1455
+ message: `High complexity component detected (${complexity} nodes)`,
1456
+ renderId,
1457
+ timestamp: Date.now()
1458
+ });
1459
+ }
1460
+ this.analyzeContext(context, renderId);
1461
+ }
1462
+ /**
1463
+ * Post-render analysis
1464
+ */
1465
+ postRenderAnalysis(component, result, renderTime, renderId) {
1466
+ const renderRecord = {
1467
+ id: renderId,
1468
+ timestamp: Date.now(),
1469
+ component: this.serializeComponent(component),
1470
+ renderTime,
1471
+ outputSize: result.length,
1472
+ complexity: this.analyzeComplexity(component)
1473
+ };
1474
+ this.renderHistory.push(renderRecord);
1475
+ if (this.renderHistory.length > 50) {
1476
+ this.renderHistory.shift();
1477
+ }
1478
+ if (renderTime > 10) {
1479
+ this.warnings.push({
1480
+ type: "performance",
1481
+ message: `Slow render detected: ${renderTime.toFixed(2)}ms`,
1482
+ renderId,
1483
+ timestamp: Date.now()
1484
+ });
1485
+ }
1486
+ if (renderTime > 1) {
1487
+ console.log(`\u{1F504} Render ${renderId}: ${renderTime.toFixed(2)}ms`);
1488
+ }
1489
+ }
1490
+ /**
1491
+ * Deep component validation
1492
+ */
1493
+ deepValidateComponent(component, path2 = "root", depth = 0) {
1494
+ if (depth > 100) {
1495
+ return {
1496
+ isValid: false,
1497
+ message: `Component nesting too deep at ${path2}`
1498
+ };
1499
+ }
1500
+ try {
1501
+ validateComponent2(component);
1502
+ } catch (_error) {
1503
+ return {
1504
+ isValid: false,
1505
+ message: `Invalid component at ${path2}: ${_error.message}`
1506
+ };
1507
+ }
1508
+ if (Array.isArray(component)) {
1509
+ for (let i = 0; i < component.length; i++) {
1510
+ const childValidation = this.deepValidateComponent(
1511
+ component[i],
1512
+ `${path2}[${i}]`,
1513
+ depth + 1
1514
+ );
1515
+ if (!childValidation.isValid) {
1516
+ return childValidation;
1517
+ }
1518
+ }
1519
+ } else if (isCoherentObject(component)) {
1520
+ for (const [tag, props] of Object.entries(component)) {
1521
+ if (props && typeof props === "object" && props.children) {
1522
+ const childValidation = this.deepValidateComponent(
1523
+ props.children,
1524
+ `${path2}.${tag}.children`,
1525
+ depth + 1
1526
+ );
1527
+ if (!childValidation.isValid) {
1528
+ return childValidation;
1529
+ }
1530
+ }
1531
+ }
1532
+ }
1533
+ return { isValid: true };
1534
+ }
1535
+ /**
1536
+ * Analyze component complexity
1537
+ */
1538
+ analyzeComplexity(component, depth = 0) {
1539
+ if (depth > 100) return 1e3;
1540
+ if (typeof component === "string" || typeof component === "number") {
1541
+ return 1;
1542
+ }
1543
+ if (Array.isArray(component)) {
1544
+ return component.reduce((sum, child) => sum + this.analyzeComplexity(child, depth + 1), 0);
1545
+ }
1546
+ if (isCoherentObject(component)) {
1547
+ let complexity = 1;
1548
+ for (const [, props] of Object.entries(component)) {
1549
+ if (props && typeof props === "object") {
1550
+ if (props.children) {
1551
+ complexity += this.analyzeComplexity(props.children, depth + 1);
1552
+ }
1553
+ if (typeof props.text === "function") {
1554
+ complexity += 2;
1555
+ }
1556
+ }
1557
+ }
1558
+ return complexity;
1559
+ }
1560
+ return 1;
1561
+ }
1562
+ /**
1563
+ * Context analysis
1564
+ */
1565
+ analyzeContext(context, renderId) {
1566
+ const contextSize = JSON.stringify(context).length;
1567
+ if (contextSize > 1e4) {
1568
+ this.warnings.push({
1569
+ type: "context",
1570
+ message: `Large context object: ${contextSize} characters`,
1571
+ renderId,
1572
+ timestamp: Date.now()
1573
+ });
1574
+ }
1575
+ try {
1576
+ JSON.stringify(context);
1577
+ } catch (_error) {
1578
+ if (_error.message.includes("circular")) {
1579
+ this.warnings.push({
1580
+ type: "context",
1581
+ message: "Circular reference detected in context",
1582
+ renderId,
1583
+ timestamp: Date.now()
1584
+ });
1585
+ }
1586
+ }
1587
+ }
1588
+ /**
1589
+ * Component inspector
1590
+ */
1591
+ inspectComponent(component) {
1592
+ return {
1593
+ type: this.getComponentType(component),
1594
+ complexity: this.analyzeComplexity(component),
1595
+ validation: this.deepValidateComponent(component),
1596
+ structure: this.visualizeStructure(component),
1597
+ serialized: this.serializeComponent(component),
1598
+ recommendations: this.getOptimizationRecommendations(component)
1599
+ };
1600
+ }
1601
+ /**
1602
+ * Get component type
1603
+ */
1604
+ getComponentType(component) {
1605
+ if (typeof component === "string") return "text";
1606
+ if (typeof component === "function") return "function";
1607
+ if (Array.isArray(component)) return "array";
1608
+ if (isCoherentObject(component)) return "element";
1609
+ return "unknown";
1610
+ }
1611
+ /**
1612
+ * Visualize component structure
1613
+ */
1614
+ visualizeStructure(component, depth = 0, maxDepth = 5) {
1615
+ if (depth > maxDepth) return "...";
1616
+ const indent = " ".repeat(depth);
1617
+ if (typeof component === "string") {
1618
+ return `${indent}"${component.substring(0, 20)}${component.length > 20 ? "..." : ""}"`;
1619
+ }
1620
+ if (Array.isArray(component)) {
1621
+ const items = component.slice(0, 3).map(
1622
+ (child) => this.visualizeStructure(child, depth + 1, maxDepth)
1623
+ );
1624
+ const more = component.length > 3 ? `${indent} ...${component.length - 3} more` : "";
1625
+ return `${indent}[
1626
+ ${items.join("\n")}${more ? `
1627
+ ${more}` : ""}
1628
+ ${indent}]`;
1629
+ }
1630
+ if (isCoherentObject(component)) {
1631
+ const entries = Object.entries(component).slice(0, 3);
1632
+ const elements = entries.map(([tag, props]) => {
1633
+ let result = `${indent}<${tag}`;
1634
+ if (props && props.children) {
1635
+ result += `>
1636
+ ${this.visualizeStructure(props.children, depth + 1, maxDepth)}
1637
+ ${indent}</${tag}>`;
1638
+ } else if (props && props.text) {
1639
+ result += `>${props.text}</${tag}>`;
1640
+ } else {
1641
+ result += " />";
1642
+ }
1643
+ return result;
1644
+ });
1645
+ return elements.join("\n");
1646
+ }
1647
+ return `${indent}${typeof component}`;
1648
+ }
1649
+ /**
1650
+ * Get optimization recommendations
1651
+ */
1652
+ getOptimizationRecommendations(component) {
1653
+ const recommendations = [];
1654
+ const complexity = this.analyzeComplexity(component);
1655
+ if (complexity > 500) {
1656
+ recommendations.push({
1657
+ type: "complexity",
1658
+ message: "Consider breaking down this component into smaller parts",
1659
+ priority: "high"
1660
+ });
1661
+ }
1662
+ const serialized = JSON.stringify(component);
1663
+ const patterns = this.findRepeatedPatterns(serialized);
1664
+ if (patterns.length > 0) {
1665
+ recommendations.push({
1666
+ type: "caching",
1667
+ message: "Consider extracting repeated patterns into cached components",
1668
+ priority: "medium",
1669
+ patterns: patterns.slice(0, 3)
1670
+ });
1671
+ }
1672
+ return recommendations;
1673
+ }
1674
+ /**
1675
+ * Find repeated patterns in component
1676
+ */
1677
+ findRepeatedPatterns(serialized) {
1678
+ const patterns = [];
1679
+ const minPatternLength = 20;
1680
+ for (let i = 0; i < serialized.length - minPatternLength; i++) {
1681
+ for (let len = minPatternLength; len <= 100 && i + len < serialized.length; len++) {
1682
+ const pattern = serialized.substring(i, i + len);
1683
+ const occurrences = (serialized.match(new RegExp(this.escapeRegex(pattern), "g")) || []).length;
1684
+ if (occurrences > 2) {
1685
+ patterns.push({ pattern: `${pattern.substring(0, 50)}...`, occurrences });
1686
+ break;
1687
+ }
1688
+ }
1689
+ }
1690
+ return patterns.sort((a, b) => b.occurrences - a.occurrences);
1691
+ }
1692
+ /**
1693
+ * Escape regex special characters
1694
+ */
1695
+ escapeRegex(string) {
1696
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1697
+ }
1698
+ /**
1699
+ * Setup _error handling
1700
+ */
1701
+ setupErrorHandling() {
1702
+ const originalConsoleError = console.error;
1703
+ console.error = (...args) => {
1704
+ this.errors.push({
1705
+ type: "console",
1706
+ message: args.join(" "),
1707
+ timestamp: Date.now(),
1708
+ stack: new Error().stack
1709
+ });
1710
+ originalConsoleError.apply(console, args);
1711
+ };
1712
+ if (typeof process !== "undefined") {
1713
+ process.on("unhandledRejection", (reason, promise) => {
1714
+ this.errors.push({
1715
+ type: "unhandled-rejection",
1716
+ message: reason.toString(),
1717
+ promise: promise.toString(),
1718
+ timestamp: Date.now()
1719
+ });
1720
+ });
1721
+ }
1722
+ if (typeof window !== "undefined") {
1723
+ window.addEventListener("_error", (event) => {
1724
+ this.errors.push({
1725
+ type: "browser-_error",
1726
+ message: event.message,
1727
+ filename: event.filename,
1728
+ lineno: event.lineno,
1729
+ colno: event.colno,
1730
+ timestamp: Date.now()
1731
+ });
1732
+ });
1733
+ }
1734
+ }
1735
+ /**
1736
+ * Handle render errors specifically
1737
+ */
1738
+ handleRenderError(_error, component, context, renderId) {
1739
+ this.errors.push({
1740
+ type: "render-_error",
1741
+ message: _error.message,
1742
+ stack: _error.stack,
1743
+ component: this.serializeComponent(component),
1744
+ context: Object.keys(context),
1745
+ renderId,
1746
+ timestamp: Date.now()
1747
+ });
1748
+ console.error(`\u{1F6A8} Render Error in ${renderId}:`, _error.message);
1749
+ console.error("Component:", this.serializeComponent(component));
1750
+ }
1751
+ /**
1752
+ * Setup hot reload capability
1753
+ */
1754
+ setupHotReload() {
1755
+ if (typeof window !== "undefined" && "WebSocket" in window) {
1756
+ this.setupBrowserHotReload();
1757
+ } else if (typeof __require !== "undefined") {
1758
+ this.setupNodeHotReload();
1759
+ }
1760
+ }
1761
+ /**
1762
+ * Browser hot reload setup
1763
+ */
1764
+ setupBrowserHotReload() {
1765
+ try {
1766
+ const ws = new WebSocket("ws://localhost:3001/coherent-dev");
1767
+ ws.onmessage = (event) => {
1768
+ const data = JSON.parse(event.data);
1769
+ if (data.type === "component-updated") {
1770
+ console.log("\u{1F504} Component updated:", data.componentName);
1771
+ this.handleComponentUpdate(data);
1772
+ } else if (data.type === "full-reload") {
1773
+ window.location.reload();
1774
+ }
1775
+ };
1776
+ ws.onopen = () => {
1777
+ console.log("\u{1F517} Connected to Coherent dev server");
1778
+ this.hotReloadEnabled = true;
1779
+ };
1780
+ ws.onclose = () => {
1781
+ console.log("\u{1F50C} Disconnected from dev server");
1782
+ this.hotReloadEnabled = false;
1783
+ };
1784
+ } catch {
1785
+ }
1786
+ }
1787
+ /**
1788
+ * Node.js hot reload setup
1789
+ */
1790
+ setupNodeHotReload() {
1791
+ try {
1792
+ const fs = __require("fs");
1793
+ const path2 = __require("path");
1794
+ const watchDir = path2.join(process.cwd(), "src");
1795
+ fs.watch(watchDir, { recursive: true }, (eventType, filename) => {
1796
+ if (filename && filename.endsWith(".js")) {
1797
+ console.log(`\u{1F504} File changed: ${filename}`);
1798
+ this.handleFileChange(filename, eventType);
1799
+ }
1800
+ });
1801
+ this.hotReloadEnabled = true;
1802
+ } catch {
1803
+ }
1804
+ }
1805
+ /**
1806
+ * Handle component updates
1807
+ */
1808
+ handleComponentUpdate(updateData) {
1809
+ if (this.coherent.cache) {
1810
+ this.coherent.cache.invalidatePattern(updateData.componentName);
1811
+ }
1812
+ this.componentRegistry.set(updateData.componentName, {
1813
+ ...updateData,
1814
+ lastUpdated: Date.now()
1815
+ });
1816
+ if (typeof window !== "undefined" && window.location.search.includes("auto-reload=true")) {
1817
+ window.location.reload();
1818
+ }
1819
+ }
1820
+ /**
1821
+ * Handle file changes
1822
+ */
1823
+ handleFileChange(filename, eventType) {
1824
+ if (typeof __require !== "undefined" && __require.cache) {
1825
+ const fullPath = __require.resolve(path.resolve(filename));
1826
+ delete __require.cache[fullPath];
1827
+ }
1828
+ console.log(`\u{1F4DD} ${eventType}: ${filename}`);
1829
+ }
1830
+ /**
1831
+ * Setup browser-specific dev tools
1832
+ */
1833
+ setupBrowserDevTools() {
1834
+ this.createDevPanel();
1835
+ document.addEventListener("keydown", (e) => {
1836
+ if (e.ctrlKey && e.shiftKey && e.code === "KeyC") {
1837
+ this.toggleDevPanel();
1838
+ e.preventDefault();
1839
+ }
1840
+ if (e.ctrlKey && e.shiftKey && e.code === "KeyP") {
1841
+ console.table(this.getPerformanceInsights());
1842
+ e.preventDefault();
1843
+ }
1844
+ });
1845
+ }
1846
+ /**
1847
+ * Create development panel in browser
1848
+ */
1849
+ createDevPanel() {
1850
+ const panel = document.createElement("div");
1851
+ panel.id = "coherent-dev-panel";
1852
+ panel.style.cssText = `
1853
+ position: fixed;
1854
+ top: 10px;
1855
+ right: 10px;
1856
+ width: 300px;
1857
+ background: #1a1a1a;
1858
+ color: #fff;
1859
+ font-family: monospace;
1860
+ font-size: 12px;
1861
+ border-radius: 8px;
1862
+ box-shadow: 0 4px 20px rgba(0,0,0,0.5);
1863
+ z-index: 999999;
1864
+ display: none;
1865
+ max-height: 80vh;
1866
+ overflow-y: auto;
1867
+ `;
1868
+ document.body.appendChild(panel);
1869
+ this.devPanel = panel;
1870
+ this.updateDevPanel();
1871
+ }
1872
+ /**
1873
+ * Toggle dev panel visibility
1874
+ */
1875
+ toggleDevPanel() {
1876
+ if (this.devPanel) {
1877
+ const isVisible = this.devPanel.style.display === "block";
1878
+ this.devPanel.style.display = isVisible ? "none" : "block";
1879
+ if (!isVisible) {
1880
+ this.updateDevPanel();
1881
+ }
1882
+ }
1883
+ }
1884
+ /**
1885
+ * Update dev panel content
1886
+ */
1887
+ updateDevPanel() {
1888
+ if (!this.devPanel) return;
1889
+ const stats = this.getPerformanceInsights();
1890
+ const recentRenders = this.renderHistory.slice(-5);
1891
+ const recentWarnings = this.warnings.slice(-3);
1892
+ this.devPanel.innerHTML = `
1893
+ <div style="padding: 15px; border-bottom: 1px solid #333;">
1894
+ <strong>\u{1F6E0}\uFE0F Coherent.js Dev Tools</strong>
1895
+ <button onclick="this.parentElement.parentElement.style.display='none'"
1896
+ style="float: right; background: none; border: none; color: #fff; cursor: pointer;">\xD7</button>
1897
+ </div>
1898
+
1899
+ <div style="padding: 10px;">
1900
+ <h4 style="margin: 0 0 10px 0; color: #4CAF50;">Performance</h4>
1901
+ <div style="font-size: 11px;">
1902
+ <div>Avg Render: ${stats.averageRenderTime || 0}ms</div>
1903
+ <div>Cache Hit Rate: ${((stats.cacheHits || 0) / Math.max(stats.totalRenders || 1, 1) * 100).toFixed(1)}%</div>
1904
+ <div>Memory Usage: ${(performance.memory?.usedJSHeapSize / 1024 / 1024 || 0).toFixed(1)}MB</div>
1905
+ </div>
1906
+ </div>
1907
+
1908
+ <div style="padding: 10px;">
1909
+ <h4 style="margin: 0 0 10px 0; color: #2196F3;">Recent Renders</h4>
1910
+ ${recentRenders.map((r) => `
1911
+ <div style="font-size: 10px; margin-bottom: 5px; padding: 3px; background: #333; border-radius: 3px;">
1912
+ ${r.id}: ${r.renderTime.toFixed(1)}ms (${r.complexity} nodes)
1913
+ </div>
1914
+ `).join("")}
1915
+ </div>
1916
+
1917
+ ${recentWarnings.length > 0 ? `
1918
+ <div style="padding: 10px;">
1919
+ <h4 style="margin: 0 0 10px 0; color: #FF9800;">Warnings</h4>
1920
+ ${recentWarnings.map((w) => `
1921
+ <div style="font-size: 10px; margin-bottom: 5px; padding: 3px; background: #4a2c0a; border-radius: 3px; color: #FFB74D;">
1922
+ ${w.type}: ${w.message}
1923
+ </div>
1924
+ `).join("")}
1925
+ </div>
1926
+ ` : ""}
1927
+
1928
+ <div style="padding: 10px; font-size: 10px; color: #888;">
1929
+ Press Ctrl+Shift+P for performance details
1930
+ </div>
1931
+ `;
1932
+ }
1933
+ /**
1934
+ * Setup Node.js specific dev tools
1935
+ */
1936
+ setupNodeDevTools() {
1937
+ process.on("SIGINT", () => {
1938
+ this.printDevSummary();
1939
+ process.exit();
1940
+ });
1941
+ }
1942
+ /**
1943
+ * Print development summary
1944
+ */
1945
+ printDevSummary() {
1946
+ console.log("\n\u{1F6E0}\uFE0F Coherent.js Development Summary");
1947
+ console.log("=================================");
1948
+ console.log(`Total Renders: ${this.renderHistory.length}`);
1949
+ console.log(`Total Warnings: ${this.warnings.length}`);
1950
+ console.log(`Total Errors: ${this.errors.length}`);
1951
+ if (this.renderHistory.length > 0) {
1952
+ const avgTime = this.renderHistory.reduce((sum, r) => sum + r.renderTime, 0) / this.renderHistory.length;
1953
+ console.log(`Average Render Time: ${avgTime.toFixed(2)}ms`);
1954
+ }
1955
+ console.log("=================================\n");
1956
+ }
1957
+ /**
1958
+ * Get performance insights
1959
+ */
1960
+ getPerformanceInsights() {
1961
+ const insights = {
1962
+ totalRenders: this.renderHistory.length,
1963
+ averageRenderTime: 0,
1964
+ slowestRender: null,
1965
+ fastestRender: null,
1966
+ cacheHits: 0,
1967
+ totalWarnings: this.warnings.length,
1968
+ totalErrors: this.errors.length
1969
+ };
1970
+ if (this.renderHistory.length > 0) {
1971
+ const times = this.renderHistory.map((r) => r.renderTime);
1972
+ insights.averageRenderTime = times.reduce((a, b) => a + b, 0) / times.length;
1973
+ insights.slowestRender = Math.max(...times);
1974
+ insights.fastestRender = Math.min(...times);
1975
+ }
1976
+ if (this.coherent.cache && this.coherent.cache.getStats) {
1977
+ const cacheStats = this.coherent.cache.getStats();
1978
+ insights.cacheHits = cacheStats.hits;
1979
+ insights.cacheHitRate = cacheStats.hitRate;
1980
+ }
1981
+ if (performanceMonitor && performanceMonitor.getStats) {
1982
+ const perfStats = performanceMonitor.getStats();
1983
+ insights.performanceMonitorStats = perfStats;
1984
+ }
1985
+ return insights;
1986
+ }
1987
+ /**
1988
+ * Utility methods
1989
+ */
1990
+ generateRenderId() {
1991
+ return `render_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
1992
+ }
1993
+ serializeComponent(component, maxDepth = 3, currentDepth = 0) {
1994
+ if (currentDepth > maxDepth) return "...";
1995
+ try {
1996
+ if (typeof component === "function") {
1997
+ return `[Function: ${component.name || "anonymous"}]`;
1998
+ }
1999
+ if (Array.isArray(component)) {
2000
+ return component.slice(0, 3).map(
2001
+ (c) => this.serializeComponent(c, maxDepth, currentDepth + 1)
2002
+ ).concat(component.length > 3 ? [`...(${component.length - 3} more)`] : []);
2003
+ }
2004
+ if (component && typeof component === "object") {
2005
+ const serialized = {};
2006
+ const keys = Object.keys(component).slice(0, 10);
2007
+ for (const key of keys) {
2008
+ if (key === "children" && component[key]) {
2009
+ serialized[key] = this.serializeComponent(component[key], maxDepth, currentDepth + 1);
2010
+ } else if (typeof component[key] === "function") {
2011
+ serialized[key] = `[Function: ${component[key].name || "anonymous"}]`;
2012
+ } else {
2013
+ serialized[key] = component[key];
2014
+ }
2015
+ }
2016
+ if (Object.keys(component).length > 10) {
2017
+ serialized["..."] = `(${Object.keys(component).length - 10} more properties)`;
2018
+ }
2019
+ return serialized;
2020
+ }
2021
+ return component;
2022
+ } catch (_error) {
2023
+ return `[Serialization Error: ${_error.message}]`;
2024
+ }
2025
+ }
2026
+ clearDevData() {
2027
+ this.renderHistory = [];
2028
+ this.warnings = [];
2029
+ this.errors = [];
2030
+ this.componentRegistry.clear();
2031
+ console.log("\u{1F9F9} Dev data cleared");
2032
+ }
2033
+ toggleFeature(feature) {
2034
+ switch (feature) {
2035
+ case "cache":
2036
+ if (this.coherent.cache) {
2037
+ this.coherent.cache.enabled = !this.coherent.cache.enabled;
2038
+ console.log(`Cache ${this.coherent.cache.enabled ? "enabled" : "disabled"}`);
2039
+ }
2040
+ break;
2041
+ case "monitoring":
2042
+ if (performanceMonitor) {
2043
+ performanceMonitor.enabled = !performanceMonitor.enabled;
2044
+ console.log(`Monitoring ${performanceMonitor.enabled ? "enabled" : "disabled"}`);
2045
+ }
2046
+ break;
2047
+ case "hot-reload":
2048
+ this.hotReloadEnabled = !this.hotReloadEnabled;
2049
+ console.log(`Hot reload ${this.hotReloadEnabled ? "enabled" : "disabled"}`);
2050
+ break;
2051
+ default:
2052
+ console.log(`Unknown feature: ${feature}`);
2053
+ }
2054
+ }
2055
+ validateComponent(component) {
2056
+ return this.deepValidateComponent(component);
2057
+ }
2058
+ setupComponentInspector() {
2059
+ const originalCreateComponent = this.coherent.createComponent;
2060
+ if (originalCreateComponent) {
2061
+ this.coherent.createComponent = (config) => {
2062
+ const component = originalCreateComponent.call(this.coherent, config);
2063
+ this.componentRegistry.set(config.name || "anonymous", {
2064
+ config,
2065
+ component,
2066
+ registeredAt: Date.now()
2067
+ });
2068
+ return component;
2069
+ };
2070
+ }
2071
+ }
2072
+ };
2073
+ function createDevTools(coherentInstance) {
2074
+ return new DevTools(coherentInstance);
2075
+ }
2076
+
2077
+ // src/index.js
2078
+ var index_default = {
2079
+ // Inspector
2080
+ ComponentInspector,
2081
+ createInspector,
2082
+ inspect,
2083
+ validateComponent,
2084
+ // Profiler
2085
+ PerformanceProfiler,
2086
+ createProfiler,
2087
+ measure,
2088
+ profile,
2089
+ // Logger
2090
+ DevLogger,
2091
+ LogLevel,
2092
+ createLogger,
2093
+ createComponentLogger,
2094
+ createConsoleLogger,
2095
+ // DevTools
2096
+ DevTools,
2097
+ createDevTools
2098
+ };
2099
+ export {
2100
+ ComponentInspector,
2101
+ DevLogger,
2102
+ DevTools,
2103
+ LogLevel,
2104
+ PerformanceProfiler,
2105
+ createComponentLogger,
2106
+ createConsoleLogger,
2107
+ createDevTools,
2108
+ createInspector,
2109
+ createLogger,
2110
+ createProfiler,
2111
+ index_default as default,
2112
+ inspect,
2113
+ measure,
2114
+ profile,
2115
+ validateComponent
2116
+ };
2117
+ //# sourceMappingURL=index.js.map