create-fluxstack 1.13.0 → 1.14.0

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 (61) hide show
  1. package/LLMD/patterns/anti-patterns.md +100 -0
  2. package/LLMD/reference/routing.md +39 -39
  3. package/LLMD/resources/live-auth.md +20 -2
  4. package/LLMD/resources/live-components.md +94 -10
  5. package/LLMD/resources/live-logging.md +95 -33
  6. package/LLMD/resources/live-upload.md +59 -8
  7. package/app/client/index.html +2 -2
  8. package/app/client/public/favicon.svg +46 -0
  9. package/app/client/src/App.tsx +2 -1
  10. package/app/client/src/assets/fluxstack-static.svg +46 -0
  11. package/app/client/src/assets/fluxstack.svg +183 -0
  12. package/app/client/src/components/AppLayout.tsx +138 -9
  13. package/app/client/src/components/BackButton.tsx +13 -13
  14. package/app/client/src/components/DemoPage.tsx +4 -4
  15. package/app/client/src/live/AuthDemo.tsx +23 -21
  16. package/app/client/src/live/ChatDemo.tsx +2 -2
  17. package/app/client/src/live/CounterDemo.tsx +12 -12
  18. package/app/client/src/live/FormDemo.tsx +2 -2
  19. package/app/client/src/live/LiveDebuggerPanel.tsx +779 -0
  20. package/app/client/src/live/RoomChatDemo.tsx +24 -16
  21. package/app/client/src/main.tsx +13 -13
  22. package/app/client/src/pages/ApiTestPage.tsx +6 -6
  23. package/app/client/src/pages/HomePage.tsx +80 -52
  24. package/app/server/live/LiveAdminPanel.ts +1 -0
  25. package/app/server/live/LiveChat.ts +78 -77
  26. package/app/server/live/LiveCounter.ts +1 -1
  27. package/app/server/live/LiveForm.ts +1 -0
  28. package/app/server/live/LiveLocalCounter.ts +38 -37
  29. package/app/server/live/LiveProtectedChat.ts +1 -0
  30. package/app/server/live/LiveRoomChat.ts +1 -0
  31. package/app/server/live/LiveUpload.ts +1 -0
  32. package/app/server/live/register-components.ts +19 -19
  33. package/config/system/runtime.config.ts +4 -0
  34. package/core/build/optimizer.ts +235 -235
  35. package/core/client/components/Live.tsx +17 -11
  36. package/core/client/components/LiveDebugger.tsx +1324 -0
  37. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
  38. package/core/client/hooks/useLiveComponent.ts +11 -1
  39. package/core/client/hooks/useLiveDebugger.ts +392 -0
  40. package/core/client/index.ts +14 -0
  41. package/core/plugins/built-in/index.ts +134 -134
  42. package/core/plugins/built-in/live-components/commands/create-live-component.ts +4 -0
  43. package/core/plugins/built-in/vite/index.ts +75 -21
  44. package/core/server/index.ts +15 -15
  45. package/core/server/live/ComponentRegistry.ts +55 -26
  46. package/core/server/live/FileUploadManager.ts +188 -24
  47. package/core/server/live/LiveDebugger.ts +462 -0
  48. package/core/server/live/LiveLogger.ts +38 -5
  49. package/core/server/live/LiveRoomManager.ts +17 -1
  50. package/core/server/live/StateSignature.ts +87 -27
  51. package/core/server/live/WebSocketConnectionManager.ts +11 -10
  52. package/core/server/live/auto-generated-components.ts +1 -1
  53. package/core/server/live/websocket-plugin.ts +233 -8
  54. package/core/server/plugins/static-files-plugin.ts +179 -69
  55. package/core/types/build.ts +219 -219
  56. package/core/types/plugin.ts +107 -107
  57. package/core/types/types.ts +145 -9
  58. package/core/utils/logger/startup-banner.ts +82 -82
  59. package/core/utils/version.ts +6 -6
  60. package/package.json +1 -1
  61. package/app/client/src/assets/react.svg +0 -1
