create-fluxstack 1.0.13 → 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 (214) 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/runtime-config.ts +3 -3
  90. package/core/config/schema.ts +84 -49
  91. package/core/framework/server.ts +30 -0
  92. package/core/index.ts +25 -0
  93. package/core/live/ComponentRegistry.ts +399 -0
  94. package/core/live/types.ts +164 -0
  95. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
  96. package/core/plugins/built-in/live-components/index.ts +27 -0
  97. package/core/plugins/built-in/logger/index.ts +1 -1
  98. package/core/plugins/built-in/monitoring/index.ts +1 -1
  99. package/core/plugins/built-in/static/index.ts +1 -1
  100. package/core/plugins/built-in/swagger/index.ts +1 -1
  101. package/core/plugins/built-in/vite/index.ts +1 -1
  102. package/core/plugins/dependency-manager.ts +384 -0
  103. package/core/plugins/index.ts +5 -1
  104. package/core/plugins/manager.ts +7 -3
  105. package/core/plugins/registry.ts +88 -10
  106. package/core/plugins/types.ts +11 -11
  107. package/core/server/framework.ts +43 -0
  108. package/core/server/index.ts +11 -1
  109. package/core/server/live/ComponentRegistry.ts +1017 -0
  110. package/core/server/live/FileUploadManager.ts +272 -0
  111. package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
  112. package/core/server/live/SingleConnectionManager.ts +0 -0
  113. package/core/server/live/StateSignature.ts +644 -0
  114. package/core/server/live/WebSocketConnectionManager.ts +688 -0
  115. package/core/server/live/websocket-plugin.ts +435 -0
  116. package/core/server/middleware/errorHandling.ts +141 -0
  117. package/core/server/middleware/index.ts +16 -0
  118. package/core/server/plugins/static-files-plugin.ts +232 -0
  119. package/core/server/services/BaseService.ts +95 -0
  120. package/core/server/services/ServiceContainer.ts +144 -0
  121. package/core/server/services/index.ts +9 -0
  122. package/core/templates/create-project.ts +46 -2
  123. package/core/testing/index.ts +10 -0
  124. package/core/testing/setup.ts +74 -0
  125. package/core/types/build.ts +38 -14
  126. package/core/types/types.ts +319 -0
  127. package/core/utils/env-runtime.ts +7 -0
  128. package/core/utils/errors/handlers.ts +264 -39
  129. package/core/utils/errors/index.ts +528 -18
  130. package/core/utils/errors/middleware.ts +114 -0
  131. package/core/utils/logger/formatters.ts +222 -0
  132. package/core/utils/logger/index.ts +167 -48
  133. package/core/utils/logger/middleware.ts +253 -0
  134. package/core/utils/logger/performance.ts +384 -0
  135. package/core/utils/logger/transports.ts +365 -0
  136. package/create-fluxstack.ts +296 -296
  137. package/fluxstack.config.ts +17 -1
  138. package/package-template.json +66 -66
  139. package/package.json +31 -6
  140. package/public/README.md +16 -0
  141. package/vite.config.ts +29 -14
  142. package/.claude/settings.local.json +0 -74
  143. package/.github/workflows/ci-build-tests.yml +0 -480
  144. package/.github/workflows/dependency-management.yml +0 -324
  145. package/.github/workflows/release-validation.yml +0 -355
  146. package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
  147. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
  148. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
  149. package/CLAUDE.md +0 -200
  150. package/Dockerfile +0 -58
  151. package/Dockerfile.backend +0 -52
  152. package/Dockerfile.frontend +0 -54
  153. package/README-Docker.md +0 -85
  154. package/ai-context/00-QUICK-START.md +0 -86
  155. package/ai-context/README.md +0 -88
  156. package/ai-context/development/eden-treaty-guide.md +0 -362
  157. package/ai-context/development/patterns.md +0 -382
  158. package/ai-context/development/plugins-guide.md +0 -572
  159. package/ai-context/examples/crud-complete.md +0 -626
  160. package/ai-context/project/architecture.md +0 -399
  161. package/ai-context/project/overview.md +0 -213
  162. package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
  163. package/ai-context/recent-changes/type-inference-fix.md +0 -223
  164. package/ai-context/reference/environment-vars.md +0 -384
  165. package/ai-context/reference/troubleshooting.md +0 -407
  166. package/app/client/src/components/TestPage.tsx +0 -453
  167. package/bun.lock +0 -1063
  168. package/bunfig.toml +0 -16
  169. package/core/__tests__/integration.test.ts +0 -227
  170. package/core/build/index.ts +0 -186
  171. package/core/config/__tests__/config-loader.test.ts +0 -554
  172. package/core/config/__tests__/config-merger.test.ts +0 -657
  173. package/core/config/__tests__/env-converter.test.ts +0 -372
  174. package/core/config/__tests__/env-processor.test.ts +0 -431
  175. package/core/config/__tests__/env.test.ts +0 -452
  176. package/core/config/__tests__/integration.test.ts +0 -418
  177. package/core/config/__tests__/loader.test.ts +0 -331
  178. package/core/config/__tests__/schema.test.ts +0 -129
  179. package/core/config/__tests__/validator.test.ts +0 -318
  180. package/core/framework/__tests__/server.test.ts +0 -233
  181. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  182. package/core/plugins/__tests__/manager.test.ts +0 -398
  183. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  184. package/core/plugins/__tests__/registry.test.ts +0 -335
  185. package/core/utils/__tests__/errors.test.ts +0 -139
  186. package/core/utils/__tests__/helpers.test.ts +0 -297
  187. package/core/utils/__tests__/logger.test.ts +0 -141
  188. package/create-test-app.ts +0 -156
  189. package/docker-compose.microservices.yml +0 -75
  190. package/docker-compose.simple.yml +0 -57
  191. package/docker-compose.yml +0 -71
  192. package/eslint.config.js +0 -23
  193. package/flux-cli.ts +0 -214
  194. package/nginx-lb.conf +0 -37
  195. package/publish.sh +0 -63
  196. package/run-clean.ts +0 -26
  197. package/run-env-tests.ts +0 -313
  198. package/tailwind.config.js +0 -34
  199. package/tests/__mocks__/api.ts +0 -56
  200. package/tests/fixtures/users.ts +0 -69
  201. package/tests/integration/api/users.routes.test.ts +0 -221
  202. package/tests/setup.ts +0 -29
  203. package/tests/unit/app/client/App-simple.test.tsx +0 -56
  204. package/tests/unit/app/client/App.test.tsx.skip +0 -237
  205. package/tests/unit/app/client/eden-api.test.ts +0 -186
  206. package/tests/unit/app/client/simple.test.tsx +0 -23
  207. package/tests/unit/app/controllers/users.controller.test.ts +0 -150
  208. package/tests/unit/core/create-project.test.ts.skip +0 -95
  209. package/tests/unit/core/framework.test.ts +0 -144
  210. package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
  211. package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
  212. package/tests/utils/test-helpers.ts +0 -61
  213. package/vitest.config.ts +0 -50
  214. package/workspace.json +0 -6
