create-fluxstack 1.0.12 โ†’ 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/.env.example +29 -29
  2. package/app/client/README.md +69 -69
  3. package/app/client/index.html +14 -13
  4. package/app/client/src/App.tsx +157 -524
  5. package/app/client/src/components/ErrorBoundary.tsx +107 -0
  6. package/app/client/src/components/ErrorDisplay.css +365 -0
  7. package/app/client/src/components/ErrorDisplay.tsx +258 -0
  8. package/app/client/src/components/FluxStackConfig.tsx +1321 -0
  9. package/app/client/src/components/HybridLiveCounter.tsx +140 -0
  10. package/app/client/src/components/LiveClock.tsx +286 -0
  11. package/app/client/src/components/MainLayout.tsx +390 -0
  12. package/app/client/src/components/SidebarNavigation.tsx +391 -0
  13. package/app/client/src/components/StateDemo.tsx +178 -0
  14. package/app/client/src/components/SystemMonitor.tsx +1038 -0
  15. package/app/client/src/components/Teste.tsx +104 -0
  16. package/app/client/src/components/UserProfile.tsx +809 -0
  17. package/app/client/src/hooks/useAuth.ts +39 -0
  18. package/app/client/src/hooks/useNotifications.ts +56 -0
  19. package/app/client/src/lib/eden-api.ts +189 -53
  20. package/app/client/src/lib/errors.ts +340 -0
  21. package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
  22. package/app/client/src/lib/index.ts +45 -0
  23. package/app/client/src/main.tsx +3 -2
  24. package/app/client/src/pages/ApiDocs.tsx +182 -0
  25. package/app/client/src/pages/Demo.tsx +174 -0
  26. package/app/client/src/pages/HybridLive.tsx +263 -0
  27. package/app/client/src/pages/Overview.tsx +155 -0
  28. package/app/client/src/store/README.md +43 -0
  29. package/app/client/src/store/index.ts +16 -0
  30. package/app/client/src/store/slices/uiSlice.ts +151 -0
  31. package/app/client/src/store/slices/userSlice.ts +161 -0
  32. package/app/client/src/test/README.md +257 -0
  33. package/app/client/src/test/setup.ts +70 -0
  34. package/app/client/src/test/types.ts +12 -0
  35. package/app/client/src/vite-env.d.ts +1 -1
  36. package/app/client/tsconfig.app.json +44 -43
  37. package/app/client/tsconfig.json +7 -7
  38. package/app/client/tsconfig.node.json +25 -25
  39. package/app/client/zustand-setup.md +65 -0
  40. package/app/server/controllers/users.controller.ts +68 -68
  41. package/app/server/index.ts +9 -1
  42. package/app/server/live/CounterComponent.ts +191 -0
  43. package/app/server/live/FluxStackConfig.ts +529 -0
  44. package/app/server/live/LiveClockComponent.ts +214 -0
  45. package/app/server/live/SidebarNavigation.ts +156 -0
  46. package/app/server/live/SystemMonitor.ts +594 -0
  47. package/app/server/live/SystemMonitorIntegration.ts +151 -0
  48. package/app/server/live/TesteComponent.ts +87 -0
  49. package/app/server/live/UserProfileComponent.ts +135 -0
  50. package/app/server/live/register-components.ts +28 -0
  51. package/app/server/middleware/auth.ts +136 -0
  52. package/app/server/middleware/errorHandling.ts +250 -0
  53. package/app/server/middleware/index.ts +10 -0
  54. package/app/server/middleware/rateLimit.ts +193 -0
  55. package/app/server/middleware/requestLogging.ts +215 -0
  56. package/app/server/middleware/validation.ts +270 -0
  57. package/app/server/routes/index.ts +14 -2
  58. package/app/server/routes/upload.ts +92 -0
  59. package/app/server/routes/users.routes.ts +2 -9
  60. package/app/server/services/NotificationService.ts +302 -0
  61. package/app/server/services/UserService.ts +222 -0
  62. package/app/server/services/index.ts +46 -0
  63. package/core/cli/commands/plugin-deps.ts +263 -0
  64. package/core/cli/generators/README.md +339 -0
  65. package/core/cli/generators/component.ts +770 -0
  66. package/core/cli/generators/controller.ts +299 -0
  67. package/core/cli/generators/index.ts +144 -0
  68. package/core/cli/generators/interactive.ts +228 -0
  69. package/core/cli/generators/prompts.ts +83 -0
  70. package/core/cli/generators/route.ts +513 -0
  71. package/core/cli/generators/service.ts +465 -0
  72. package/core/cli/generators/template-engine.ts +154 -0
  73. package/core/cli/generators/types.ts +71 -0
  74. package/core/cli/generators/utils.ts +192 -0
  75. package/core/cli/index.ts +69 -0
  76. package/core/cli/plugin-discovery.ts +16 -85
  77. package/core/client/fluxstack.ts +17 -0
  78. package/core/client/hooks/index.ts +7 -0
  79. package/core/client/hooks/state-validator.ts +130 -0
  80. package/core/client/hooks/useAuth.ts +49 -0
  81. package/core/client/hooks/useChunkedUpload.ts +258 -0
  82. package/core/client/hooks/useHybridLiveComponent.ts +967 -0
  83. package/core/client/hooks/useWebSocket.ts +373 -0
  84. package/core/client/index.ts +47 -0
  85. package/core/client/state/createStore.ts +193 -0
  86. package/core/client/state/index.ts +15 -0
  87. package/core/config/env-dynamic.ts +1 -1
  88. package/core/config/env.ts +2 -1
  89. package/core/config/loader.ts +8 -32
  90. package/core/config/runtime-config.ts +3 -3
  91. package/core/config/schema.ts +84 -49
  92. package/core/framework/server.ts +30 -0
  93. package/core/index.ts +25 -0
  94. package/core/live/ComponentRegistry.ts +399 -0
  95. package/core/live/types.ts +164 -0
  96. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
  97. package/core/plugins/built-in/live-components/index.ts +27 -0
  98. package/core/plugins/built-in/logger/index.ts +1 -1
  99. package/core/plugins/built-in/monitoring/index.ts +1 -1
  100. package/core/plugins/built-in/static/index.ts +1 -1
  101. package/core/plugins/built-in/swagger/index.ts +1 -1
  102. package/core/plugins/built-in/vite/index.ts +1 -1
  103. package/core/plugins/dependency-manager.ts +384 -0
  104. package/core/plugins/index.ts +5 -1
  105. package/core/plugins/manager.ts +7 -3
  106. package/core/plugins/registry.ts +88 -10
  107. package/core/plugins/types.ts +11 -11
  108. package/core/server/framework.ts +43 -0
  109. package/core/server/index.ts +11 -1
  110. package/core/server/live/ComponentRegistry.ts +1017 -0
  111. package/core/server/live/FileUploadManager.ts +272 -0
  112. package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
  113. package/core/server/live/SingleConnectionManager.ts +0 -0
  114. package/core/server/live/StateSignature.ts +644 -0
  115. package/core/server/live/WebSocketConnectionManager.ts +688 -0
  116. package/core/server/live/websocket-plugin.ts +435 -0
  117. package/core/server/middleware/errorHandling.ts +141 -0
  118. package/core/server/middleware/index.ts +16 -0
  119. package/core/server/plugins/static-files-plugin.ts +232 -0
  120. package/core/server/services/BaseService.ts +95 -0
  121. package/core/server/services/ServiceContainer.ts +144 -0
  122. package/core/server/services/index.ts +9 -0
  123. package/core/templates/create-project.ts +46 -2
  124. package/core/testing/index.ts +10 -0
  125. package/core/testing/setup.ts +74 -0
  126. package/core/types/build.ts +38 -14
  127. package/core/types/types.ts +319 -0
  128. package/core/utils/env-runtime.ts +7 -0
  129. package/core/utils/errors/handlers.ts +264 -39
  130. package/core/utils/errors/index.ts +528 -18
  131. package/core/utils/errors/middleware.ts +114 -0
  132. package/core/utils/logger/formatters.ts +222 -0
  133. package/core/utils/logger/index.ts +167 -48
  134. package/core/utils/logger/middleware.ts +253 -0
  135. package/core/utils/logger/performance.ts +384 -0
  136. package/core/utils/logger/transports.ts +365 -0
  137. package/create-fluxstack.ts +296 -296
  138. package/fluxstack.config.ts +17 -1
  139. package/package-template.json +66 -66
  140. package/package.json +31 -6
  141. package/public/README.md +16 -0
  142. package/vite.config.ts +29 -14
  143. package/.claude/settings.local.json +0 -74
  144. package/.github/workflows/ci-build-tests.yml +0 -480
  145. package/.github/workflows/dependency-management.yml +0 -324
  146. package/.github/workflows/release-validation.yml +0 -355
  147. package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
  148. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
  149. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
  150. package/CLAUDE.md +0 -200
  151. package/Dockerfile +0 -58
  152. package/Dockerfile.backend +0 -52
  153. package/Dockerfile.frontend +0 -54
  154. package/README-Docker.md +0 -85
  155. package/ai-context/00-QUICK-START.md +0 -86
  156. package/ai-context/README.md +0 -88
  157. package/ai-context/development/eden-treaty-guide.md +0 -362
  158. package/ai-context/development/patterns.md +0 -382
  159. package/ai-context/development/plugins-guide.md +0 -572
  160. package/ai-context/examples/crud-complete.md +0 -626
  161. package/ai-context/project/architecture.md +0 -399
  162. package/ai-context/project/overview.md +0 -213
  163. package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
  164. package/ai-context/recent-changes/type-inference-fix.md +0 -223
  165. package/ai-context/reference/environment-vars.md +0 -384
  166. package/ai-context/reference/troubleshooting.md +0 -407
  167. package/app/client/src/components/TestPage.tsx +0 -453
  168. package/bun.lock +0 -1063
  169. package/bunfig.toml +0 -16
  170. package/core/__tests__/integration.test.ts +0 -227
  171. package/core/build/index.ts +0 -186
  172. package/core/config/__tests__/config-loader.test.ts +0 -591
  173. package/core/config/__tests__/config-merger.test.ts +0 -657
  174. package/core/config/__tests__/env-converter.test.ts +0 -372
  175. package/core/config/__tests__/env-processor.test.ts +0 -431
  176. package/core/config/__tests__/env.test.ts +0 -452
  177. package/core/config/__tests__/integration.test.ts +0 -418
  178. package/core/config/__tests__/loader.test.ts +0 -331
  179. package/core/config/__tests__/schema.test.ts +0 -129
  180. package/core/config/__tests__/validator.test.ts +0 -318
  181. package/core/framework/__tests__/server.test.ts +0 -233
  182. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  183. package/core/plugins/__tests__/manager.test.ts +0 -398
  184. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  185. package/core/plugins/__tests__/registry.test.ts +0 -335
  186. package/core/utils/__tests__/errors.test.ts +0 -139
  187. package/core/utils/__tests__/helpers.test.ts +0 -297
  188. package/core/utils/__tests__/logger.test.ts +0 -141
  189. package/create-test-app.ts +0 -156
  190. package/docker-compose.microservices.yml +0 -75
  191. package/docker-compose.simple.yml +0 -57
  192. package/docker-compose.yml +0 -71
  193. package/eslint.config.js +0 -23
  194. package/flux-cli.ts +0 -214
  195. package/nginx-lb.conf +0 -37
  196. package/publish.sh +0 -63
  197. package/run-clean.ts +0 -26
  198. package/run-env-tests.ts +0 -313
  199. package/tailwind.config.js +0 -34
  200. package/tests/__mocks__/api.ts +0 -56
  201. package/tests/fixtures/users.ts +0 -69
  202. package/tests/integration/api/users.routes.test.ts +0 -221
  203. package/tests/setup.ts +0 -29
  204. package/tests/unit/app/client/App-simple.test.tsx +0 -56
  205. package/tests/unit/app/client/App.test.tsx.skip +0 -237
  206. package/tests/unit/app/client/eden-api.test.ts +0 -186
  207. package/tests/unit/app/client/simple.test.tsx +0 -23
  208. package/tests/unit/app/controllers/users.controller.test.ts +0 -150
  209. package/tests/unit/core/create-project.test.ts.skip +0 -95
  210. package/tests/unit/core/framework.test.ts +0 -144
  211. package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
  212. package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
  213. package/tests/utils/test-helpers.ts +0 -61
  214. package/vitest.config.ts +0 -50
  215. package/workspace.json +0 -6