@@ -0,0 +1,392 @@
1
+ // 🔍 FluxStack Live Component Debugger - Client Hook
2
+ //
3
+ // Connects to the debug WebSocket endpoint and streams debug events.
4
+ // Provides reactive state for building debugger UIs.
5
+ //
6
+ // Usage:
7
+ // const debugger = useLiveDebugger()
8
+ // debugger.components // Active components with current states
9
+ // debugger.events // Event timeline
10
+ // debugger.connected // Connection status
11
+
12
+ import { useState, useEffect, useRef, useCallback } from 'react'
13
+
14
+ // ===== Types (mirrored from server) =====
15
+
16
+ export type DebugEventType =
17
+ | 'COMPONENT_MOUNT'
18
+ | 'COMPONENT_UNMOUNT'
19
+ | 'COMPONENT_REHYDRATE'
20
+ | 'STATE_CHANGE'
21
+ | 'ACTION_CALL'
22
+ | 'ACTION_RESULT'
23
+ | 'ACTION_ERROR'
24
+ | 'ROOM_JOIN'
25
+ | 'ROOM_LEAVE'
26
+ | 'ROOM_EMIT'
27
+ | 'ROOM_EVENT_RECEIVED'
28
+ | 'WS_CONNECT'
29
+ | 'WS_DISCONNECT'
30
+ | 'ERROR'
31
+
32
+ export interface DebugEvent {
33
+ id: string
34
+ timestamp: number
35
+ type: DebugEventType
36
+ componentId: string | null
37
+ componentName: string | null
38
+ data: Record<string, unknown>
39
+ }
40
+
41
+ export interface ComponentSnapshot {
42
+ componentId: string
43
+ componentName: string
44
+ /** Developer-defined label for easier identification in the debugger */
45
+ debugLabel?: string
46
+ state: Record<string, unknown>
47
+ rooms: string[]
48
+ mountedAt: number
49
+ lastActivity: number
50
+ actionCount: number
51
+ stateChangeCount: number
52
+ errorCount: number
53
+ }
54
+
55
+ export interface DebugSnapshot {
56
+ components: ComponentSnapshot[]
57
+ connections: number
58
+ uptime: number
59
+ totalEvents: number
60
+ }
61
+
62
+ export interface DebugFilter {
63
+ componentId?: string | null
64
+ types?: Set<DebugEventType>
65
+ search?: string
66
+ }
67
+
68
+ export interface UseLiveDebuggerReturn {
69
+ // Connection
70
+ connected: boolean
71
+ connecting: boolean
72
+ /** Server reported that debugging is disabled */
73
+ serverDisabled: boolean
74
+
75
+ // Data
76
+ components: ComponentSnapshot[]
77
+ events: DebugEvent[]
78
+ filteredEvents: DebugEvent[]
79
+ snapshot: DebugSnapshot | null
80
+
81
+ // Selected component
82
+ selectedComponentId: string | null
83
+ selectedComponent: ComponentSnapshot | null
84
+ selectComponent: (id: string | null) => void
85
+
86
+ // Filtering
87
+ filter: DebugFilter
88
+ setFilter: (filter: Partial<DebugFilter>) => void
89
+
90
+ // Controls
91
+ paused: boolean
92
+ togglePause: () => void
93
+ clearEvents: () => void
94
+ reconnect: () => void
95
+
96
+ // Stats
97
+ eventCount: number
98
+ componentCount: number
99
+ }
100
+
101
+ export interface UseLiveDebuggerOptions {
102
+ /** Max events to keep in memory. Default: 500 */
103
+ maxEvents?: number
104
+ /** Auto-connect on mount. Default: true */
105
+ autoConnect?: boolean
106
+ /** Custom WebSocket URL */
107
+ url?: string
108
+ }
109
+
110
+ // ===== Hook =====
111
+
112
+ export function useLiveDebugger(options: UseLiveDebuggerOptions = {}): UseLiveDebuggerReturn {
113
+ const {
114
+ maxEvents = 500,
115
+ autoConnect = true,
116
+ url
117
+ } = options
118
+
119
+ // State
120
+ const [connected, setConnected] = useState(false)
121
+ const [connecting, setConnecting] = useState(false)
122
+ const [components, setComponents] = useState<ComponentSnapshot[]>([])
123
+ const [events, setEvents] = useState<DebugEvent[]>([])
124
+ const [snapshot, setSnapshot] = useState<DebugSnapshot | null>(null)
125
+ const [selectedComponentId, setSelectedComponentId] = useState<string | null>(null)
126
+ const [filter, setFilterState] = useState<DebugFilter>({})
127
+ const [paused, setPaused] = useState(false)
128
+ const [serverDisabled, setServerDisabled] = useState(false)
129
+
130
+ // Refs
131
+ const wsRef = useRef<WebSocket | null>(null)
132
+ const pausedRef = useRef(false)
133
+ const serverDisabledRef = useRef(false)
134
+ const reconnectTimeoutRef = useRef<number | null>(null)
135
+
136
+ // Keep refs in sync
137
+ pausedRef.current = paused
138
+ serverDisabledRef.current = serverDisabled
139
+
140
+ // Build WebSocket URL
141
+ const getWsUrl = useCallback(() => {
142
+ if (url) return url
143
+ if (typeof window === 'undefined') return 'ws://localhost:3000/api/live/debug/ws'
144
+ const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
145
+ return `${protocol}//${window.location.host}/api/live/debug/ws`
146
+ }, [url])
147
+
148
+ // Connect
149
+ const connect = useCallback(() => {
150
+ if (wsRef.current?.readyState === WebSocket.CONNECTING) return
151
+ if (wsRef.current?.readyState === WebSocket.OPEN) return
152
+
153
+ setConnecting(true)
154
+
155
+ try {
156
+ const ws = new WebSocket(getWsUrl())
157
+ wsRef.current = ws
158
+
159
+ ws.onopen = () => {
160
+ setConnected(true)
161
+ setConnecting(false)
162
+ }
163
+
164
+ ws.onmessage = (event) => {
165
+ try {
166
+ const msg = JSON.parse(event.data)
167
+
168
+ if (msg.type === 'DEBUG_DISABLED') {
169
+ // Server has debugging disabled — stop reconnecting
170
+ setServerDisabled(true)
171
+ return
172
+ }
173
+
174
+ if (msg.type === 'DEBUG_WELCOME') {
175
+ // Initial snapshot
176
+ setServerDisabled(false)
177
+ const snap = msg.snapshot as DebugSnapshot
178
+ setSnapshot(snap)
179
+ setComponents(snap.components)
180
+ } else if (msg.type === 'DEBUG_EVENT') {
181
+ if (pausedRef.current) return
182
+
183
+ const debugEvent = msg.event as DebugEvent
184
+
185
+ // Update events list
186
+ setEvents(prev => {
187
+ const next = [...prev, debugEvent]
188
+ return next.length > maxEvents ? next.slice(-maxEvents) : next
189
+ })
190
+
191
+ // Update component snapshots based on event
192
+ updateComponentsFromEvent(debugEvent)
193
+ } else if (msg.type === 'DEBUG_SNAPSHOT') {
194
+ const snap = msg.snapshot as DebugSnapshot
195
+ setSnapshot(snap)
196
+ setComponents(snap.components)
197
+ }
198
+ } catch {
199
+ // Ignore parse errors
200
+ }
201
+ }
202
+
203
+ ws.onclose = () => {
204
+ setConnected(false)
205
+ setConnecting(false)
206
+ wsRef.current = null
207
+
208
+ // Don't reconnect if server told us debug is disabled
209
+ if (serverDisabledRef.current) return
210
+
211
+ // Auto-reconnect after 3 seconds
212
+ reconnectTimeoutRef.current = window.setTimeout(() => {
213
+ if (autoConnect) connect()
214
+ }, 3000)
215
+ }
216
+
217
+ ws.onerror = () => {
218
+ setConnecting(false)
219
+ }
220
+ } catch {
221
+ setConnecting(false)
222
+ }
223
+ }, [getWsUrl, maxEvents, autoConnect])
224
+
225
+ // Update components from incoming events
226
+ const updateComponentsFromEvent = useCallback((event: DebugEvent) => {
227
+ setComponents(prev => {
228
+ switch (event.type) {
229
+ case 'COMPONENT_MOUNT': {
230
+ if (!event.componentId || !event.componentName) return prev
231
+ const existing = prev.find(c => c.componentId === event.componentId)
232
+ if (existing) return prev
233
+ return [...prev, {
234
+ componentId: event.componentId,
235
+ componentName: event.componentName,
236
+ debugLabel: (event.data.debugLabel as string) || undefined,
237
+ state: (event.data.initialState as Record<string, unknown>) || {},
238
+ rooms: event.data.room ? [event.data.room as string] : [],
239
+ mountedAt: event.timestamp,
240
+ lastActivity: event.timestamp,
241
+ actionCount: 0,
242
+ stateChangeCount: 0,
243
+ errorCount: 0
244
+ }]
245
+ }
246
+
247
+ case 'COMPONENT_UNMOUNT': {
248
+ return prev.filter(c => c.componentId !== event.componentId)
249
+ }
250
+
251
+ case 'STATE_CHANGE': {
252
+ return prev.map(c => {
253
+ if (c.componentId !== event.componentId) return c
254
+ return {
255
+ ...c,
256
+ state: (event.data.fullState as Record<string, unknown>) || c.state,
257
+ stateChangeCount: c.stateChangeCount + 1,
258
+ lastActivity: event.timestamp
259
+ }
260
+ })
261
+ }
262
+
263
+ case 'ACTION_CALL': {
264
+ return prev.map(c => {
265
+ if (c.componentId !== event.componentId) return c
266
+ return {
267
+ ...c,
268
+ actionCount: c.actionCount + 1,
269
+ lastActivity: event.timestamp
270
+ }
271
+ })
272
+ }
273
+
274
+ case 'ACTION_ERROR':
275
+ case 'ERROR': {
276
+ return prev.map(c => {
277
+ if (c.componentId !== event.componentId) return c
278
+ return {
279
+ ...c,
280
+ errorCount: c.errorCount + 1,
281
+ lastActivity: event.timestamp
282
+ }
283
+ })
284
+ }
285
+
286
+ case 'ROOM_JOIN': {
287
+ return prev.map(c => {
288
+ if (c.componentId !== event.componentId) return c
289
+ const roomId = event.data.roomId as string
290
+ if (c.rooms.includes(roomId)) return c
291
+ return { ...c, rooms: [...c.rooms, roomId] }
292
+ })
293
+ }
294
+
295
+ case 'ROOM_LEAVE': {
296
+ return prev.map(c => {
297
+ if (c.componentId !== event.componentId) return c
298
+ const roomId = event.data.roomId as string
299
+ return { ...c, rooms: c.rooms.filter(r => r !== roomId) }
300
+ })
301
+ }
302
+
303
+ default:
304
+ return prev.map(c => {
305
+ if (c.componentId !== event.componentId) return c
306
+ return { ...c, lastActivity: event.timestamp }
307
+ })
308
+ }
309
+ })
310
+ }, [])
311
+
312
+ // Disconnect
313
+ const disconnect = useCallback(() => {
314
+ if (reconnectTimeoutRef.current) {
315
+ clearTimeout(reconnectTimeoutRef.current)
316
+ reconnectTimeoutRef.current = null
317
+ }
318
+ if (wsRef.current) {
319
+ wsRef.current.close()
320
+ wsRef.current = null
321
+ }
322
+ setConnected(false)
323
+ setConnecting(false)
324
+ }, [])
325
+
326
+ // Reconnect
327
+ const reconnect = useCallback(() => {
328
+ disconnect()
329
+ setTimeout(() => connect(), 100)
330
+ }, [connect, disconnect])
331
+
332
+ // Filter events
333
+ const filteredEvents = events.filter(event => {
334
+ if (filter.componentId && event.componentId !== filter.componentId) return false
335
+ if (filter.types && filter.types.size > 0 && !filter.types.has(event.type)) return false
336
+ if (filter.search) {
337
+ const search = filter.search.toLowerCase()
338
+ const matchesData = JSON.stringify(event.data).toLowerCase().includes(search)
339
+ const matchesName = event.componentName?.toLowerCase().includes(search)
340
+ const matchesType = event.type.toLowerCase().includes(search)
341
+ if (!matchesData && !matchesName && !matchesType) return false
342
+ }
343
+ return true
344
+ })
345
+
346
+ // Selected component
347
+ const selectedComponent = selectedComponentId
348
+ ? components.find(c => c.componentId === selectedComponentId) ?? null
349
+ : null
350
+
351
+ // Filter setter
352
+ const setFilter = useCallback((partial: Partial<DebugFilter>) => {
353
+ setFilterState(prev => ({ ...prev, ...partial }))
354
+ }, [])
355
+
356
+ // Toggle pause
357
+ const togglePause = useCallback(() => {
358
+ setPaused(prev => !prev)
359
+ }, [])
360
+
361
+ // Clear events
362
+ const clearEvents = useCallback(() => {
363
+ setEvents([])
364
+ }, [])
365
+
366
+ // Auto-connect
367
+ useEffect(() => {
368
+ if (autoConnect) connect()
369
+ return () => disconnect()
370
+ }, [autoConnect, connect, disconnect])
371
+
372
+ return {
373
+ connected,
374
+ connecting,
375
+ serverDisabled,
376
+ components,
377
+ events,
378
+ filteredEvents,
379
+ snapshot,
380
+ selectedComponentId,
381
+ selectedComponent,
382
+ selectComponent: setSelectedComponentId,
383
+ filter,
384
+ setFilter,
385
+ paused,
386
+ togglePause,
387
+ clearEvents,
388
+ reconnect,
389
+ eventCount: events.length,
390
+ componentCount: components.length
391
+ }
392
+ }
@@ -29,3 +29,17 @@ export { useLiveUpload } from './hooks/useLiveUpload'
29
29
 