@@ -0,0 +1,435 @@
1
+ // 🔥 FluxStack Live Components - Enhanced WebSocket Plugin with Connection Management
2
+
3
+ import { componentRegistry } from './ComponentRegistry'
4
+ import { fileUploadManager } from './FileUploadManager'
5
+ import { connectionManager } from './WebSocketConnectionManager'
6
+ import { performanceMonitor } from './LiveComponentPerformanceMonitor'
7
+ import type { LiveMessage, FileUploadStartMessage, FileUploadChunkMessage, FileUploadCompleteMessage } from '../../types/types'
8
+ import type { Plugin, PluginContext } from '../../plugins/types'
9
+ import { t } from 'elysia'
10
+ import path from 'path'
11
+
12
+ export const liveComponentsPlugin: Plugin = {
13
+ name: 'live-components',
14
+ version: '1.0.0',
15
+ description: 'Real-time Live Components with Elysia native WebSocket support',
16
+ author: 'FluxStack Team',
17
+ priority: 'normal',
18
+ category: 'core',
19
+ tags: ['websocket', 'real-time', 'live-components'],
20
+
21
+ setup: async (context: PluginContext) => {
22
+ context.logger.info('🔌 Setting up Live Components plugin with Elysia WebSocket...')
23
+
24
+ // Auto-discover components from app/server/live directory
25
+ const componentsPath = path.join(process.cwd(), 'app', 'server', 'live')
26
+ await componentRegistry.autoDiscoverComponents(componentsPath)
27
+ context.logger.info('🔍 Component auto-discovery completed')
28
+
29
+ // Add WebSocket route for Live Components
30
+ context.app
31
+ .ws('/api/live/ws', {
32
+ body: t.Object({
33
+ type: t.String(),
34
+ componentId: t.String(),
35
+ action: t.Optional(t.String()),
36
+ payload: t.Optional(t.Any()),
37
+ timestamp: t.Optional(t.Number()),
38
+ userId: t.Optional(t.String()),
39
+ room: t.Optional(t.String()),
40
+ requestId: t.Optional(t.String()),
41
+ expectResponse: t.Optional(t.Boolean()),
42
+ // File upload specific fields
43
+ uploadId: t.Optional(t.String()),
44
+ filename: t.Optional(t.String()),
45
+ fileType: t.Optional(t.String()),
46
+ fileSize: t.Optional(t.Number()),
47
+ chunkSize: t.Optional(t.Number()),
48
+ chunkIndex: t.Optional(t.Number()),
49
+ totalChunks: t.Optional(t.Number()),
50
+ data: t.Optional(t.String()),
51
+ hash: t.Optional(t.String())
52
+ }),
53
+
54
+ open(ws) {
55
+ const connectionId = `ws-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
56
+ console.log(`🔌 Live Components WebSocket connected: ${connectionId}`)
57
+
58
+ // Register connection with enhanced connection manager
59
+ connectionManager.registerConnection(ws, connectionId, 'live-components')
60
+
61
+ // Initialize and store connection data in ws.data
62
+ if (!ws.data) {
63
+ ws.data = {}
64
+ }
65
+ ws.data.connectionId = connectionId
66
+ ws.data.components = new Map()
67
+ ws.data.subscriptions = new Set()
68
+ ws.data.connectedAt = new Date()
69
+
70
+ // Send connection confirmation
71
+ ws.send(JSON.stringify({
72
+ type: 'CONNECTION_ESTABLISHED',
73
+ connectionId,
74
+ timestamp: Date.now(),
75
+ features: {
76
+ compression: true,
77
+ encryption: true,
78
+ offlineQueue: true,
79
+ loadBalancing: true
80
+ }
81
+ }))
82
+ },
83
+
84
+ async message(ws, message: LiveMessage) {
85
+ try {
86
+ // Add connection metadata
87
+ message.timestamp = Date.now()
88
+
89
+ console.log(`📨 Received message:`, {
90
+ type: message.type,
91
+ componentId: message.componentId,
92
+ action: message.action,
93
+ requestId: message.requestId
94
+ })
95
+
96
+ // Handle different message types
97
+ switch (message.type) {
98
+ case 'COMPONENT_MOUNT':
99
+ await handleComponentMount(ws, message)
100
+ break
101
+ case 'COMPONENT_REHYDRATE':
102
+ await handleComponentRehydrate(ws, message)
103
+ break
104
+ case 'COMPONENT_UNMOUNT':
105
+ await handleComponentUnmount(ws, message)
106
+ break
107
+ case 'CALL_ACTION':
108
+ await handleActionCall(ws, message)
109
+ break
110
+ case 'PROPERTY_UPDATE':
111
+ await handlePropertyUpdate(ws, message)
112
+ break
113
+ case 'FILE_UPLOAD_START':
114
+ await handleFileUploadStart(ws, message as FileUploadStartMessage)
115
+ break
116
+ case 'FILE_UPLOAD_CHUNK':
117
+ await handleFileUploadChunk(ws, message as FileUploadChunkMessage)
118
+ break
119
+ case 'FILE_UPLOAD_COMPLETE':
120
+ await handleFileUploadComplete(ws, message as FileUploadCompleteMessage)
121
+ break
122
+ default:
123
+ console.warn(`❌ Unknown message type: ${message.type}`)
124
+ ws.send(JSON.stringify({
125
+ type: 'ERROR',
126
+ error: `Unknown message type: ${message.type}`,
127
+ timestamp: Date.now()
128
+ }))
129
+ }
130
+ } catch (error) {
131
+ console.error('❌ WebSocket message error:', error)
132
+ ws.send(JSON.stringify({
133
+ type: 'ERROR',
134
+ error: error instanceof Error ? error.message : 'Unknown error',
135
+ timestamp: Date.now()
136
+ }))
137
+ }
138
+ },
139
+
140
+ close(ws) {
141
+ const connectionId = ws.data?.connectionId
142
+ console.log(`🔌 Live Components WebSocket disconnected: ${connectionId}`)
143
+
144
+ // Cleanup connection in connection manager
145
+ if (connectionId) {
146
+ connectionManager.cleanupConnection(connectionId)
147
+ }
148
+
149
+ // Cleanup components for this connection
150
+ componentRegistry.cleanupConnection(ws)
151
+ }
152
+ })
153
+
154
+ // Add Live Components info routes
155
+ .get('/api/live/websocket-info', () => {
156
+ return {
157
+ success: true,
158
+ message: 'Live Components WebSocket available via Elysia',
159
+ endpoint: 'ws://localhost:3000/api/live/ws',
160
+ status: 'running',
161
+ connectionManager: connectionManager.getSystemStats()
162
+ }
163
+ })
164
+ .get('/api/live/stats', () => {
165
+ const stats = componentRegistry.getStats()
166
+ return {
167
+ success: true,
168
+ stats,
169
+ timestamp: new Date().toISOString()
170
+ }
171
+ })
172
+ .get('/api/live/health', () => {
173
+ return {
174
+ success: true,
175
+ service: 'FluxStack Live Components',
176
+ status: 'operational',
177
+ components: componentRegistry.getStats().components,
178
+ connections: connectionManager.getSystemStats(),
179
+ uptime: process.uptime(),
180
+ timestamp: new Date().toISOString()
181
+ }
182
+ })
183
+ .get('/api/live/connections', () => {
184
+ return {
185
+ success: true,
186
+ connections: connectionManager.getAllConnectionMetrics(),
187
+ systemStats: connectionManager.getSystemStats(),
188
+ timestamp: new Date().toISOString()
189
+ }
190
+ })
191
+ .get('/api/live/connections/:connectionId', ({ params }) => {
192
+ const metrics = connectionManager.getConnectionMetrics(params.connectionId)
193
+ if (!metrics) {
194
+ return {
195
+ success: false,
196
+ error: 'Connection not found'
197
+ }
198
+ }
199
+ return {
200
+ success: true,
201
+ connection: metrics,
202
+ timestamp: new Date().toISOString()
203
+ }
204
+ })
205
+ .get('/api/live/pools/:poolId/stats', ({ params }) => {
206
+ const stats = connectionManager.getPoolStats(params.poolId)
207
+ if (!stats) {
208
+ return {
209
+ success: false,
210
+ error: 'Pool not found'
211
+ }
212
+ }
213
+ return {
214
+ success: true,
215
+ pool: params.poolId,
216
+ stats,
217
+ timestamp: new Date().toISOString()
218
+ }
219
+ })
220
+ .get('/api/live/performance/dashboard', () => {
221
+ return {
222
+ success: true,
223
+ dashboard: performanceMonitor.generateDashboard(),
224
+ timestamp: new Date().toISOString()
225
+ }
226
+ })
227
+ .get('/api/live/performance/components/:componentId', ({ params }) => {
228
+ const metrics = performanceMonitor.getComponentMetrics(params.componentId)
229
+ if (!metrics) {
230
+ return {
231
+ success: false,
232
+ error: 'Component metrics not found'
233
+ }
234
+ }
235
+
236
+ const alerts = performanceMonitor.getComponentAlerts(params.componentId)
237
+ const suggestions = performanceMonitor.getComponentSuggestions(params.componentId)
238
+
239
+ return {
240
+ success: true,
241
+ component: params.componentId,
242
+ metrics,
243
+ alerts,
244
+ suggestions,
245
+ timestamp: new Date().toISOString()
246
+ }
247
+ })
248
+ .post('/api/live/performance/alerts/:alertId/resolve', ({ params }) => {
249
+ const resolved = performanceMonitor.resolveAlert(params.alertId)
250
+ return {
251
+ success: resolved,
252
+ message: resolved ? 'Alert resolved' : 'Alert not found',
253
+ timestamp: new Date().toISOString()
254
+ }
255
+ })
256
+ },
257
+
258
+ onServerStart: async (context: PluginContext) => {
259
+ context.logger.info('🔌 Live Components WebSocket ready on /api/live/ws')
260
+ }
261
+ }
262
+
263
+ // Handler functions for WebSocket messages
264
+ async function handleComponentMount(ws: any, message: LiveMessage) {
265
+ const result = await componentRegistry.handleMessage(ws, message)
266
+
267
+ if (result !== null) {
268
+ const response = {
269
+ type: 'COMPONENT_MOUNTED',
270
+ componentId: message.componentId,
271
+ success: result.success,
272
+ result: result.result,
273
+ error: result.error,
274
+ requestId: message.requestId,
275
+ timestamp: Date.now()
276
+ }
277
+ ws.send(JSON.stringify(response))
278
+ }
279
+ }
280
+
281
+ async function handleComponentRehydrate(ws: any, message: LiveMessage) {
282
+ console.log('🔄 Processing component re-hydration request:', {
283
+ componentId: message.componentId,
284
+ payload: message.payload
285
+ })
286
+
287
+ try {
288
+ const { componentName, signedState, room, userId } = message.payload || {}
289
+
290
+ if (!componentName || !signedState) {
291
+ throw new Error('Missing componentName or signedState in rehydration payload')
292
+ }
293
+
294
+ const result = await componentRegistry.rehydrateComponent(
295
+ message.componentId,
296
+ componentName,
297
+ signedState,
298
+ ws,
299
+ { room, userId }
300
+ )
301
+
302
+ const response = {
303
+ type: 'COMPONENT_REHYDRATED',
304
+ componentId: message.componentId,
305
+ success: result.success,
306
+ result: {
307
+ newComponentId: result.newComponentId,
308
+ ...result
309
+ },
310
+ error: result.error,
311
+ requestId: message.requestId,
312
+ timestamp: Date.now()
313
+ }
314
+
315
+ console.log('📤 Sending COMPONENT_REHYDRATED response:', {
316
+ type: response.type,
317
+ success: response.success,
318
+ newComponentId: response.result?.newComponentId,
319
+ requestId: response.requestId
320
+ })
321
+
322
+ ws.send(JSON.stringify(response))
323
+
324
+ } catch (error: any) {
325
+ console.error('❌ Re-hydration handler error:', error.message)
326
+
327
+ const errorResponse = {
328
+ type: 'COMPONENT_REHYDRATED',
329
+ componentId: message.componentId,
330
+ success: false,
331
+ error: error.message,
332
+ requestId: message.requestId,
333
+ timestamp: Date.now()
334
+ }
335
+
336
+ ws.send(JSON.stringify(errorResponse))
337
+ }
338
+ }
339
+
340
+ async function handleComponentUnmount(ws: any, message: LiveMessage) {
341
+ const result = await componentRegistry.handleMessage(ws, message)
342
+
343
+ if (result !== null) {
344
+ const response = {
345
+ type: 'COMPONENT_UNMOUNTED',
346
+ componentId: message.componentId,
347
+ success: result.success,
348
+ requestId: message.requestId,
349
+ timestamp: Date.now()
350
+ }
351
+ ws.send(JSON.stringify(response))
352
+ }
353
+ }
354
+
355
+ async function handleActionCall(ws: any, message: LiveMessage) {
356
+ const result = await componentRegistry.handleMessage(ws, message)
357
+
358
+ if (result !== null) {
359
+ const response = {
360
+ type: message.expectResponse ? 'ACTION_RESPONSE' : 'MESSAGE_RESPONSE',
361
+ originalType: message.type,
362
+ componentId: message.componentId,
363
+ success: result.success,
364
+ result: result.result,
365
+ error: result.error,
366
+ requestId: message.requestId,
367
+ timestamp: Date.now()
368
+ }
369
+ ws.send(JSON.stringify(response))
370
+ }
371
+ }
372
+
373
+ async function handlePropertyUpdate(ws: any, message: LiveMessage) {
374
+ const result = await componentRegistry.handleMessage(ws, message)
375
+
376
+ if (result !== null) {
377
+ const response = {
378
+ type: 'PROPERTY_UPDATED',
379
+ componentId: message.componentId,
380
+ success: result.success,
381
+ result: result.result,
382
+ error: result.error,
383
+ requestId: message.requestId,
384
+ timestamp: Date.now()
385
+ }
386
+ ws.send(JSON.stringify(response))
387
+ }
388
+ }
389
+
390
+ // File Upload Handler Functions
391
+ async function handleFileUploadStart(ws: any, message: FileUploadStartMessage) {
392
+ console.log('📤 Starting file upload:', message.uploadId)
393
+
394
+ const result = await fileUploadManager.startUpload(message)
395
+
396
+ const response = {
397
+ type: 'FILE_UPLOAD_START_RESPONSE',
398
+ componentId: message.componentId,
399
+ uploadId: message.uploadId,
400
+ success: result.success,
401
+ error: result.error,
402
+ requestId: message.requestId,
403
+ timestamp: Date.now()
404
+ }
405
+
406
+ ws.send(JSON.stringify(response))
407
+ }
408
+
409
+ async function handleFileUploadChunk(ws: any, message: FileUploadChunkMessage) {
410
+ console.log(`📦 Receiving chunk ${message.chunkIndex + 1} for upload ${message.uploadId}`)
411
+
412
+ const progressResponse = await fileUploadManager.receiveChunk(message, ws)
413
+
414
+ if (progressResponse) {
415
+ ws.send(JSON.stringify(progressResponse))
416
+ } else {
417
+ // Send error response
418
+ const errorResponse = {
419
+ type: 'FILE_UPLOAD_ERROR',
420
+ componentId: message.componentId,
421
+ uploadId: message.uploadId,
422
+ error: 'Failed to process chunk',
423
+ requestId: message.requestId,
424
+ timestamp: Date.now()
425
+ }
426
+ ws.send(JSON.stringify(errorResponse))
427
+ }
428
+ }
429
+
430
+ async function handleFileUploadComplete(ws: any, message: FileUploadCompleteMessage) {
431
+ console.log('✅ Completing file upload:', message.uploadId)
432
+
433
+ const completeResponse = await fileUploadManager.completeUpload(message)
434
+ ws.send(JSON.stringify(completeResponse))
435
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Error Handling Middleware
3
+ * Core FluxStack error handling infrastructure
4
+ */
5
+
6
+ // Express types - these should be provided by the framework user
7
+ export interface Request {
8
+ url: string
9
+ method: string
10
+ ip?: string
11
+ [key: string]: any
12
+ }
13
+
14
+ export interface Response {
15
+ status: (code: number) => Response
16
+ json: (data: any) => Response
17
+ [key: string]: any
18
+ }
19
+
20
+ export interface NextFunction {
21
+ (error?: any): void
22
+ }
23
+ import type { Logger } from '../../utils/logger/index.js'
24
+
25
+ export interface ErrorHandlingOptions {
26
+ logger?: Logger
27
+ includeStack?: boolean
28
+ customErrorHandler?: (error: Error, req: Request, res: Response) => void
29
+ }
30
+
31
+ export interface FluxStackError extends Error {
32
+ statusCode?: number
33
+ code?: string
34
+ details?: any
35
+ }
36
+
37
+ /**
38
+ * Global error handling middleware
39
+ */
40
+ export function errorHandlingMiddleware(options: ErrorHandlingOptions = {}) {
41
+ const { logger, includeStack = false, customErrorHandler } = options
42
+
43
+ return (error: FluxStackError, req: Request, res: Response, next: NextFunction) => {
44
+ // Log the error
45
+ if (logger) {
46
+ logger.error('Request error', {
47
+ error: error.message,
48
+ stack: error.stack,
49
+ url: req.url,
50
+ method: req.method,
51
+ statusCode: error.statusCode || 500
52
+ })
53
+ }
54
+
55
+ // Custom error handler
56
+ if (customErrorHandler) {
57
+ try {
58
+ customErrorHandler(error, req, res)
59
+ return
60
+ } catch (handlerError) {
61
+ if (logger) {
62
+ logger.error('Custom error handler failed', { error: handlerError })
63
+ }
64
+ }
65
+ }
66
+
67
+ // Default error response
68
+ const statusCode = error.statusCode || 500
69
+ const response: any = {
70
+ error: {
71
+ message: error.message || 'Internal Server Error',
72
+ code: error.code || 'INTERNAL_ERROR',
73
+ statusCode
74
+ }
75
+ }
76
+
77
+ // Include stack trace in development
78
+ if (includeStack && error.stack) {
79
+ response.error.stack = error.stack
80
+ }
81
+
82
+ // Include additional details if available
83
+ if (error.details) {
84
+ response.error.details = error.details
85
+ }
86
+
87
+ res.status(statusCode).json(response)
88
+ }
89
+ }
90
+
91
+ /**
92
+ * 404 Not Found middleware
93
+ */
94
+ export function notFoundMiddleware(options: { logger?: Logger } = {}) {
95
+ const { logger } = options
96
+
97
+ return (req: Request, res: Response, next: NextFunction) => {
98
+ if (logger) {
99
+ logger.warn('Route not found', {
100
+ url: req.url,
101
+ method: req.method,
102
+ ip: req.ip
103
+ })
104
+ }
105
+
106
+ res.status(404).json({
107
+ error: {
108
+ message: 'Route not found',
109
+ code: 'NOT_FOUND',
110
+ statusCode: 404,
111
+ path: req.url,
112
+ method: req.method
113
+ }
114
+ })
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Create a FluxStack error
120
+ */
121
+ export function createError(
122
+ message: string,
123
+ statusCode: number = 500,
124
+ code?: string,
125
+ details?: any
126
+ ): FluxStackError {
127
+ const error = new Error(message) as FluxStackError
128
+ error.statusCode = statusCode
129
+ error.code = code
130
+ error.details = details
131
+ return error
132
+ }
133
+
134
+ /**
135
+ * Async error wrapper
136
+ */
137
+ export function asyncHandler(fn: Function) {
138
+ return (req: Request, res: Response, next: NextFunction) => {
139
+ Promise.resolve(fn(req, res, next)).catch(next)
140
+ }
141
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Core Server Middleware
3
+ * FluxStack middleware infrastructure exports
4
+ */
5
+
6
+ export {
7
+ errorHandlingMiddleware,
8
+ notFoundMiddleware,
9
+ createError,
10
+ asyncHandler
11
+ } from './errorHandling.js'
12
+
13
+ export type {
14
+ ErrorHandlingOptions,
15
+ FluxStackError
16
+ } from './errorHandling.js'