@@ -0,0 +1,930 @@
1
+ // ๐Ÿ“Š FluxStack Live Component Performance Monitor
2
+ // Advanced performance monitoring, metrics collection, and optimization suggestions
3
+
4
+ import { EventEmitter } from 'events'
5
+
6
+ export interface PerformanceMetrics {
7
+ componentId: string
8
+ componentName: string
9
+ renderMetrics: RenderMetrics
10
+ actionMetrics: ActionMetrics
11
+ memoryMetrics: MemoryMetrics
12
+ networkMetrics: NetworkMetrics
13
+ userInteractionMetrics: UserInteractionMetrics
14
+ timestamp: Date
15
+ }
16
+
17
+ export interface RenderMetrics {
18
+ totalRenders: number
19
+ averageRenderTime: number
20
+ minRenderTime: number
21
+ maxRenderTime: number
22
+ lastRenderTime: number
23
+ renderTimeHistory: number[]
24
+ slowRenderCount: number // renders > threshold
25
+ renderErrorCount: number
26
+ }
27
+
28
+ export interface ActionMetrics {
29
+ totalActions: number
30
+ averageActionTime: number
31
+ minActionTime: number
32
+ maxActionTime: number
33
+ actionsByType: Record<string, ActionTypeMetrics>
34
+ failedActions: number
35
+ timeoutActions: number
36
+ }
37
+
38
+ export interface ActionTypeMetrics {
39
+ count: number
40
+ averageTime: number
41
+ minTime: number
42
+ maxTime: number
43
+ errorCount: number
44
+ lastExecuted: Date
45
+ }
46
+
47
+ export interface MemoryMetrics {
48
+ currentUsage: number // bytes
49
+ peakUsage: number
50
+ averageUsage: number
51
+ memoryLeakDetected: boolean
52
+ gcCount: number
53
+ stateSize: number // serialized state size
54
+ stateSizeHistory: number[]
55
+ }
56
+
57
+ export interface NetworkMetrics {
58
+ messagesSent: number
59
+ messagesReceived: number
60
+ bytesTransferred: number
61
+ averageLatency: number
62
+ connectionDrops: number
63
+ reconnectCount: number
64
+ queuedMessages: number
65
+ }
66
+
67
+ export interface UserInteractionMetrics {
68
+ clickCount: number
69
+ inputChangeCount: number
70
+ formSubmissions: number
71
+ averageInteractionTime: number
72
+ bounceRate: number // percentage of single interactions
73
+ engagementScore: number // calculated engagement metric
74
+ }
75
+
76
+ export interface PerformanceAlert {
77
+ id: string
78
+ componentId: string
79
+ type: 'warning' | 'critical'
80
+ category: 'render' | 'action' | 'memory' | 'network' | 'interaction'
81
+ message: string
82
+ threshold: number
83
+ currentValue: number
84
+ timestamp: Date
85
+ resolved: boolean
86
+ }
87
+
88
+ export interface OptimizationSuggestion {
89
+ id: string
90
+ componentId: string
91
+ type: 'render' | 'memory' | 'network' | 'state' | 'action'
92
+ priority: 'low' | 'medium' | 'high' | 'critical'
93
+ title: string
94
+ description: string
95
+ impact: string
96
+ implementation: string
97
+ estimatedImprovement: string
98
+ timestamp: Date
99
+ }
100
+
101
+ export interface PerformanceDashboard {
102
+ overview: {
103
+ totalComponents: number
104
+ healthyComponents: number
105
+ degradedComponents: number
106
+ unhealthyComponents: number
107
+ averageRenderTime: number
108
+ averageMemoryUsage: number
109
+ totalAlerts: number
110
+ criticalAlerts: number
111
+ }
112
+ topPerformers: PerformanceMetrics[]
113
+ worstPerformers: PerformanceMetrics[]
114
+ recentAlerts: PerformanceAlert[]
115
+ suggestions: OptimizationSuggestion[]
116
+ trends: {
117
+ renderTimetrend: number[] // last 24 hours
118
+ memoryUsageTrend: number[]
119
+ actionTimeTrend: number[]
120
+ }
121
+ }
122
+
123
+ export interface MonitoringConfig {
124
+ enabled: boolean
125
+ sampleRate: number // 0-1, percentage of operations to monitor
126
+ renderTimeThreshold: number // ms
127
+ memoryThreshold: number // bytes
128
+ actionTimeThreshold: number // ms
129
+ alertCooldown: number // ms between same type alerts
130
+ historyRetention: number // ms to keep historical data
131
+ dashboardUpdateInterval: number // ms
132
+ }
133
+
134
+ export class LiveComponentPerformanceMonitor extends EventEmitter {
135
+ private metrics = new Map<string, PerformanceMetrics>()
136
+ private alerts = new Map<string, PerformanceAlert[]>() // componentId -> alerts
137
+ private suggestions = new Map<string, OptimizationSuggestion[]>()
138
+ private config: MonitoringConfig
139
+ private dashboardUpdateInterval: NodeJS.Timeout
140
+ private alertCooldowns = new Map<string, number>() // alertType -> lastAlertTime
141
+ private performanceObserver?: any
142
+
143
+ constructor(config?: Partial<MonitoringConfig>) {
144
+ super()
145
+
146
+ this.config = {
147
+ enabled: true,
148
+ sampleRate: 1.0, // Monitor 100% by default
149
+ renderTimeThreshold: 100, // 100ms
150
+ memoryThreshold: 50 * 1024 * 1024, // 50MB
151
+ actionTimeThreshold: 1000, // 1 second
152
+ alertCooldown: 60000, // 1 minute
153
+ historyRetention: 24 * 60 * 60 * 1000, // 24 hours
154
+ dashboardUpdateInterval: 30000, // 30 seconds
155
+ ...config
156
+ }
157
+
158
+ if (this.config.enabled) {
159
+ this.setupPerformanceObserver()
160
+ this.setupDashboardUpdates()
161
+ this.setupCleanupTasks()
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Setup performance observer for native performance monitoring
167
+ */
168
+ private setupPerformanceObserver(): void {
169
+ try {
170
+ // Use Node.js performance hooks if available
171
+ const { PerformanceObserver, performance } = require('perf_hooks')
172
+
173
+ this.performanceObserver = new PerformanceObserver((list: any) => {
174
+ const entries = list.getEntries()
175
+ for (const entry of entries) {
176
+ if (entry.name.startsWith('live-component-')) {
177
+ this.processPerformanceEntry(entry)
178
+ }
179
+ }
180
+ })
181
+
182
+ this.performanceObserver.observe({ entryTypes: ['measure', 'mark'] })
183
+ console.log('๐Ÿ“Š Performance observer initialized')
184
+ } catch (error) {
185
+ console.warn('โš ๏ธ Performance observer not available:', error)
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Process performance entry from observer
191
+ */
192
+ private processPerformanceEntry(entry: any): void {
193
+ const [, componentId, operation] = entry.name.split('-')
194
+
195
+ if (operation === 'render') {
196
+ this.recordRenderTime(componentId, entry.duration)
197
+ } else if (operation === 'action') {
198
+ this.recordActionTime(componentId, 'unknown', entry.duration)
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Setup dashboard update interval
204
+ */
205
+ private setupDashboardUpdates(): void {
206
+ this.dashboardUpdateInterval = setInterval(() => {
207
+ this.updateDashboard()
208
+ }, this.config.dashboardUpdateInterval)
209
+ }
210
+
211
+ /**
212
+ * Setup cleanup tasks
213
+ */
214
+ private setupCleanupTasks(): void {
215
+ // Clean up old data every hour
216
+ setInterval(() => {
217
+ this.cleanupOldData()
218
+ }, 60 * 60 * 1000)
219
+ }
220
+
221
+ /**
222
+ * Initialize metrics for a component
223
+ */
224
+ initializeComponent(componentId: string, componentName: string): void {
225
+ if (!this.config.enabled || !this.shouldSample()) return
226
+
227
+ const metrics: PerformanceMetrics = {
228
+ componentId,
229
+ componentName,
230
+ renderMetrics: {
231
+ totalRenders: 0,
232
+ averageRenderTime: 0,
233
+ minRenderTime: Infinity,
234
+ maxRenderTime: 0,
235
+ lastRenderTime: 0,
236
+ renderTimeHistory: [],
237
+ slowRenderCount: 0,
238
+ renderErrorCount: 0
239
+ },
240
+ actionMetrics: {
241
+ totalActions: 0,
242
+ averageActionTime: 0,
243
+ minActionTime: Infinity,
244
+ maxActionTime: 0,
245
+ actionsByType: {},
246
+ failedActions: 0,
247
+ timeoutActions: 0
248
+ },
249
+ memoryMetrics: {
250
+ currentUsage: 0,
251
+ peakUsage: 0,
252
+ averageUsage: 0,
253
+ memoryLeakDetected: false,
254
+ gcCount: 0,
255
+ stateSize: 0,
256
+ stateSizeHistory: []
257
+ },
258
+ networkMetrics: {
259
+ messagesSent: 0,
260
+ messagesReceived: 0,
261
+ bytesTransferred: 0,
262
+ averageLatency: 0,
263
+ connectionDrops: 0,
264
+ reconnectCount: 0,
265
+ queuedMessages: 0
266
+ },
267
+ userInteractionMetrics: {
268
+ clickCount: 0,
269
+ inputChangeCount: 0,
270
+ formSubmissions: 0,
271
+ averageInteractionTime: 0,
272
+ bounceRate: 0,
273
+ engagementScore: 0
274
+ },
275
+ timestamp: new Date()
276
+ }
277
+
278
+ this.metrics.set(componentId, metrics)
279
+ this.alerts.set(componentId, [])
280
+ this.suggestions.set(componentId, [])
281
+
282
+ console.log(`๐Ÿ“Š Performance monitoring initialized for component: ${componentId}`)
283
+ }
284
+
285
+ /**
286
+ * Record render performance
287
+ */
288
+ recordRenderTime(componentId: string, renderTime: number, error?: Error): void {
289
+ if (!this.config.enabled || !this.shouldSample()) return
290
+
291
+ const metrics = this.metrics.get(componentId)
292
+ if (!metrics) return
293
+
294
+ const renderMetrics = metrics.renderMetrics
295
+
296
+ if (error) {
297
+ renderMetrics.renderErrorCount++
298
+ this.createAlert(componentId, 'warning', 'render', `Render error: ${error.message}`, 0, 1)
299
+ return
300
+ }
301
+
302
+ // Update render metrics
303
+ renderMetrics.totalRenders++
304
+ renderMetrics.lastRenderTime = renderTime
305
+ renderMetrics.minRenderTime = Math.min(renderMetrics.minRenderTime, renderTime)
306
+ renderMetrics.maxRenderTime = Math.max(renderMetrics.maxRenderTime, renderTime)
307
+
308
+ // Update average
309
+ renderMetrics.averageRenderTime =
310
+ (renderMetrics.averageRenderTime * (renderMetrics.totalRenders - 1) + renderTime) / renderMetrics.totalRenders
311
+
312
+ // Track history (keep last 100 renders)
313
+ renderMetrics.renderTimeHistory.push(renderTime)
314
+ if (renderMetrics.renderTimeHistory.length > 100) {
315
+ renderMetrics.renderTimeHistory.shift()
316
+ }
317
+
318
+ // Check for slow renders
319
+ if (renderTime > this.config.renderTimeThreshold) {
320
+ renderMetrics.slowRenderCount++
321
+
322
+ if (renderTime > this.config.renderTimeThreshold * 2) {
323
+ this.createAlert(componentId, 'warning', 'render',
324
+ `Slow render detected: ${renderTime.toFixed(2)}ms`,
325
+ this.config.renderTimeThreshold, renderTime)
326
+ }
327
+ }
328
+
329
+ // Generate optimization suggestions
330
+ this.analyzeRenderPerformance(componentId, metrics)
331
+
332
+ metrics.timestamp = new Date()
333
+ }
334
+
335
+ /**
336
+ * Record action performance
337
+ */
338
+ recordActionTime(componentId: string, actionName: string, actionTime: number, error?: Error): void {
339
+ if (!this.config.enabled || !this.shouldSample()) return
340
+
341
+ const metrics = this.metrics.get(componentId)
342
+ if (!metrics) return
343
+
344
+ const actionMetrics = metrics.actionMetrics
345
+
346
+ if (error) {
347
+ actionMetrics.failedActions++
348
+ this.createAlert(componentId, 'warning', 'action',
349
+ `Action failed: ${actionName} - ${error.message}`, 0, 1)
350
+ return
351
+ }
352
+
353
+ // Update overall action metrics
354
+ actionMetrics.totalActions++
355
+ actionMetrics.minActionTime = Math.min(actionMetrics.minActionTime, actionTime)
356
+ actionMetrics.maxActionTime = Math.max(actionMetrics.maxActionTime, actionTime)
357
+ actionMetrics.averageActionTime =
358
+ (actionMetrics.averageActionTime * (actionMetrics.totalActions - 1) + actionTime) / actionMetrics.totalActions
359
+
360
+ // Update action type metrics
361
+ if (!actionMetrics.actionsByType[actionName]) {
362
+ actionMetrics.actionsByType[actionName] = {
363
+ count: 0,
364
+ averageTime: 0,
365
+ minTime: Infinity,
366
+ maxTime: 0,
367
+ errorCount: 0,
368
+ lastExecuted: new Date()
369
+ }
370
+ }
371
+
372
+ const typeMetrics = actionMetrics.actionsByType[actionName]
373
+ typeMetrics.count++
374
+ typeMetrics.minTime = Math.min(typeMetrics.minTime, actionTime)
375
+ typeMetrics.maxTime = Math.max(typeMetrics.maxTime, actionTime)
376
+ typeMetrics.averageTime =
377
+ (typeMetrics.averageTime * (typeMetrics.count - 1) + actionTime) / typeMetrics.count
378
+ typeMetrics.lastExecuted = new Date()
379
+
380
+ // Check for slow actions
381
+ if (actionTime > this.config.actionTimeThreshold) {
382
+ this.createAlert(componentId, 'warning', 'action',
383
+ `Slow action detected: ${actionName} took ${actionTime.toFixed(2)}ms`,
384
+ this.config.actionTimeThreshold, actionTime)
385
+ }
386
+
387
+ // Generate optimization suggestions
388
+ this.analyzeActionPerformance(componentId, actionName, metrics)
389
+
390
+ metrics.timestamp = new Date()
391
+ }
392
+
393
+ /**
394
+ * Record memory usage
395
+ */
396
+ recordMemoryUsage(componentId: string, memoryUsage: number, stateSize?: number): void {
397
+ if (!this.config.enabled || !this.shouldSample()) return
398
+
399
+ const metrics = this.metrics.get(componentId)
400
+ if (!metrics) return
401
+
402
+ const memoryMetrics = metrics.memoryMetrics
403
+
404
+ // Update memory metrics
405
+ memoryMetrics.currentUsage = memoryUsage
406
+ memoryMetrics.peakUsage = Math.max(memoryMetrics.peakUsage, memoryUsage)
407
+
408
+ // Calculate average (simple moving average)
409
+ const sampleCount = Math.min(100, memoryMetrics.gcCount + 1)
410
+ memoryMetrics.averageUsage =
411
+ (memoryMetrics.averageUsage * (sampleCount - 1) + memoryUsage) / sampleCount
412
+
413
+ if (stateSize !== undefined) {
414
+ memoryMetrics.stateSize = stateSize
415
+ memoryMetrics.stateSizeHistory.push(stateSize)
416
+
417
+ // Keep last 100 state sizes
418
+ if (memoryMetrics.stateSizeHistory.length > 100) {
419
+ memoryMetrics.stateSizeHistory.shift()
420
+ }
421
+ }
422
+
423
+ // Check for memory issues
424
+ if (memoryUsage > this.config.memoryThreshold) {
425
+ this.createAlert(componentId, 'critical', 'memory',
426
+ `High memory usage: ${(memoryUsage / 1024 / 1024).toFixed(2)}MB`,
427
+ this.config.memoryThreshold, memoryUsage)
428
+ }
429
+
430
+ // Detect memory leaks (increasing trend over time)
431
+ if (memoryMetrics.stateSizeHistory.length >= 10) {
432
+ const recentSizes = memoryMetrics.stateSizeHistory.slice(-10)
433
+ const trend = this.calculateTrend(recentSizes)
434
+
435
+ if (trend > 0.1) { // 10% increase trend
436
+ memoryMetrics.memoryLeakDetected = true
437
+ this.createAlert(componentId, 'critical', 'memory',
438
+ 'Potential memory leak detected - state size increasing', 0, trend)
439
+ }
440
+ }
441
+
442
+ // Generate optimization suggestions
443
+ this.analyzeMemoryPerformance(componentId, metrics)
444
+
445
+ metrics.timestamp = new Date()
446
+ }
447
+
448
+ /**
449
+ * Record network metrics
450
+ */
451
+ recordNetworkActivity(componentId: string, type: 'sent' | 'received', bytes: number, latency?: number): void {
452
+ if (!this.config.enabled || !this.shouldSample()) return
453
+
454
+ const metrics = this.metrics.get(componentId)
455
+ if (!metrics) return
456
+
457
+ const networkMetrics = metrics.networkMetrics
458
+
459
+ if (type === 'sent') {
460
+ networkMetrics.messagesSent++
461
+ } else {
462
+ networkMetrics.messagesReceived++
463
+ }
464
+
465
+ networkMetrics.bytesTransferred += bytes
466
+
467
+ if (latency !== undefined) {
468
+ const totalMessages = networkMetrics.messagesSent + networkMetrics.messagesReceived
469
+ networkMetrics.averageLatency =
470
+ (networkMetrics.averageLatency * (totalMessages - 1) + latency) / totalMessages
471
+ }
472
+
473
+ metrics.timestamp = new Date()
474
+ }
475
+
476
+ /**
477
+ * Record user interaction
478
+ */
479
+ recordUserInteraction(componentId: string, type: 'click' | 'input' | 'submit', interactionTime?: number): void {
480
+ if (!this.config.enabled || !this.shouldSample()) return
481
+
482
+ const metrics = this.metrics.get(componentId)
483
+ if (!metrics) return
484
+
485
+ const interactionMetrics = metrics.userInteractionMetrics
486
+
487
+ switch (type) {
488
+ case 'click':
489
+ interactionMetrics.clickCount++
490
+ break
491
+ case 'input':
492
+ interactionMetrics.inputChangeCount++
493
+ break
494
+ case 'submit':
495
+ interactionMetrics.formSubmissions++
496
+ break
497
+ }
498
+
499
+ if (interactionTime !== undefined) {
500
+ const totalInteractions = interactionMetrics.clickCount +
501
+ interactionMetrics.inputChangeCount +
502
+ interactionMetrics.formSubmissions
503
+
504
+ interactionMetrics.averageInteractionTime =
505
+ (interactionMetrics.averageInteractionTime * (totalInteractions - 1) + interactionTime) / totalInteractions
506
+ }
507
+
508
+ // Calculate engagement score
509
+ interactionMetrics.engagementScore = this.calculateEngagementScore(interactionMetrics)
510
+
511
+ metrics.timestamp = new Date()
512
+ }
513
+
514
+ /**
515
+ * Calculate engagement score based on interactions
516
+ */
517
+ private calculateEngagementScore(metrics: UserInteractionMetrics): number {
518
+ const totalInteractions = metrics.clickCount + metrics.inputChangeCount + metrics.formSubmissions
519
+ const timeWeight = Math.min(metrics.averageInteractionTime / 1000, 10) // Cap at 10 seconds
520
+ const diversityBonus = (metrics.clickCount > 0 ? 1 : 0) +
521
+ (metrics.inputChangeCount > 0 ? 1 : 0) +
522
+ (metrics.formSubmissions > 0 ? 1 : 0)
523
+
524
+ return Math.min(100, (totalInteractions * timeWeight * diversityBonus) / 10)
525
+ }
526
+
527
+ /**
528
+ * Create performance alert
529
+ */
530
+ private createAlert(
531
+ componentId: string,
532
+ type: 'warning' | 'critical',
533
+ category: 'render' | 'action' | 'memory' | 'network' | 'interaction',
534
+ message: string,
535
+ threshold: number,
536
+ currentValue: number
537
+ ): void {
538
+ const alertKey = `${componentId}-${category}-${type}`
539
+ const now = Date.now()
540
+
541
+ // Check cooldown
542
+ const lastAlert = this.alertCooldowns.get(alertKey)
543
+ if (lastAlert && (now - lastAlert) < this.config.alertCooldown) {
544
+ return
545
+ }
546
+
547
+ const alert: PerformanceAlert = {
548
+ id: `alert-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
549
+ componentId,
550
+ type,
551
+ category,
552
+ message,
553
+ threshold,
554
+ currentValue,
555
+ timestamp: new Date(),
556
+ resolved: false
557
+ }
558
+
559
+ const componentAlerts = this.alerts.get(componentId) || []
560
+ componentAlerts.push(alert)
561
+ this.alerts.set(componentId, componentAlerts)
562
+
563
+ this.alertCooldowns.set(alertKey, now)
564
+
565
+ console.warn(`โš ๏ธ Performance alert [${type}]: ${message}`)
566
+ this.emit('performanceAlert', alert)
567
+ }
568
+
569
+ /**
570
+ * Analyze render performance and generate suggestions
571
+ */
572
+ private analyzeRenderPerformance(componentId: string, metrics: PerformanceMetrics): void {
573
+ const renderMetrics = metrics.renderMetrics
574
+
575
+ // Check for consistently slow renders
576
+ if (renderMetrics.averageRenderTime > this.config.renderTimeThreshold * 0.8) {
577
+ this.createSuggestion(componentId, 'render', 'medium',
578
+ 'Optimize Render Performance',
579
+ 'Component renders are consistently slow. Consider optimizing state updates and reducing re-renders.',
580
+ 'Improved user experience and responsiveness',
581
+ 'Use React.memo, useMemo, or useCallback to prevent unnecessary re-renders. Optimize state structure.',
582
+ `${((this.config.renderTimeThreshold - renderMetrics.averageRenderTime) / renderMetrics.averageRenderTime * 100).toFixed(1)}% faster renders`
583
+ )
584
+ }
585
+
586
+ // Check for render time variance
587
+ if (renderMetrics.renderTimeHistory.length >= 10) {
588
+ const variance = this.calculateVariance(renderMetrics.renderTimeHistory)
589
+ if (variance > renderMetrics.averageRenderTime * 0.5) {
590
+ this.createSuggestion(componentId, 'render', 'low',
591
+ 'Reduce Render Time Variance',
592
+ 'Render times are inconsistent, which can cause jank.',
593
+ 'Smoother user experience',
594
+ 'Identify and optimize conditional rendering logic. Consider lazy loading heavy components.',
595
+ 'More consistent performance'
596
+ )
597
+ }
598
+ }
599
+ }
600
+
601
+ /**
602
+ * Analyze action performance and generate suggestions
603
+ */
604
+ private analyzeActionPerformance(componentId: string, actionName: string, metrics: PerformanceMetrics): void {
605
+ const actionMetrics = metrics.actionMetrics
606
+ const typeMetrics = actionMetrics.actionsByType[actionName]
607
+
608
+ // Check for slow actions
609
+ if (typeMetrics.averageTime > this.config.actionTimeThreshold * 0.8) {
610
+ this.createSuggestion(componentId, 'action', 'high',
611
+ `Optimize ${actionName} Action`,
612
+ `The ${actionName} action is taking longer than expected to complete.`,
613
+ 'Better user experience and responsiveness',
614
+ 'Consider adding loading states, optimizing database queries, or implementing caching.',
615
+ `${((this.config.actionTimeThreshold - typeMetrics.averageTime) / typeMetrics.averageTime * 100).toFixed(1)}% faster actions`
616
+ )
617
+ }
618
+
619
+ // Check for high error rate
620
+ const errorRate = typeMetrics.errorCount / typeMetrics.count
621
+ if (errorRate > 0.1) { // 10% error rate
622
+ this.createSuggestion(componentId, 'action', 'critical',
623
+ `Fix ${actionName} Action Errors`,
624
+ `High error rate detected for ${actionName} action (${(errorRate * 100).toFixed(1)}%).`,
625
+ 'Improved reliability and user experience',
626
+ 'Add proper error handling, input validation, and retry mechanisms.',
627
+ `${((1 - errorRate) * 100).toFixed(1)}% success rate improvement`
628
+ )
629
+ }
630
+ }
631
+
632
+ /**
633
+ * Analyze memory performance and generate suggestions
634
+ */
635
+ private analyzeMemoryPerformance(componentId: string, metrics: PerformanceMetrics): void {
636
+ const memoryMetrics = metrics.memoryMetrics
637
+
638
+ // Check for large state size
639
+ if (memoryMetrics.stateSize > 100 * 1024) { // 100KB
640
+ this.createSuggestion(componentId, 'memory', 'medium',
641
+ 'Optimize State Size',
642
+ 'Component state is larger than recommended, which can impact performance.',
643
+ 'Reduced memory usage and faster serialization',
644
+ 'Consider normalizing state structure, removing unused data, or implementing state compression.',
645
+ `${((memoryMetrics.stateSize - 50 * 1024) / 1024).toFixed(1)}KB reduction potential`
646
+ )
647
+ }
648
+
649
+ // Check for memory leak
650
+ if (memoryMetrics.memoryLeakDetected) {
651
+ this.createSuggestion(componentId, 'memory', 'critical',
652
+ 'Fix Memory Leak',
653
+ 'Potential memory leak detected - memory usage is continuously increasing.',
654
+ 'Prevent application crashes and improve stability',
655
+ 'Review event listeners, timers, and subscriptions for proper cleanup. Use weak references where appropriate.',
656
+ 'Stable memory usage'
657
+ )
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Create optimization suggestion
663
+ */
664
+ private createSuggestion(
665
+ componentId: string,
666
+ type: 'render' | 'memory' | 'network' | 'state' | 'action',
667
+ priority: 'low' | 'medium' | 'high' | 'critical',
668
+ title: string,
669
+ description: string,
670
+ impact: string,
671
+ implementation: string,
672
+ estimatedImprovement: string
673
+ ): void {
674
+ const suggestions = this.suggestions.get(componentId) || []
675
+
676
+ // Check if similar suggestion already exists
677
+ const existingSuggestion = suggestions.find(s => s.title === title && !s.timestamp ||
678
+ (Date.now() - s.timestamp.getTime()) < 24 * 60 * 60 * 1000) // 24 hours
679
+
680
+ if (existingSuggestion) return
681
+
682
+ const suggestion: OptimizationSuggestion = {
683
+ id: `suggestion-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
684
+ componentId,
685
+ type,
686
+ priority,
687
+ title,
688
+ description,
689
+ impact,
690
+ implementation,
691
+ estimatedImprovement,
692
+ timestamp: new Date()
693
+ }
694
+
695
+ suggestions.push(suggestion)
696
+ this.suggestions.set(componentId, suggestions)
697
+
698
+ console.log(`๐Ÿ’ก Optimization suggestion for ${componentId}: ${title}`)
699
+ this.emit('optimizationSuggestion', suggestion)
700
+ }
701
+
702
+ /**
703
+ * Calculate trend from array of numbers
704
+ */
705
+ private calculateTrend(values: number[]): number {
706
+ if (values.length < 2) return 0
707
+
708
+ const n = values.length
709
+ const sumX = (n * (n - 1)) / 2
710
+ const sumY = values.reduce((sum, val) => sum + val, 0)
711
+ const sumXY = values.reduce((sum, val, index) => sum + (index * val), 0)
712
+ const sumX2 = (n * (n - 1) * (2 * n - 1)) / 6
713
+
714
+ const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX)
715
+ return slope / (sumY / n) // Normalize by average
716
+ }
717
+
718
+ /**
719
+ * Calculate variance from array of numbers
720
+ */
721
+ private calculateVariance(values: number[]): number {
722
+ if (values.length < 2) return 0
723
+
724
+ const mean = values.reduce((sum, val) => sum + val, 0) / values.length
725
+ const squaredDiffs = values.map(val => Math.pow(val - mean, 2))
726
+ return squaredDiffs.reduce((sum, val) => sum + val, 0) / values.length
727
+ }
728
+
729
+ /**
730
+ * Should sample this operation based on sample rate
731
+ */
732
+ private shouldSample(): boolean {
733
+ return Math.random() < this.config.sampleRate
734
+ }
735
+
736
+ /**
737
+ * Update dashboard data
738
+ */
739
+ private updateDashboard(): void {
740
+ const dashboard = this.generateDashboard()
741
+ this.emit('dashboardUpdate', dashboard)
742
+ }
743
+
744
+ /**
745
+ * Generate performance dashboard
746
+ */
747
+ generateDashboard(): PerformanceDashboard {
748
+ const allMetrics = Array.from(this.metrics.values())
749
+ const allAlerts = Array.from(this.alerts.values()).flat()
750
+ const allSuggestions = Array.from(this.suggestions.values()).flat()
751
+
752
+ // Calculate overview stats
753
+ const totalComponents = allMetrics.length
754
+ const healthyComponents = allMetrics.filter(m => this.isComponentHealthy(m)).length
755
+ const degradedComponents = allMetrics.filter(m => this.isComponentDegraded(m)).length
756
+ const unhealthyComponents = totalComponents - healthyComponents - degradedComponents
757
+
758
+ const averageRenderTime = allMetrics.reduce((sum, m) => sum + m.renderMetrics.averageRenderTime, 0) / totalComponents || 0
759
+ const averageMemoryUsage = allMetrics.reduce((sum, m) => sum + m.memoryMetrics.currentUsage, 0) / totalComponents || 0
760
+
761
+ const totalAlerts = allAlerts.filter(a => !a.resolved).length
762
+ const criticalAlerts = allAlerts.filter(a => a.type === 'critical' && !a.resolved).length
763
+
764
+ // Get top and worst performers
765
+ const sortedByRender = [...allMetrics].sort((a, b) => a.renderMetrics.averageRenderTime - b.renderMetrics.averageRenderTime)
766
+ const topPerformers = sortedByRender.slice(0, 5)
767
+ const worstPerformers = sortedByRender.slice(-5).reverse()
768
+
769
+ // Get recent alerts
770
+ const recentAlerts = allAlerts
771
+ .filter(a => !a.resolved)
772
+ .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())
773
+ .slice(0, 10)
774
+
775
+ // Get top suggestions
776
+ const topSuggestions = allSuggestions
777
+ .sort((a, b) => {
778
+ const priorityOrder = { critical: 4, high: 3, medium: 2, low: 1 }
779
+ return priorityOrder[b.priority] - priorityOrder[a.priority]
780
+ })
781
+ .slice(0, 10)
782
+
783
+ // Generate trends (simplified - would need historical data storage for real trends)
784
+ const renderTimeHistory = allMetrics.map(m => m.renderMetrics.averageRenderTime)
785
+ const memoryUsageHistory = allMetrics.map(m => m.memoryMetrics.currentUsage)
786
+ const actionTimeHistory = allMetrics.map(m => m.actionMetrics.averageActionTime)
787
+
788
+ return {
789
+ overview: {
790
+ totalComponents,
791
+ healthyComponents,
792
+ degradedComponents,
793
+ unhealthyComponents,
794
+ averageRenderTime,
795
+ averageMemoryUsage,
796
+ totalAlerts,
797
+ criticalAlerts
798
+ },
799
+ topPerformers,
800
+ worstPerformers,
801
+ recentAlerts,
802
+ suggestions: topSuggestions,
803
+ trends: {
804
+ renderTimetrend: renderTimeHistory,
805
+ memoryUsageTrend: memoryUsageHistory,
806
+ actionTimeTrend: actionTimeHistory
807
+ }
808
+ }
809
+ }
810
+
811
+ /**
812
+ * Check if component is healthy
813
+ */
814
+ private isComponentHealthy(metrics: PerformanceMetrics): boolean {
815
+ return metrics.renderMetrics.averageRenderTime < this.config.renderTimeThreshold * 0.5 &&
816
+ metrics.memoryMetrics.currentUsage < this.config.memoryThreshold * 0.5 &&
817
+ metrics.actionMetrics.failedActions / Math.max(metrics.actionMetrics.totalActions, 1) < 0.05
818
+ }
819
+
820
+ /**
821
+ * Check if component is degraded
822
+ */
823
+ private isComponentDegraded(metrics: PerformanceMetrics): boolean {
824
+ return !this.isComponentHealthy(metrics) && !this.isComponentUnhealthy(metrics)
825
+ }
826
+
827
+ /**
828
+ * Check if component is unhealthy
829
+ */
830
+ private isComponentUnhealthy(metrics: PerformanceMetrics): boolean {
831
+ return metrics.renderMetrics.averageRenderTime > this.config.renderTimeThreshold ||
832
+ metrics.memoryMetrics.currentUsage > this.config.memoryThreshold ||
833
+ metrics.actionMetrics.failedActions / Math.max(metrics.actionMetrics.totalActions, 1) > 0.2 ||
834
+ metrics.memoryMetrics.memoryLeakDetected
835
+ }
836
+
837
+ /**
838
+ * Get component metrics
839
+ */
840
+ getComponentMetrics(componentId: string): PerformanceMetrics | null {
841
+ return this.metrics.get(componentId) || null
842
+ }
843
+
844
+ /**
845
+ * Get component alerts
846
+ */
847
+ getComponentAlerts(componentId: string): PerformanceAlert[] {
848
+ return this.alerts.get(componentId) || []
849
+ }
850
+
851
+ /**
852
+ * Get component suggestions
853
+ */
854
+ getComponentSuggestions(componentId: string): OptimizationSuggestion[] {
855
+ return this.suggestions.get(componentId) || []
856
+ }
857
+
858
+ /**
859
+ * Resolve alert
860
+ */
861
+ resolveAlert(alertId: string): boolean {
862
+ for (const alerts of this.alerts.values()) {
863
+ const alert = alerts.find(a => a.id === alertId)
864
+ if (alert) {
865
+ alert.resolved = true
866
+ console.log(`โœ… Alert resolved: ${alertId}`)
867
+ return true
868
+ }
869
+ }
870
+ return false
871
+ }
872
+
873
+ /**
874
+ * Clean up old data
875
+ */
876
+ private cleanupOldData(): void {
877
+ const now = Date.now()
878
+ const cutoff = now - this.config.historyRetention
879
+
880
+ // Clean up old alerts
881
+ for (const [componentId, alerts] of this.alerts) {
882
+ const validAlerts = alerts.filter(alert => alert.timestamp.getTime() > cutoff)
883
+ this.alerts.set(componentId, validAlerts)
884
+ }
885
+
886
+ // Clean up old suggestions
887
+ for (const [componentId, suggestions] of this.suggestions) {
888
+ const validSuggestions = suggestions.filter(suggestion => suggestion.timestamp.getTime() > cutoff)
889
+ this.suggestions.set(componentId, validSuggestions)
890
+ }
891
+
892
+ console.log('๐Ÿงน Performance monitoring data cleanup completed')
893
+ }
894
+
895
+ /**
896
+ * Remove component from monitoring
897
+ */
898
+ removeComponent(componentId: string): void {
899
+ this.metrics.delete(componentId)
900
+ this.alerts.delete(componentId)
901
+ this.suggestions.delete(componentId)
902
+
903
+ console.log(`๐Ÿ“Š Performance monitoring removed for component: ${componentId}`)
904
+ }
905
+
906
+ /**
907
+ * Shutdown performance monitor
908
+ */
909
+ shutdown(): void {
910
+ console.log('๐Ÿ“Š Shutting down Performance Monitor...')
911
+
912
+ if (this.dashboardUpdateInterval) {
913
+ clearInterval(this.dashboardUpdateInterval)
914
+ }
915
+
916
+ if (this.performanceObserver) {
917
+ this.performanceObserver.disconnect()
918
+ }
919
+
920
+ this.metrics.clear()
921
+ this.alerts.clear()
922
+ this.suggestions.clear()
923
+ this.alertCooldowns.clear()
924
+
925
+ console.log('โœ… Performance Monitor shutdown complete')
926
+ }
927
+ }
928
+
929
+ // Global performance monitor instance
930
+ export const performanceMonitor = new LiveComponentPerformanceMonitor()