@coherent.js/devtools 1.0.0-beta.3 → 1.0.0-beta.6

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 CHANGED
@@ -2074,44 +2074,1259 @@ function createDevTools(coherentInstance) {
2074
2074
  return new DevTools(coherentInstance);
2075
2075
  }
2076
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
2077
+ // src/component-visualizer.js
2078
+ import {
2079
+ isCoherentObject as isCoherentObject2,
2080
+ hasChildren,
2081
+ normalizeChildren
2082
+ } from "@coherent.js/core";
2083
+ var ComponentVisualizer = class {
2084
+ constructor(options = {}) {
2085
+ this.options = {
2086
+ maxDepth: options.maxDepth || 50,
2087
+ showProps: options.showProps !== false,
2088
+ showMetadata: options.showMetadata !== false,
2089
+ colorOutput: options.colorOutput !== false,
2090
+ compactMode: options.compactMode || false,
2091
+ ...options
2092
+ };
2093
+ this.stats = {
2094
+ totalComponents: 0,
2095
+ totalDepth: 0,
2096
+ staticComponents: 0,
2097
+ dynamicComponents: 0,
2098
+ renderTime: 0
2099
+ };
2100
+ }
2101
+ /**
2102
+ * Visualize a component tree
2103
+ */
2104
+ visualize(component, name = "Root") {
2105
+ const startTime = performance.now();
2106
+ this.stats = { totalComponents: 0, totalDepth: 0, staticComponents: 0, dynamicComponents: 0, renderTime: 0 };
2107
+ const tree = this.buildTree(component, name, 0);
2108
+ const visualization = this.renderTree(tree);
2109
+ this.stats.renderTime = performance.now() - startTime;
2110
+ return {
2111
+ visualization,
2112
+ stats: { ...this.stats },
2113
+ tree
2114
+ };
2115
+ }
2116
+ /**
2117
+ * Build component tree structure
2118
+ */
2119
+ buildTree(component, name, depth) {
2120
+ if (depth > this.options.maxDepth) {
2121
+ return {
2122
+ name: "MAX_DEPTH_REACHED",
2123
+ type: "warning",
2124
+ depth,
2125
+ children: [],
2126
+ metadata: { message: `Maximum depth ${this.options.maxDepth} exceeded` }
2127
+ };
2128
+ }
2129
+ this.stats.totalComponents++;
2130
+ this.stats.totalDepth = Math.max(this.stats.totalDepth, depth);
2131
+ const node = {
2132
+ name,
2133
+ depth,
2134
+ children: [],
2135
+ metadata: {}
2136
+ };
2137
+ if (component === null || component === void 0) {
2138
+ node.type = "empty";
2139
+ node.value = "";
2140
+ this.stats.staticComponents++;
2141
+ } else if (typeof component === "string") {
2142
+ node.type = "text";
2143
+ node.value = component;
2144
+ node.metadata.length = component.length;
2145
+ this.stats.staticComponents++;
2146
+ } else if (typeof component === "number") {
2147
+ node.type = "number";
2148
+ node.value = component;
2149
+ this.stats.staticComponents++;
2150
+ } else if (typeof component === "boolean") {
2151
+ node.type = "boolean";
2152
+ node.value = component;
2153
+ this.stats.staticComponents++;
2154
+ } else if (typeof component === "function") {
2155
+ node.type = "function";
2156
+ node.value = `Function: ${component.name || "anonymous"}`;
2157
+ node.metadata.arity = component.length;
2158
+ node.metadata.isAsync = component.constructor.name === "AsyncFunction";
2159
+ this.stats.dynamicComponents++;
2160
+ } else if (Array.isArray(component)) {
2161
+ node.type = "array";
2162
+ node.metadata.length = component.length;
2163
+ component.forEach((item, _index) => {
2164
+ const childNode = this.buildTree(item, `[${_index}]`, depth + 1);
2165
+ node.children.push(childNode);
2166
+ });
2167
+ this.stats.dynamicComponents++;
2168
+ } else if (isCoherentObject2(component)) {
2169
+ const entries = Object.entries(component);
2170
+ if (entries.length === 1) {
2171
+ const [tagName, props] = entries;
2172
+ node.type = "element";
2173
+ node.tagName = tagName;
2174
+ node.props = this.options.showProps ? this.analyzeProps(props) : {};
2175
+ if (hasChildren(props)) {
2176
+ const children = normalizeChildren(props.children);
2177
+ children.forEach((child, _index) => {
2178
+ const childNode = this.buildTree(child, `${tagName}[${_index}]`, depth + 1);
2179
+ node.children.push(childNode);
2180
+ });
2181
+ }
2182
+ if (this.hasDynamicContent(props)) {
2183
+ this.stats.dynamicComponents++;
2184
+ node.metadata.dynamic = true;
2185
+ } else {
2186
+ this.stats.staticComponents++;
2187
+ node.metadata.dynamic = false;
2188
+ }
2189
+ } else {
2190
+ node.type = "complex";
2191
+ node.metadata.keys = entries.map(([key]) => key);
2192
+ this.stats.dynamicComponents++;
2193
+ }
2194
+ } else {
2195
+ node.type = "unknown";
2196
+ node.value = String(component);
2197
+ node.metadata.constructor = component.constructor?.name || "Object";
2198
+ this.stats.staticComponents++;
2199
+ }
2200
+ return node;
2201
+ }
2202
+ /**
2203
+ * Analyze component props
2204
+ */
2205
+ analyzeProps(props) {
2206
+ const analyzed = {};
2207
+ if (!props || typeof props !== "object") {
2208
+ return analyzed;
2209
+ }
2210
+ Object.entries(props).forEach(([key, value]) => {
2211
+ if (key === "children") return;
2212
+ if (typeof value === "function") {
2213
+ analyzed[key] = {
2214
+ type: "function",
2215
+ name: value.name || "anonymous",
2216
+ isEvent: /^on[A-Z]/.test(key)
2217
+ };
2218
+ } else if (typeof value === "string") {
2219
+ analyzed[key] = {
2220
+ type: "string",
2221
+ length: value.length,
2222
+ preview: value.length > 50 ? `${value.substring(0, 47)}...` : value
2223
+ };
2224
+ } else if (typeof value === "object" && value !== null) {
2225
+ analyzed[key] = {
2226
+ type: "object",
2227
+ keys: Object.keys(value),
2228
+ constructor: value.constructor?.name || "Object"
2229
+ };
2230
+ } else {
2231
+ analyzed[key] = {
2232
+ type: typeof value,
2233
+ value
2234
+ };
2235
+ }
2236
+ });
2237
+ return analyzed;
2238
+ }
2239
+ /**
2240
+ * Check if component has dynamic content
2241
+ */
2242
+ hasDynamicContent(props) {
2243
+ if (typeof props === "object" && props !== null) {
2244
+ for (const value of Object.values(props)) {
2245
+ if (typeof value === "function") return true;
2246
+ if (typeof value === "object" && this.hasDynamicContent(value)) return true;
2247
+ }
2248
+ }
2249
+ return false;
2250
+ }
2251
+ /**
2252
+ * Render tree as formatted text
2253
+ */
2254
+ renderTree(tree) {
2255
+ const lines = [];
2256
+ if (this.options.colorOutput) {
2257
+ lines.push(this.colorize("\u{1F333} Coherent.js Component Tree", "cyan"));
2258
+ lines.push(this.colorize("\u2550".repeat(40), "cyan"));
2259
+ } else {
2260
+ lines.push("\u{1F333} Coherent.js Component Tree");
2261
+ lines.push("\u2550".repeat(40));
2262
+ }
2263
+ this.renderNode(tree, lines, "", true);
2264
+ if (this.options.showMetadata) {
2265
+ lines.push("");
2266
+ lines.push("\u{1F4CA} Tree Statistics:");
2267
+ lines.push(` Total Components: ${this.stats.totalComponents}`);
2268
+ lines.push(` Max Depth: ${this.stats.totalDepth}`);
2269
+ lines.push(` Static Components: ${this.stats.staticComponents}`);
2270
+ lines.push(` Dynamic Components: ${this.stats.dynamicComponents}`);
2271
+ lines.push(` Render Time: ${this.stats.renderTime.toFixed(2)}ms`);
2272
+ }
2273
+ return lines.join("\n");
2274
+ }
2275
+ /**
2276
+ * Render individual node
2277
+ */
2278
+ renderNode(node, lines, prefix = "", isLast = true) {
2279
+ const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
2280
+ const childPrefix = prefix + (isLast ? " " : "\u2502 ");
2281
+ let nodeLine = prefix + connector;
2282
+ if (this.options.colorOutput) {
2283
+ nodeLine += this.getNodeIcon(node.type);
2284
+ nodeLine += this.colorize(node.name, this.getNodeColor(node.type));
2285
+ } else {
2286
+ nodeLine += this.getNodeIcon(node.type) + node.name;
2287
+ }
2288
+ if (!this.options.compactMode) {
2289
+ nodeLine += ` (${node.type})`;
2290
+ if (node.type === "element") {
2291
+ nodeLine += ` <${node.tagName}>`;
2292
+ } else if (node.type === "text" && node.value) {
2293
+ nodeLine += `: "${node.value.substring(0, 30)}${node.value.length > 30 ? "..." : ""}"`;
2294
+ } else if (node.type === "function") {
2295
+ nodeLine += `(${node.metadata.arity || 0} args)`;
2296
+ }
2297
+ if (node.metadata.dynamic !== void 0) {
2298
+ nodeLine += node.metadata.dynamic ? " \u{1F504}" : " \u{1F4CC}";
2299
+ }
2300
+ }
2301
+ lines.push(nodeLine);
2302
+ if (this.options.showProps && node.props && !this.options.compactMode) {
2303
+ Object.entries(node.props).forEach(([key, prop], _index) => {
2304
+ const isLastProp = _index === Object.keys(node.props).length - 1;
2305
+ const propConnector = isLastProp ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
2306
+ const _propPrefix = childPrefix + (isLastProp && node.children.length === 0 ? " " : "\u2502 ");
2307
+ let propLine = childPrefix + propConnector;
2308
+ if (this.options.colorOutput) {
2309
+ propLine += this.colorize(key, "yellow");
2310
+ } else {
2311
+ propLine += key;
2312
+ }
2313
+ propLine += `: ${this.formatPropValue(prop)}`;
2314
+ lines.push(propLine);
2315
+ });
2316
+ }
2317
+ node.children.forEach((child, index) => {
2318
+ const isLastChild = index === node.children.length - 1;
2319
+ this.renderNode(child, lines, childPrefix, isLastChild);
2320
+ });
2321
+ }
2322
+ /**
2323
+ * Get node icon based on type
2324
+ */
2325
+ getNodeIcon(type) {
2326
+ const icons = {
2327
+ element: "\u{1F3F7}\uFE0F ",
2328
+ text: "\u{1F4DD} ",
2329
+ function: "\u26A1 ",
2330
+ array: "\u{1F4CB} ",
2331
+ empty: "\u2B55 ",
2332
+ number: "\u{1F522} ",
2333
+ boolean: "\u2611\uFE0F ",
2334
+ complex: "\u{1F4E6} ",
2335
+ unknown: "\u2753 ",
2336
+ warning: "\u26A0\uFE0F "
2337
+ };
2338
+ return icons[type] || "\u{1F4C4} ";
2339
+ }
2340
+ /**
2341
+ * Get node color based on type
2342
+ */
2343
+ getNodeColor(type) {
2344
+ const colors = {
2345
+ element: "green",
2346
+ text: "blue",
2347
+ function: "magenta",
2348
+ array: "cyan",
2349
+ empty: "gray",
2350
+ number: "yellow",
2351
+ boolean: "yellow",
2352
+ complex: "red",
2353
+ unknown: "red",
2354
+ warning: "red"
2355
+ };
2356
+ return colors[type] || "white";
2357
+ }
2358
+ /**
2359
+ * Format property value for display
2360
+ */
2361
+ formatPropValue(prop) {
2362
+ if (prop.type === "function") {
2363
+ return `\u26A1 ${prop.name}${prop.isEvent ? " (event)" : ""}`;
2364
+ } else if (prop.type === "string") {
2365
+ return `"${prop.preview}"`;
2366
+ } else if (prop.type === "object") {
2367
+ return `${prop.constructor} {${prop.keys.join(", ")}}`;
2368
+ } else {
2369
+ return String(prop.value);
2370
+ }
2371
+ }
2372
+ /**
2373
+ * Add color to text (ANSI colors)
2374
+ */
2375
+ colorize(text, color) {
2376
+ const colors = {
2377
+ black: "\x1B[30m",
2378
+ red: "\x1B[31m",
2379
+ green: "\x1B[32m",
2380
+ yellow: "\x1B[33m",
2381
+ blue: "\x1B[34m",
2382
+ magenta: "\x1B[35m",
2383
+ cyan: "\x1B[36m",
2384
+ white: "\x1B[37m",
2385
+ gray: "\x1B[90m"
2386
+ };
2387
+ const reset = "\x1B[0m";
2388
+ return `${colors[color] || ""}${text}${reset}`;
2389
+ }
2390
+ /**
2391
+ * Export tree as JSON for further analysis
2392
+ */
2393
+ exportAsJSON(tree) {
2394
+ return JSON.stringify(tree, null, 2);
2395
+ }
2396
+ /**
2397
+ * Export tree as DOT format for Graphviz
2398
+ */
2399
+ exportAsDOT(tree) {
2400
+ const lines = ["digraph ComponentTree {"];
2401
+ lines.push(" rankdir=TB;");
2402
+ lines.push(" node [shape=box, style=rounded];");
2403
+ this.generateDOTNodes(tree, lines, "root");
2404
+ lines.push("}");
2405
+ return lines.join("\n");
2406
+ }
2407
+ /**
2408
+ * Generate DOT nodes
2409
+ */
2410
+ generateDOTNodes(node, lines, parentId) {
2411
+ const nodeId = `${parentId}_${node.name.replace(/[^a-zA-Z0-9]/g, "_")}`;
2412
+ let label = node.name;
2413
+ if (node.type === "element") {
2414
+ label = `<${node.tagName}>\\n${node.name}`;
2415
+ }
2416
+ lines.push(` "${nodeId}" [label="${label}"];`);
2417
+ if (parentId !== "root") {
2418
+ lines.push(` "${parentId}" -> "${nodeId}";`);
2419
+ }
2420
+ node.children.forEach((child, _index) => {
2421
+ this.generateDOTNodes(child, lines, nodeId);
2422
+ });
2423
+ }
2424
+ };
2425
+ function createComponentVisualizer(options = {}) {
2426
+ return new ComponentVisualizer(options);
2427
+ }
2428
+ function visualizeComponent(component, name = "Root", options = {}) {
2429
+ const visualizer = createComponentVisualizer(options);
2430
+ return visualizer.visualize(component, name);
2431
+ }
2432
+ function logComponentTree(component, name = "Root", options = {}) {
2433
+ const result = visualizeComponent(component, name, options);
2434
+ console.log(result.visualization);
2435
+ return result;
2436
+ }
2437
+
2438
+ // src/performance-dashboard.js
2439
+ var PerformanceDashboard = class {
2440
+ constructor(options = {}) {
2441
+ this.options = {
2442
+ updateInterval: options.updateInterval || 5e3,
2443
+ maxHistoryPoints: options.maxHistoryPoints || 100,
2444
+ enableAlerts: options.enableAlerts !== false,
2445
+ enableRecommendations: options.enableRecommendations !== false,
2446
+ colorOutput: options.colorOutput !== false,
2447
+ ...options
2448
+ };
2449
+ this.metrics = {
2450
+ api: {
2451
+ requests: 0,
2452
+ averageTime: 0,
2453
+ cacheHits: 0,
2454
+ cacheMisses: 0,
2455
+ staticRoutes: 0,
2456
+ dynamicRoutes: 0,
2457
+ history: []
2458
+ },
2459
+ components: {
2460
+ renders: 0,
2461
+ averageTime: 0,
2462
+ cacheHits: 0,
2463
+ cacheMisses: 0,
2464
+ staticComponents: 0,
2465
+ dynamicComponents: 0,
2466
+ memoryUsage: 0,
2467
+ history: []
2468
+ },
2469
+ fullstack: {
2470
+ totalRequests: 0,
2471
+ averageTime: 0,
2472
+ errors: 0,
2473
+ bottlenecks: [],
2474
+ history: []
2475
+ }
2476
+ };
2477
+ this.alerts = [];
2478
+ this.recommendations = [];
2479
+ this.startTime = Date.now();
2480
+ this.updateTimer = null;
2481
+ }
2482
+ /**
2483
+ * Start monitoring performance
2484
+ */
2485
+ startMonitoring() {
2486
+ if (this.updateTimer) return;
2487
+ this.updateTimer = setInterval(() => {
2488
+ this.updateMetrics();
2489
+ this.generateAlerts();
2490
+ this.generateRecommendations();
2491
+ }, this.options.updateInterval);
2492
+ }
2493
+ /**
2494
+ * Stop monitoring
2495
+ */
2496
+ stopMonitoring() {
2497
+ if (this.updateTimer) {
2498
+ clearInterval(this.updateTimer);
2499
+ this.updateTimer = null;
2500
+ }
2501
+ }
2502
+ /**
2503
+ * Record API request metrics
2504
+ */
2505
+ recordAPIRequest(duration, routeType, cacheHit = false) {
2506
+ this.metrics.api.requests++;
2507
+ this.metrics.api.averageTime = this.updateAverage(
2508
+ this.metrics.api.averageTime,
2509
+ duration,
2510
+ this.metrics.api.requests
2511
+ );
2512
+ if (cacheHit) {
2513
+ this.metrics.api.cacheHits++;
2514
+ } else {
2515
+ this.metrics.api.cacheMisses++;
2516
+ }
2517
+ if (routeType === "static") {
2518
+ this.metrics.api.staticRoutes++;
2519
+ } else {
2520
+ this.metrics.api.dynamicRoutes++;
2521
+ }
2522
+ this.addToHistory("api", {
2523
+ timestamp: Date.now(),
2524
+ duration,
2525
+ routeType,
2526
+ cacheHit
2527
+ });
2528
+ }
2529
+ /**
2530
+ * Record component render metrics
2531
+ */
2532
+ recordComponentRender(duration, componentType, cacheHit = false, memoryDelta = 0) {
2533
+ this.metrics.components.renders++;
2534
+ this.metrics.components.averageTime = this.updateAverage(
2535
+ this.metrics.components.averageTime,
2536
+ duration,
2537
+ this.metrics.components.renders
2538
+ );
2539
+ if (cacheHit) {
2540
+ this.metrics.components.cacheHits++;
2541
+ } else {
2542
+ this.metrics.components.cacheMisses++;
2543
+ }
2544
+ if (componentType === "static") {
2545
+ this.metrics.components.staticComponents++;
2546
+ } else {
2547
+ this.metrics.components.dynamicComponents++;
2548
+ }
2549
+ this.metrics.components.memoryUsage += memoryDelta;
2550
+ this.addToHistory("components", {
2551
+ timestamp: Date.now(),
2552
+ duration,
2553
+ componentType,
2554
+ cacheHit,
2555
+ memoryDelta
2556
+ });
2557
+ }
2558
+ /**
2559
+ * Record full-stack request metrics
2560
+ */
2561
+ recordFullStackRequest(duration, error = null, bottlenecks = []) {
2562
+ this.metrics.fullstack.totalRequests++;
2563
+ this.metrics.fullstack.averageTime = this.updateAverage(
2564
+ this.metrics.fullstack.averageTime,
2565
+ duration,
2566
+ this.metrics.fullstack.totalRequests
2567
+ );
2568
+ if (error) {
2569
+ this.metrics.fullstack.errors++;
2570
+ }
2571
+ this.metrics.fullstack.bottlenecks = bottlenecks;
2572
+ this.addToHistory("fullstack", {
2573
+ timestamp: Date.now(),
2574
+ duration,
2575
+ error,
2576
+ bottlenecks
2577
+ });
2578
+ }
2579
+ /**
2580
+ * Update metrics from external sources
2581
+ */
2582
+ updateMetrics() {
2583
+ const now = Date.now();
2584
+ const uptime = now - this.startTime;
2585
+ const apiRate = this.metrics.api.requests / (uptime / 1e3);
2586
+ const componentRate = this.metrics.components.renders / (uptime / 1e3);
2587
+ const fullStackRate = this.metrics.fullstack.totalRequests / (uptime / 1e3);
2588
+ return {
2589
+ apiRate,
2590
+ componentRate,
2591
+ fullStackRate,
2592
+ uptime
2593
+ };
2594
+ }
2595
+ /**
2596
+ * Generate performance alerts
2597
+ */
2598
+ generateAlerts() {
2599
+ this.alerts = [];
2600
+ if (this.metrics.api.averageTime > 50) {
2601
+ this.alerts.push({
2602
+ type: "warning",
2603
+ category: "api",
2604
+ message: `API response time is high: ${this.metrics.api.averageTime.toFixed(2)}ms`,
2605
+ threshold: 50,
2606
+ current: this.metrics.api.averageTime
2607
+ });
2608
+ }
2609
+ const apiCacheHitRate = this.getCacheHitRate("api");
2610
+ if (apiCacheHitRate < 80) {
2611
+ this.alerts.push({
2612
+ type: "warning",
2613
+ category: "api",
2614
+ message: `API cache hit rate is low: ${apiCacheHitRate.toFixed(1)}%`,
2615
+ threshold: 80,
2616
+ current: apiCacheHitRate
2617
+ });
2618
+ }
2619
+ if (this.metrics.components.averageTime > 20) {
2620
+ this.alerts.push({
2621
+ type: "warning",
2622
+ category: "components",
2623
+ message: `Component render time is high: ${this.metrics.components.averageTime.toFixed(2)}ms`,
2624
+ threshold: 20,
2625
+ current: this.metrics.components.averageTime
2626
+ });
2627
+ }
2628
+ const componentCacheHitRate = this.getCacheHitRate("components");
2629
+ if (componentCacheHitRate < 90) {
2630
+ this.alerts.push({
2631
+ type: "warning",
2632
+ category: "components",
2633
+ message: `Component cache hit rate is low: ${componentCacheHitRate.toFixed(1)}%`,
2634
+ threshold: 90,
2635
+ current: componentCacheHitRate
2636
+ });
2637
+ }
2638
+ if (this.metrics.fullstack.errors > 0) {
2639
+ this.alerts.push({
2640
+ type: "error",
2641
+ category: "fullstack",
2642
+ message: `${this.metrics.fullstack.errors} errors detected`,
2643
+ threshold: 0,
2644
+ current: this.metrics.fullstack.errors
2645
+ });
2646
+ }
2647
+ }
2648
+ /**
2649
+ * Generate performance recommendations
2650
+ */
2651
+ generateRecommendations() {
2652
+ this.recommendations = [];
2653
+ const staticRouteRatio = this.metrics.api.staticRoutes / Math.max(this.metrics.api.requests, 1);
2654
+ if (staticRouteRatio < 0.7) {
2655
+ this.recommendations.push({
2656
+ type: "optimization",
2657
+ category: "api",
2658
+ message: "Consider adding more static routes to improve smart routing efficiency",
2659
+ impact: "high",
2660
+ effort: "low"
2661
+ });
2662
+ }
2663
+ const apiCacheHitRate = this.getCacheHitRate("api");
2664
+ if (apiCacheHitRate < 90) {
2665
+ this.recommendations.push({
2666
+ type: "optimization",
2667
+ category: "api",
2668
+ message: "Increase API cache size or TTL to improve cache hit rate",
2669
+ impact: "medium",
2670
+ effort: "low"
2671
+ });
2672
+ }
2673
+ const staticComponentRatio = this.metrics.components.staticComponents / Math.max(this.metrics.components.renders, 1);
2674
+ if (staticComponentRatio < 0.8) {
2675
+ this.recommendations.push({
2676
+ type: "optimization",
2677
+ category: "components",
2678
+ message: "More components could be optimized as static for better caching",
2679
+ impact: "high",
2680
+ effort: "medium"
2681
+ });
2682
+ }
2683
+ if (this.metrics.components.memoryUsage > 100 * 1024 * 1024) {
2684
+ this.recommendations.push({
2685
+ type: "optimization",
2686
+ category: "memory",
2687
+ message: "Memory usage is high. Consider reducing cache size or implementing memory cleanup",
2688
+ impact: "medium",
2689
+ effort: "medium"
2690
+ });
2691
+ }
2692
+ }
2693
+ /**
2694
+ * Get cache hit rate for category
2695
+ */
2696
+ getCacheHitRate(category) {
2697
+ const metrics = this.metrics[category];
2698
+ if (!metrics || !metrics.cacheHits) return 0;
2699
+ const total = metrics.cacheHits + metrics.cacheMisses;
2700
+ return total > 0 ? metrics.cacheHits / total * 100 : 0;
2701
+ }
2702
+ /**
2703
+ * Update running average
2704
+ */
2705
+ updateAverage(current, newValue, count) {
2706
+ return (current * (count - 1) + newValue) / count;
2707
+ }
2708
+ /**
2709
+ * Add data point to history
2710
+ */
2711
+ addToHistory(category, data) {
2712
+ if (!this.metrics[category].history) {
2713
+ this.metrics[category].history = [];
2714
+ }
2715
+ this.metrics[category].history.push(data);
2716
+ if (this.metrics[category].history.length > this.options.maxHistoryPoints) {
2717
+ this.metrics[category].history = this.metrics[category].history.slice(-this.options.maxHistoryPoints);
2718
+ }
2719
+ }
2720
+ /**
2721
+ * Generate dashboard visualization
2722
+ */
2723
+ generateDashboard() {
2724
+ const lines = [];
2725
+ if (this.options.colorOutput) {
2726
+ lines.push(this.colorize("\u{1F4CA} Coherent.js Performance Dashboard", "cyan"));
2727
+ lines.push(this.colorize("\u2550".repeat(50), "cyan"));
2728
+ } else {
2729
+ lines.push("\u{1F4CA} Coherent.js Performance Dashboard");
2730
+ lines.push("\u2550".repeat(50));
2731
+ }
2732
+ const uptime = (Date.now() - this.startTime) / 1e3;
2733
+ lines.push(`\u23F1\uFE0F Uptime: ${uptime.toFixed(1)}s`);
2734
+ lines.push("");
2735
+ lines.push("\u{1F680} API Performance");
2736
+ lines.push("\u2500".repeat(20));
2737
+ const apiCacheHitRate = this.getCacheHitRate("api");
2738
+ lines.push(` Requests: ${this.metrics.api.requests} (${(this.metrics.api.requests / uptime).toFixed(1)} req/s)`);
2739
+ lines.push(` Avg Time: ${this.metrics.api.averageTime.toFixed(2)}ms`);
2740
+ lines.push(` Cache Hit Rate: ${apiCacheHitRate.toFixed(1)}%`);
2741
+ lines.push(` Static Routes: ${this.metrics.api.staticRoutes}/${this.metrics.api.requests} (${(this.metrics.api.staticRoutes / Math.max(this.metrics.api.requests, 1) * 100).toFixed(1)}%)`);
2742
+ lines.push("");
2743
+ lines.push("\u{1F3D7}\uFE0F Component Performance");
2744
+ lines.push("\u2500".repeat(25));
2745
+ const componentCacheHitRate = this.getCacheHitRate("components");
2746
+ lines.push(` Renders: ${this.metrics.components.renders} (${(this.metrics.components.renders / uptime).toFixed(1)} renders/s)`);
2747
+ lines.push(` Avg Time: ${this.metrics.components.averageTime.toFixed(2)}ms`);
2748
+ lines.push(` Cache Hit Rate: ${componentCacheHitRate.toFixed(1)}%`);
2749
+ lines.push(` Static Components: ${this.metrics.components.staticComponents}/${this.metrics.components.renders} (${(this.metrics.components.staticComponents / Math.max(this.metrics.components.renders, 1) * 100).toFixed(1)}%)`);
2750
+ lines.push(` Memory Usage: ${(this.metrics.components.memoryUsage / 1024 / 1024).toFixed(1)}MB`);
2751
+ lines.push("");
2752
+ lines.push("\u{1F310} Full-Stack Performance");
2753
+ lines.push("\u2500".repeat(26));
2754
+ lines.push(` Total Requests: ${this.metrics.fullstack.totalRequests} (${(this.metrics.fullstack.totalRequests / uptime).toFixed(1)} req/s)`);
2755
+ lines.push(` Avg Time: ${this.metrics.fullstack.averageTime.toFixed(2)}ms`);
2756
+ lines.push(` Errors: ${this.metrics.fullstack.errors}`);
2757
+ lines.push("");
2758
+ if (this.alerts.length > 0) {
2759
+ lines.push("\u26A0\uFE0F Performance Alerts");
2760
+ lines.push("\u2500".repeat(22));
2761
+ this.alerts.forEach((alert) => {
2762
+ const icon = alert.type === "error" ? "\u274C" : "\u26A0\uFE0F";
2763
+ lines.push(` ${icon} ${alert.message}`);
2764
+ });
2765
+ lines.push("");
2766
+ }
2767
+ if (this.recommendations.length > 0) {
2768
+ lines.push("\u{1F4A1} Optimization Recommendations");
2769
+ lines.push("\u2500".repeat(30));
2770
+ this.recommendations.forEach((rec) => {
2771
+ const impact = rec.impact === "high" ? "\u{1F525}" : rec.impact === "medium" ? "\u26A1" : "\u{1F4A4}";
2772
+ lines.push(` ${impact} ${rec.message} (${rec.effort} effort)`);
2773
+ });
2774
+ lines.push("");
2775
+ }
2776
+ const score = this.calculatePerformanceScore();
2777
+ const scoreColor = score >= 90 ? "green" : score >= 70 ? "yellow" : "red";
2778
+ lines.push(`Performance Score: ${this.colorize(`${score.toFixed(1)}/100`, scoreColor)}`);
2779
+ return lines.join("\n");
2780
+ }
2781
+ /**
2782
+ * Calculate overall performance score
2783
+ */
2784
+ calculatePerformanceScore() {
2785
+ let score = 100;
2786
+ if (this.metrics.api.averageTime > 50) score -= 10;
2787
+ if (this.metrics.api.averageTime > 100) score -= 10;
2788
+ if (this.getCacheHitRate("api") < 90) score -= 10;
2789
+ if (this.metrics.components.averageTime > 20) score -= 10;
2790
+ if (this.metrics.components.averageTime > 50) score -= 10;
2791
+ if (this.getCacheHitRate("components") < 95) score -= 10;
2792
+ if (this.metrics.fullstack.errors > 0) score -= Math.min(20, this.metrics.fullstack.errors * 5);
2793
+ return Math.max(0, score);
2794
+ }
2795
+ /**
2796
+ * Add color to text
2797
+ */
2798
+ colorize(text, color) {
2799
+ if (!this.options.colorOutput) return text;
2800
+ const colors = {
2801
+ black: "\x1B[30m",
2802
+ red: "\x1B[31m",
2803
+ green: "\x1B[32m",
2804
+ yellow: "\x1B[33m",
2805
+ blue: "\x1B[34m",
2806
+ magenta: "\x1B[35m",
2807
+ cyan: "\x1B[36m",
2808
+ white: "\x1B[37m",
2809
+ gray: "\x1B[90m"
2810
+ };
2811
+ const reset = "\x1B[0m";
2812
+ return `${colors[color] || ""}${text}${reset}`;
2813
+ }
2814
+ /**
2815
+ * Export metrics as JSON
2816
+ */
2817
+ exportMetrics() {
2818
+ return {
2819
+ timestamp: Date.now(),
2820
+ uptime: Date.now() - this.startTime,
2821
+ metrics: { ...this.metrics },
2822
+ alerts: [...this.alerts],
2823
+ recommendations: [...this.recommendations],
2824
+ performanceScore: this.calculatePerformanceScore()
2825
+ };
2826
+ }
2827
+ /**
2828
+ * Reset all metrics
2829
+ */
2830
+ reset() {
2831
+ this.metrics = {
2832
+ api: { requests: 0, averageTime: 0, cacheHits: 0, cacheMisses: 0, staticRoutes: 0, dynamicRoutes: 0, history: [] },
2833
+ components: { renders: 0, averageTime: 0, cacheHits: 0, cacheMisses: 0, staticComponents: 0, dynamicComponents: 0, memoryUsage: 0, history: [] },
2834
+ fullstack: { totalRequests: 0, averageTime: 0, errors: 0, bottlenecks: [], history: [] }
2835
+ };
2836
+ this.alerts = [];
2837
+ this.recommendations = [];
2838
+ this.startTime = Date.now();
2839
+ }
2098
2840
  };