30
30
  // Live Component Hook (API principal)
31
31
  export { Live } from './components/Live'
32
+
33
+ // Live Component Debugger
34
+ export { LiveDebugger } from './components/LiveDebugger'
35
+ export type { LiveDebuggerProps } from './components/LiveDebugger'
36
+ export { useLiveDebugger } from './hooks/useLiveDebugger'
37
+ export type {
38
+ DebugEvent,
39
+ DebugEventType,
40
+ ComponentSnapshot,
41
+ DebugSnapshot,
42
+ DebugFilter,
43
+ UseLiveDebuggerReturn,
44
+ UseLiveDebuggerOptions
45
+ } from './hooks/useLiveDebugger'
@@ -1,135 +1,135 @@
1
- /**
2
- * Built-in Plugins for FluxStack
3
- * Core plugins that provide essential functionality
4
- *
5
- * Note: Logger is NOT a plugin - it's core infrastructure used by plugins
6
- */
7
-
8
- // Import all built-in plugins
9
- import { swaggerPlugin } from './swagger'
10
- import { vitePlugin } from './vite'
11
- import { monitoringPlugin } from './monitoring'
12
-
13
- // Export individual plugins
14
- export { swaggerPlugin } from './swagger'
15
- export { vitePlugin } from './vite'
16
- export { monitoringPlugin } from './monitoring'
17
-
18
- // Deprecated: staticPlugin is now merged into vitePlugin (auto-detects dev/prod)
19
- /** @deprecated Use vitePlugin instead - it now handles both dev and prod */
20
- export const staticPlugin = vitePlugin
21
-
22
- // Export as a collection
23
- export const builtInPlugins = {
24
- swagger: swaggerPlugin,
25
- vite: vitePlugin,
26
- static: staticPlugin,
27
- monitoring: monitoringPlugin
28
- } as const
29
-
30
- // Export as an array for easy registration
31
- export const builtInPluginsList = [
32
- swaggerPlugin,
33
- vitePlugin,
34
- staticPlugin,
35
- monitoringPlugin
36
- ] as const
37
-
38
- // Plugin categories
39
- export const pluginCategories = {
40
- core: [vitePlugin], // vitePlugin now handles both dev (Vite) and prod (static)
41
- development: [vitePlugin],
42
- documentation: [swaggerPlugin],
43
- monitoring: [monitoringPlugin]
44
- } as const
45
-
46
- // Default plugin configuration
47
- export const defaultPluginConfig = {
48
- swagger: {
49
- enabled: true,
50
- path: '/swagger',
51
- title: 'FluxStack API',
52
- description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
53
- },
54
- vite: {
55
- enabled: true,
56
- port: 5173,
57
- host: 'localhost',
58
- checkInterval: 2000,
59
- maxRetries: 10,
60
- timeout: 5000
61
- },
62
- static: {
63
- enabled: true,
64
- publicDir: 'public',
65
- distDir: 'dist/client',
66
- indexFile: 'index.html',
67
- spa: {
68
- enabled: true,
69
- fallback: 'index.html'
70
- }
71
- },
72
- monitoring: {
73
- enabled: false, // Disabled by default to avoid overhead
74
- httpMetrics: true,
75
- systemMetrics: true,
76
- customMetrics: true,
77
- collectInterval: 5000,
78
- retentionPeriod: 300000,
79
- exporters: [
80
- {
81
- type: 'console',
82
- interval: 30000,
83
- enabled: false
84
- }
85
- ],
86
- thresholds: {
87
- responseTime: 1000,
88
- errorRate: 0.05,
89
- memoryUsage: 0.8,
90
- cpuUsage: 0.8
91
- }
92
- }
93
- } as const
94
-
95
- /**
96
- * Get default plugins for a specific environment
97
- */
98
- export function getDefaultPlugins(environment: 'development' | 'production' | 'test' = 'development') {
99
- // vitePlugin now auto-detects dev/prod and serves appropriately
100
- const basePlugins = [vitePlugin]
101
-
102
- switch (environment) {
103
- case 'development':
104
- return [...basePlugins, swaggerPlugin, monitoringPlugin]
105
- case 'production':
106
- return [...basePlugins, monitoringPlugin]
107
- case 'test':
108
- return [] // Minimal plugins for testing
109
- default:
110
- return basePlugins
111
- }
112
- }
113
-
114
- /**
115
- * Get plugin by name
116
- */
117
- export function getBuiltInPlugin(name: string) {
118
- return builtInPlugins[name as keyof typeof builtInPlugins]
119
- }
120
-
121
- /**
122
- * Check if a plugin is built-in
123
- */
124
- export function isBuiltInPlugin(name: string): boolean {
125
- return name in builtInPlugins
126
- }
127
-
128
- /**
129
- * Get plugins by category
130
- */
131
- export function getPluginsByCategory(category: keyof typeof pluginCategories) {
132
- return pluginCategories[category] || []
133
- }
134
-
1
+ /**
2
+ * Built-in Plugins for FluxStack
3
+ * Core plugins that provide essential functionality
4
+ *
5
+ * Note: Logger is NOT a plugin - it's core infrastructure used by plugins
6
+ */
7
+
8
+ // Import all built-in plugins
9
+ import { swaggerPlugin } from './swagger'
10
+ import { vitePlugin } from './vite'
11
+ import { monitoringPlugin } from './monitoring'
12
+
13
+ // Export individual plugins
14
+ export { swaggerPlugin } from './swagger'
15
+ export { vitePlugin } from './vite'
16
+ export { monitoringPlugin } from './monitoring'
17
+
18
+ // Deprecated: staticPlugin is now merged into vitePlugin (auto-detects dev/prod)
19
+ /** @deprecated Use vitePlugin instead - it now handles both dev and prod */
20
+ export const staticPlugin = vitePlugin
21
+
22
+ // Export as a collection
23
+ export const builtInPlugins = {
24
+ swagger: swaggerPlugin,
25
+ vite: vitePlugin,
26
+ static: staticPlugin,
27
+ monitoring: monitoringPlugin
28
+ } as const
29
+
30
+ // Export as an array for easy registration
31
+ export const builtInPluginsList = [
32
+ swaggerPlugin,
33
+ vitePlugin,
34
+ staticPlugin,
35
+ monitoringPlugin
36
+ ] as const
37
+
38
+ // Plugin categories
39
+ export const pluginCategories = {
40
+ core: [vitePlugin], // vitePlugin now handles both dev (Vite) and prod (static)
41
+ development: [vitePlugin],
42
+ documentation: [swaggerPlugin],
43
+ monitoring: [monitoringPlugin]
44
+ } as const
45
+
46
+ // Default plugin configuration
47
+ export const defaultPluginConfig = {
48
+ swagger: {
49
+ enabled: true,
50
+ path: '/swagger',
51
+ title: 'FluxStack API',
52
+ description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
53
+ },
54
+ vite: {
55
+ enabled: true,
56
+ port: 5173,
57
+ host: 'localhost',
58
+ checkInterval: 2000,
59
+ maxRetries: 10,
60
+ timeout: 5000
61
+ },
62
+ static: {
63
+ enabled: true,
64
+ publicDir: 'public',
65
+ distDir: 'dist/client',
66
+ indexFile: 'index.html',
67
+ spa: {
68
+ enabled: true,
69
+ fallback: 'index.html'
70
+ }
71
+ },
72
+ monitoring: {
73
+ enabled: false, // Disabled by default to avoid overhead
74
+ httpMetrics: true,
75
+ systemMetrics: true,
76
+ customMetrics: true,
77
+ collectInterval: 5000,
78
+ retentionPeriod: 300000,
79
+ exporters: [
80
+ {
81
+ type: 'console',
82
+ interval: 30000,
83
+ enabled: false
84
+ }
85
+ ],
86
+ thresholds: {
87
+ responseTime: 1000,
88
+ errorRate: 0.05,
89
+ memoryUsage: 0.8,
90
+ cpuUsage: 0.8
91
+ }
92
+ }
93
+ } as const
94
+
95
+ /**
96
+ * Get default plugins for a specific environment
97
+ */
98
+ export function getDefaultPlugins(environment: 'development' | 'production' | 'test' = 'development') {
99
+ // vitePlugin now auto-detects dev/prod and serves appropriately
100
+ const basePlugins = [vitePlugin]
101
+
102
+ switch (environment) {
103
+ case 'development':
104
+ return [...basePlugins, swaggerPlugin, monitoringPlugin]
105
+ case 'production':
106
+ return [...basePlugins, monitoringPlugin]
107
+ case 'test':
108
+ return [] // Minimal plugins for testing
109
+ default:
110
+ return basePlugins
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Get plugin by name
116
+ */
117
+ export function getBuiltInPlugin(name: string) {
118
+ return builtInPlugins[name as keyof typeof builtInPlugins]
119
+ }
120
+
121
+ /**
122
+ * Check if a plugin is built-in
123
+ */
124
+ export function isBuiltInPlugin(name: string): boolean {
125
+ return name in builtInPlugins
126
+ }
127
+
128
+ /**
129
+ * Get plugins by category
130
+ */
131
+ export function getPluginsByCategory(category: keyof typeof pluginCategories) {
132
+ return pluginCategories[category] || []
133
+ }
134
+
135
135
  export default builtInPlugins