2841
+ function createPerformanceDashboard(options = {}) {
2842
+ return new PerformanceDashboard(options);
2843
+ }
2844
+ function showPerformanceDashboard(dashboard) {
2845
+ const output = dashboard.generateDashboard();
2846
+ console.log(output);
2847
+ return dashboard;
2848
+ }
2849
+
2850
+ // src/enhanced-errors.js
2851
+ import { isCoherentObject as isCoherentObject3, hasChildren as hasChildren2 } from "@coherent.js/core";
2852
+ var EnhancedErrorHandler = class {
2853
+ constructor(options = {}) {
2854
+ this.options = {
2855
+ maxContextDepth: options.maxContextDepth || 5,
2856
+ includeStackTrace: options.includeStackTrace !== false,
2857
+ showSuggestions: options.showSuggestions !== false,
2858
+ colorOutput: options.colorOutput !== false,
2859
+ ...options
2860
+ };
2861
+ this.errorHistory = [];
2862
+ this.commonPatterns = this.initializeCommonPatterns();
2863
+ }
2864
+ /**
2865
+ * Handle and enhance an error with component context
2866
+ */
2867
+ handleError(error, component = null, context = {}) {
2868
+ const enhancedError = {
2869
+ originalError: error,
2870
+ message: error.message,
2871
+ stack: error.stack,
2872
+ timestamp: Date.now(),
2873
+ component: component ? this.analyzeComponent(component) : null,
2874
+ context,
2875
+ suggestions: [],
2876
+ severity: this.determineSeverity(error),
2877
+ category: this.categorizeError(error)
2878
+ };
2879
+ if (component) {
2880
+ enhancedError.componentContext = this.getComponentContext(component, context.path || []);
2881
+ enhancedError.propValidation = this.validateProps(component);
2882
+ }
2883
+ if (this.options.showSuggestions) {
2884
+ enhancedError.suggestions = this.generateSuggestions(enhancedError);
2885
+ }
2886
+ this.errorHistory.push(enhancedError);
2887
+ if (this.errorHistory.length > 100) {
2888
+ this.errorHistory = this.errorHistory.slice(-100);
2889
+ }
2890
+ return enhancedError;
2891
+ }
2892
+ /**
2893
+ * Analyze component structure
2894
+ */
2895
+ analyzeComponent(component) {
2896
+ const analysis = {
2897
+ type: this.getComponentType(component),
2898
+ isValid: this.isValidComponent(component),
2899
+ complexity: this.assessComplexity(component),
2900
+ hasDynamicContent: this.hasDynamicContent(component),
2901
+ estimatedSize: this.estimateSize(component)
2902
+ };
2903
+ if (isCoherentObject3(component)) {
2904
+ const entries = Object.entries(component);
2905
+ if (entries.length === 1) {
2906
+ const [_tagName, props] = entries;
2907
+ analysis.tagName = _tagName;
2908
+ analysis.propCount = Object.keys(props).length;
2909
+ analysis.hasChildren = hasChildren2(props);
2910
+ analysis.eventHandlers = this.extractEventHandlers(props);
2911
+ }
2912
+ }
2913
+ return analysis;
2914
+ }
2915
+ /**
2916
+ * Get component context tree
2917
+ */
2918
+ getComponentContext(component, path2 = []) {
2919
+ const context = {
2920
+ path: path2.join("."),
2921
+ depth: path2.length,
2922
+ component: this.summarizeComponent(component),
2923
+ children: []
2924
+ };
2925
+ if (isCoherentObject3(component) && context.depth < this.options.maxContextDepth) {
2926
+ const entries = Object.entries(component);
2927
+ if (entries.length === 1) {
2928
+ const [tagName, props] = entries;
2929
+ if (hasChildren2(props)) {
2930
+ const children = Array.isArray(props.children) ? props.children : [props.children];
2931
+ children.forEach((child, index) => {
2932
+ if (child && typeof child === "object") {
2933
+ const childContext = this.getComponentContext(child, [...path2, `${tagName}[${index}]`]);
2934
+ context.children.push(childContext);
2935
+ }
2936
+ });
2937
+ }
2938
+ }
2939
+ }
2940
+ return context;
2941
+ }
2942
+ /**
2943
+ * Validate component props
2944
+ */
2945
+ validateProps(component) {
2946
+ if (!isCoherentObject3(component)) return { valid: true, issues: [] };
2947
+ const entries = Object.entries(component);
2948
+ if (entries.length !== 1) return { valid: false, issues: ["Component must have exactly one root element"] };
2949
+ const [tagName, props] = entries;
2950
+ const issues = [];
2951
+ const warnings = [];
2952
+ Object.entries(props).forEach(([key, value]) => {
2953
+ if (value === void 0) {
2954
+ issues.push(`Prop '${key}' is undefined`);
2955
+ }
2956
+ if (value === null && key !== "children" && key !== "text") {
2957
+ warnings.push(`Prop '${key}' is null`);
2958
+ }
2959
+ if (typeof value === "function" && !/^on[A-Z]/.test(key)) {
2960
+ warnings.push(`Function prop '${key}' doesn't follow event handler naming convention (onXxx)`);
2961
+ }
2962
+ if (typeof value === "object" && value !== null) {
2963
+ const size = JSON.stringify(value).length;
2964
+ if (size > 1e4) {
2965
+ warnings.push(`Prop '${key}' is large (${size} bytes) - consider optimizing`);
2966
+ }
2967
+ }
2968
+ });
2969
+ if (tagName === "img" && !props.src && !props["data-src"]) {
2970
+ issues.push("Image element missing required src or data-src prop");
2971
+ }
2972
+ if (tagName === "a" && !props.href && !props.onclick) {
2973
+ warnings.push("Link element missing href or onclick prop");
2974
+ }
2975
+ return {
2976
+ valid: issues.length === 0,
2977
+ issues,
2978
+ warnings,
2979
+ propCount: Object.keys(props).length
2980
+ };
2981
+ }
2982
+ /**
2983
+ * Generate fix suggestions based on error and context
2984
+ */
2985
+ generateSuggestions(enhancedError) {
2986
+ const suggestions = [];
2987
+ const { originalError, component, category } = enhancedError;
2988
+ if (component && component.type === "element") {
2989
+ if (component.hasDynamicContent && category === "performance") {
2990
+ suggestions.push({
2991
+ type: "optimization",
2992
+ message: "Consider making this component static for better caching",
2993
+ code: "Remove functions from props to enable static optimization"
2994
+ });
2995
+ }
2996
+ if (component.complexity > 10) {
2997
+ suggestions.push({
2998
+ type: "structure",
2999
+ message: "Component is complex - consider breaking it into smaller components",
3000
+ code: "Split complex components into reusable functional components"
3001
+ });
3002
+ }
3003
+ }
3004
+ if (originalError && originalError.message && originalError.message.includes("undefined")) {
3005
+ suggestions.push({
3006
+ type: "fix",
3007
+ message: "Check for undefined props or missing data",
3008
+ code: "Add prop validation: if (!props.required) return null;"
3009
+ });
3010
+ }
3011
+ if (originalError && originalError.message && originalError.message.includes("Maximum render depth")) {
3012
+ suggestions.push({
3013
+ type: "fix",
3014
+ message: "Possible infinite recursion detected",
3015
+ code: "Check for circular references in component props"
3016
+ });
3017
+ }
3018
+ this.commonPatterns.forEach((pattern) => {
3019
+ if (originalError && originalError.message && pattern.matcher.test(originalError.message)) {
3020
+ suggestions.push(pattern.suggestion);
3021
+ }
3022
+ });
3023
+ return suggestions;
3024
+ }
3025
+ /**
3026
+ * Format enhanced error for display
3027
+ */
3028
+ formatError(enhancedError) {
3029
+ const lines = [];
3030
+ if (this.options.colorOutput) {
3031
+ lines.push(this.colorize("\u274C Coherent.js Error", "red"));
3032
+ lines.push(this.colorize("\u2500".repeat(40), "red"));
3033
+ } else {
3034
+ lines.push("\u274C Coherent.js Error");
3035
+ lines.push("\u2500".repeat(40));
3036
+ }
3037
+ lines.push(`Message: ${enhancedError.message}`);
3038
+ lines.push(`Category: ${enhancedError.category} (${enhancedError.severity})`);
3039
+ lines.push(`Time: ${new Date(enhancedError.timestamp).toLocaleTimeString()}`);
3040
+ lines.push("");
3041
+ if (enhancedError.componentContext) {
3042
+ lines.push("\u{1F3D7}\uFE0F Component Context");
3043
+ lines.push("\u2500".repeat(20));
3044
+ lines.push(`Path: ${enhancedError.componentContext.path}`);
3045
+ lines.push(`Type: ${enhancedError.component.type}`);
3046
+ lines.push(`Depth: ${enhancedError.componentContext.depth}`);
3047
+ if (enhancedError.componentContext.component) {
3048
+ lines.push(`Summary: ${enhancedError.componentContext.component}`);
3049
+ }
3050
+ lines.push("");
3051
+ }
3052
+ if (enhancedError.propValidation) {
3053
+ const validation = enhancedError.propValidation;
3054
+ lines.push("\u{1F4DD} Prop Validation");
3055
+ lines.push("\u2500".repeat(18));
3056
+ lines.push(`Valid: ${validation.valid ? "\u2705" : "\u274C"}`);
3057
+ lines.push(`Props: ${validation.propCount}`);
3058
+ if (validation.issues.length > 0) {
3059
+ lines.push("Issues:");
3060
+ validation.issues.forEach((issue) => {
3061
+ lines.push(` \u274C ${issue}`);
3062
+ });
3063
+ }
3064
+ if (validation.warnings.length > 0) {
3065
+ lines.push("Warnings:");
3066
+ validation.warnings.forEach((warning) => {
3067
+ lines.push(` \u26A0\uFE0F ${warning}`);
3068
+ });
3069
+ }
3070
+ lines.push("");
3071
+ }
3072
+ if (enhancedError.suggestions.length > 0) {
3073
+ lines.push("\u{1F4A1} Suggestions");
3074
+ lines.push("\u2500".repeat(13));
3075
+ enhancedError.suggestions.forEach((suggestion, index) => {
3076
+ const icon = suggestion.type === "fix" ? "\u{1F527}" : suggestion.type === "optimization" ? "\u26A1" : suggestion.type === "structure" ? "\u{1F3D7}\uFE0F" : "\u{1F4A1}";
3077
+ lines.push(`${index + 1}. ${icon} ${suggestion.message}`);
3078
+ if (suggestion.code) {
3079
+ lines.push(` Code: ${suggestion.code}`);
3080
+ }
3081
+ });
3082
+ lines.push("");
3083
+ }
3084
+ if (this.options.includeStackTrace && enhancedError.stack) {
3085
+ lines.push("\u{1F4DA} Stack Trace");
3086
+ lines.push("\u2500".repeat(15));
3087
+ lines.push(enhancedError.stack.split("\n").slice(0, 10).join("\n"));
3088
+ if (enhancedError.stack.split("\n").length > 10) {
3089
+ lines.push("... (truncated)");
3090
+ }
3091
+ }
3092
+ return lines.join("\n");
3093
+ }
3094
+ /**
3095
+ * Get component type
3096
+ */
3097
+ getComponentType(component) {
3098
+ if (component === null || component === void 0) return "empty";
3099
+ if (typeof component === "string") return "text";
3100
+ if (typeof component === "number") return "number";
3101
+ if (typeof component === "boolean") return "boolean";
3102
+ if (typeof component === "function") return "function";
3103
+ if (Array.isArray(component)) return "array";
3104
+ if (isCoherentObject3(component)) return "element";
3105
+ return "object";
3106
+ }
3107
+ /**
3108
+ * Check if component is valid
3109
+ */
3110
+ isValidComponent(component) {
3111
+ try {
3112
+ if (component === null || component === void 0) return true;
3113
+ if (typeof component === "string" || typeof component === "number") return true;
3114
+ if (typeof component === "function") return true;
3115
+ if (Array.isArray(component)) return component.every((child) => this.isValidComponent(child));
3116
+ if (isCoherentObject3(component)) {
3117
+ const entries = Object.entries(component);
3118
+ return entries.length === 1;
3119
+ }
3120
+ return false;
3121
+ } catch {
3122
+ return false;
3123
+ }
3124
+ }
3125
+ /**
3126
+ * Assess component complexity
3127
+ */
3128
+ assessComplexity(component) {
3129
+ let complexity = 0;
3130
+ if (typeof component === "object" && component !== null) {
3131
+ if (isCoherentObject3(component)) {
3132
+ const entries = Object.entries(component);
3133
+ if (entries.length === 1) {
3134
+ const [_tagName, props] = entries;
3135
+ complexity += Object.keys(props).length;
3136
+ if (hasChildren2(props)) {
3137
+ const children = Array.isArray(props.children) ? props.children : [props.children];
3138
+ children.forEach((child) => {
3139
+ complexity += this.assessComplexity(child);
3140
+ });
3141
+ }
3142
+ }
3143
+ } else {
3144
+ complexity += Object.keys(component).length;
3145
+ }
3146
+ }
3147
+ return complexity;
3148
+ }
3149
+ /**
3150
+ * Check if component has dynamic content
3151
+ */
3152
+ hasDynamicContent(component) {
3153
+ if (typeof component === "function") return true;
3154
+ if (typeof component === "object" && component !== null) {
3155
+ for (const value of Object.values(component)) {
3156
+ if (typeof value === "function") return true;
3157
+ if (typeof value === "object" && this.hasDynamicContent(value)) return true;
3158
+ }
3159
+ }
3160
+ return false;
3161
+ }
3162
+ /**
3163
+ * Estimate component size
3164
+ */
3165
+ estimateSize(component) {
3166
+ try {
3167
+ return JSON.stringify(component).length;
3168
+ } catch {
3169
+ return 0;
3170
+ }
3171
+ }
3172
+ /**
3173
+ * Summarize component for context
3174
+ */
3175
+ summarizeComponent(component) {
3176
+ const type = this.getComponentType(component);
3177
+ if (type === "element" && isCoherentObject3(component)) {
3178
+ const entries = Object.entries(component);
3179
+ if (entries.length === 1) {
3180
+ const [tagName, props] = entries;
3181
+ const propCount = Object.keys(props).length;
3182
+ const hasChildren3 = hasChildren3(props);
3183
+ return `<${tagName}> (${propCount} props, ${hasChildren3 ? "has" : "no"} children)`;
3184
+ }
3185
+ }
3186
+ if (type === "text") {
3187
+ const preview = String(component).substring(0, 30);
3188
+ return `Text: "${preview}${component.length > 30 ? "..." : ""}"`;
3189
+ }
3190
+ if (type === "function") {
3191
+ return `Function: ${component.name || "anonymous"}`;
3192
+ }
3193
+ return `${type} (${this.estimateSize(component)} bytes)`;
3194
+ }
3195
+ /**
3196
+ * Extract event handlers from props
3197
+ */
3198
+ extractEventHandlers(props) {
3199
+ return Object.keys(props).filter((key) => /^on[A-Z]/.test(key));
3200
+ }
3201
+ /**
3202
+ * Determine error severity
3203
+ */
3204
+ determineSeverity(error) {
3205
+ if (error.name === "TypeError" || error.name === "ReferenceError") return "critical";
3206
+ if (error.message.includes("Maximum render depth")) return "critical";
3207
+ if (error.message.includes("undefined")) return "high";
3208
+ if (error.message.includes("performance")) return "medium";
3209
+ return "low";
3210
+ }
3211
+ /**
3212
+ * Categorize error
3213
+ */
3214
+ categorizeError(error) {
3215
+ if (error.message.includes("render") || error.message.includes("component")) return "rendering";
3216
+ if (error.message.includes("props") || error.message.includes("prop")) return "props";
3217
+ if (error.message.includes("cache") || error.message.includes("performance")) return "performance";
3218
+ if (error.message.includes("route") || error.message.includes("router")) return "routing";
3219
+ return "general";
3220
+ }
3221
+ /**
3222
+ * Initialize common error patterns and suggestions
3223
+ */
3224
+ initializeCommonPatterns() {
3225
+ return [
3226
+ {
3227
+ matcher: /undefined.*property/gi,
3228
+ suggestion: {
3229
+ type: "fix",
3230
+ message: "Check for undefined properties in component props",
3231
+ code: 'Add default props: const { required = "default" } = props;'
3232
+ }
3233
+ },
3234
+ {
3235
+ matcher: /maximum.*depth/gi,
3236
+ suggestion: {
3237
+ type: "fix",
3238
+ message: "Infinite recursion detected in component tree",
3239
+ code: "Check for circular references in component children"
3240
+ }
3241
+ },
3242
+ {
3243
+ matcher: /cannot.*read.*property/gi,
3244
+ suggestion: {
3245
+ type: "fix",
3246
+ message: "Property access error - check object structure",
3247
+ code: "Use optional chaining: obj?.prop?.nested"
3248
+ }
3249
+ },
3250
+ {
3251
+ matcher: /performance/gi,
3252
+ suggestion: {
3253
+ type: "optimization",
3254
+ message: "Consider optimizing component for better performance",
3255
+ code: "Use memoization or static components where possible"
3256
+ }
3257
+ }
3258
+ ];
3259
+ }
3260
+ /**
3261
+ * Add color to text
3262
+ */
3263
+ colorize(text, color) {
3264
+ if (!this.options.colorOutput) return text;
3265
+ const colors = {
3266
+ black: "\x1B[30m",
3267
+ red: "\x1B[31m",
3268
+ green: "\x1B[32m",
3269
+ yellow: "\x1B[33m",
3270
+ blue: "\x1B[34m",
3271
+ magenta: "\x1B[35m",
3272
+ cyan: "\x1B[36m",
3273
+ white: "\x1B[37m",
3274
+ gray: "\x1B[90m"
3275
+ };
3276
+ const reset = "\x1B[0m";
3277
+ return `${colors[color] || ""}${text}${reset}`;
3278
+ }
3279
+ /**
3280
+ * Get error statistics
3281
+ */
3282
+ getErrorStats() {
3283
+ const stats = {
3284
+ total: this.errorHistory.length,
3285
+ byCategory: {},
3286
+ bySeverity: {},
3287
+ recent: this.errorHistory.slice(-10)
3288
+ };
3289
+ this.errorHistory.forEach((error) => {
3290
+ stats.byCategory[error.category] = (stats.byCategory[error.category] || 0) + 1;
3291
+ stats.bySeverity[error.severity] = (stats.bySeverity[error.severity] || 0) + 1;
3292
+ });
3293
+ return stats;
3294
+ }
3295
+ };
3296
+ function createEnhancedErrorHandler(options = {}) {
3297
+ return new EnhancedErrorHandler(options);
3298
+ }
3299
+ function handleEnhancedError(error, component = null, context = {}) {
3300
+ const handler = createEnhancedErrorHandler();
3301
+ const enhancedError = handler.handleError(error, component, context);
3302
+ console.error(handler.formatError(enhancedError));
3303
+ return enhancedError;
3304
+ }
2099
3305
  export {
2100
3306
  ComponentInspector,
3307
+ ComponentVisualizer,
2101
3308
  DevLogger,
2102
3309
  DevTools,
3310
+ EnhancedErrorHandler,
2103
3311
  LogLevel,
3312
+ PerformanceDashboard,
2104
3313
  PerformanceProfiler,
2105
3314
  createComponentLogger,
3315
+ createComponentVisualizer,
2106
3316
  createConsoleLogger,
2107
3317
  createDevTools,
3318
+ createEnhancedErrorHandler,
2108
3319
  createInspector,
2109
3320
  createLogger,
3321
+ createPerformanceDashboard,
2110
3322
  createProfiler,
2111
- index_default as default,
3323
+ handleEnhancedError,
2112
3324
  inspect,
3325
+ logComponentTree,
2113
3326
  measure,
2114
3327
  profile,
2115
- validateComponent
3328
+ showPerformanceDashboard,
3329
+ validateComponent,
3330
+ visualizeComponent
2116
3331
  };
2117
3332
  //# sourceMappingURL=index.js.map