create-fluxstack 1.9.1 → 1.12.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 (259) hide show
  1. package/.dockerignore +1 -2
  2. package/Dockerfile +8 -8
  3. package/LIVE_COMPONENTS_REVIEW.md +781 -0
  4. package/LLMD/INDEX.md +64 -0
  5. package/LLMD/MAINTENANCE.md +197 -0
  6. package/LLMD/MIGRATION.md +156 -0
  7. package/LLMD/config/.gitkeep +1 -0
  8. package/LLMD/config/declarative-system.md +268 -0
  9. package/LLMD/config/environment-vars.md +327 -0
  10. package/LLMD/config/runtime-reload.md +401 -0
  11. package/LLMD/core/.gitkeep +1 -0
  12. package/LLMD/core/build-system.md +599 -0
  13. package/LLMD/core/framework-lifecycle.md +229 -0
  14. package/LLMD/core/plugin-system.md +451 -0
  15. package/LLMD/patterns/.gitkeep +1 -0
  16. package/LLMD/patterns/anti-patterns.md +297 -0
  17. package/LLMD/patterns/project-structure.md +264 -0
  18. package/LLMD/patterns/type-safety.md +440 -0
  19. package/LLMD/reference/.gitkeep +1 -0
  20. package/LLMD/reference/cli-commands.md +250 -0
  21. package/LLMD/reference/plugin-hooks.md +357 -0
  22. package/LLMD/reference/routing.md +39 -0
  23. package/LLMD/reference/troubleshooting.md +364 -0
  24. package/LLMD/resources/.gitkeep +1 -0
  25. package/LLMD/resources/controllers.md +465 -0
  26. package/LLMD/resources/live-components.md +703 -0
  27. package/LLMD/resources/live-rooms.md +482 -0
  28. package/LLMD/resources/live-upload.md +130 -0
  29. package/LLMD/resources/plugins-external.md +617 -0
  30. package/LLMD/resources/routes-eden.md +254 -0
  31. package/README.md +37 -17
  32. package/app/client/index.html +0 -1
  33. package/app/client/src/App.tsx +109 -156
  34. package/app/client/src/components/AppLayout.tsx +68 -0
  35. package/app/client/src/components/BackButton.tsx +13 -0
  36. package/app/client/src/components/DemoPage.tsx +20 -0
  37. package/app/client/src/components/LiveUploadWidget.tsx +204 -0
  38. package/app/client/src/lib/eden-api.ts +85 -65
  39. package/app/client/src/live/ChatDemo.tsx +107 -0
  40. package/app/client/src/live/CounterDemo.tsx +206 -0
  41. package/app/client/src/live/FormDemo.tsx +119 -0
  42. package/app/client/src/live/RoomChatDemo.tsx +242 -0
  43. package/app/client/src/live/UploadDemo.tsx +21 -0
  44. package/app/client/src/main.tsx +13 -10
  45. package/app/client/src/pages/ApiTestPage.tsx +108 -0
  46. package/app/client/src/pages/HomePage.tsx +76 -0
  47. package/app/client/src/vite-env.d.ts +1 -1
  48. package/app/server/app.ts +1 -4
  49. package/app/server/controllers/users.controller.ts +36 -44
  50. package/app/server/index.ts +24 -107
  51. package/app/server/live/LiveChat.ts +77 -0
  52. package/app/server/live/LiveCounter.ts +67 -0
  53. package/app/server/live/LiveForm.ts +63 -0
  54. package/app/server/live/LiveLocalCounter.ts +32 -0
  55. package/app/server/live/LiveRoomChat.ts +285 -0
  56. package/app/server/live/LiveUpload.ts +81 -0
  57. package/app/server/live/register-components.ts +19 -19
  58. package/app/server/routes/index.ts +3 -1
  59. package/app/server/routes/room.routes.ts +117 -0
  60. package/app/server/routes/users.routes.ts +35 -27
  61. package/app/shared/types/index.ts +14 -2
  62. package/config/app.config.ts +2 -62
  63. package/config/client.config.ts +2 -95
  64. package/config/database.config.ts +2 -99
  65. package/config/fluxstack.config.ts +25 -45
  66. package/config/index.ts +57 -38
  67. package/config/monitoring.config.ts +2 -114
  68. package/config/plugins.config.ts +2 -80
  69. package/config/server.config.ts +2 -68
  70. package/config/services.config.ts +2 -130
  71. package/config/system/app.config.ts +29 -0
  72. package/config/system/build.config.ts +49 -0
  73. package/config/system/client.config.ts +68 -0
  74. package/config/system/database.config.ts +17 -0
  75. package/config/system/fluxstack.config.ts +114 -0
  76. package/config/{logger.config.ts → system/logger.config.ts} +3 -1
  77. package/config/system/monitoring.config.ts +114 -0
  78. package/config/system/plugins.config.ts +84 -0
  79. package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
  80. package/config/system/server.config.ts +68 -0
  81. package/config/system/services.config.ts +46 -0
  82. package/config/{system.config.ts → system/system.config.ts} +1 -1
  83. package/core/build/bundler.ts +4 -1
  84. package/core/build/flux-plugins-generator.ts +325 -325
  85. package/core/build/index.ts +159 -27
  86. package/core/build/live-components-generator.ts +70 -3
  87. package/core/build/optimizer.ts +235 -235
  88. package/core/cli/command-registry.ts +6 -4
  89. package/core/cli/commands/build.ts +79 -0
  90. package/core/cli/commands/create.ts +54 -0
  91. package/core/cli/commands/dev.ts +101 -0
  92. package/core/cli/commands/help.ts +34 -0
  93. package/core/cli/commands/index.ts +34 -0
  94. package/core/cli/commands/make-plugin.ts +90 -0
  95. package/core/cli/commands/plugin-add.ts +197 -0
  96. package/core/cli/commands/plugin-deps.ts +2 -2
  97. package/core/cli/commands/plugin-list.ts +208 -0
  98. package/core/cli/commands/plugin-remove.ts +170 -0
  99. package/core/cli/generators/component.ts +769 -769
  100. package/core/cli/generators/controller.ts +1 -1
  101. package/core/cli/generators/index.ts +146 -146
  102. package/core/cli/generators/interactive.ts +227 -227
  103. package/core/cli/generators/plugin.ts +2 -2
  104. package/core/cli/generators/prompts.ts +82 -82
  105. package/core/cli/generators/route.ts +6 -6
  106. package/core/cli/generators/service.ts +2 -2
  107. package/core/cli/generators/template-engine.ts +4 -3
  108. package/core/cli/generators/types.ts +2 -2
  109. package/core/cli/generators/utils.ts +191 -191
  110. package/core/cli/index.ts +115 -558
  111. package/core/cli/plugin-discovery.ts +2 -2
  112. package/core/client/LiveComponentsProvider.tsx +63 -17
  113. package/core/client/api/eden.ts +183 -0
  114. package/core/client/api/index.ts +11 -0
  115. package/core/client/components/Live.tsx +104 -0
  116. package/core/client/fluxstack.ts +1 -9
  117. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -0
  118. package/core/client/hooks/state-validator.ts +1 -1
  119. package/core/client/hooks/useAuth.ts +48 -48
  120. package/core/client/hooks/useChunkedUpload.ts +170 -69
  121. package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
  122. package/core/client/hooks/useLiveComponent.ts +800 -0
  123. package/core/client/hooks/useLiveUpload.ts +71 -0
  124. package/core/client/hooks/useRoom.ts +409 -0
  125. package/core/client/hooks/useRoomProxy.ts +382 -0
  126. package/core/client/index.ts +18 -51
  127. package/core/client/standalone-entry.ts +8 -0
  128. package/core/client/standalone.ts +74 -53
  129. package/core/client/state/createStore.ts +192 -192
  130. package/core/client/state/index.ts +14 -14
  131. package/core/config/index.ts +70 -291
  132. package/core/config/schema.ts +42 -723
  133. package/core/framework/client.ts +131 -131
  134. package/core/framework/index.ts +7 -7
  135. package/core/framework/server.ts +227 -47
  136. package/core/framework/types.ts +2 -2
  137. package/core/index.ts +23 -4
  138. package/core/live/ComponentRegistry.ts +7 -3
  139. package/core/live/types.ts +77 -0
  140. package/core/plugins/built-in/index.ts +134 -131
  141. package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1074
  142. package/core/plugins/built-in/live-components/index.ts +1 -1
  143. package/core/plugins/built-in/monitoring/index.ts +111 -47
  144. package/core/plugins/built-in/static/index.ts +1 -1
  145. package/core/plugins/built-in/swagger/index.ts +68 -265
  146. package/core/plugins/built-in/vite/index.ts +94 -306
  147. package/core/plugins/built-in/vite/vite-dev.ts +82 -0
  148. package/core/plugins/config.ts +9 -7
  149. package/core/plugins/dependency-manager.ts +31 -1
  150. package/core/plugins/discovery.ts +19 -7
  151. package/core/plugins/executor.ts +2 -2
  152. package/core/plugins/index.ts +203 -203
  153. package/core/plugins/manager.ts +27 -39
  154. package/core/plugins/module-resolver.ts +19 -8
  155. package/core/plugins/registry.ts +309 -21
  156. package/core/plugins/types.ts +106 -55
  157. package/core/server/framework.ts +66 -43
  158. package/core/server/index.ts +15 -16
  159. package/core/server/live/ComponentRegistry.ts +91 -75
  160. package/core/server/live/FileUploadManager.ts +41 -31
  161. package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
  162. package/core/server/live/LiveRoomManager.ts +261 -0
  163. package/core/server/live/RoomEventBus.ts +234 -0
  164. package/core/server/live/RoomStateManager.ts +172 -0
  165. package/core/server/live/StateSignature.ts +643 -643
  166. package/core/server/live/WebSocketConnectionManager.ts +30 -19
  167. package/core/server/live/auto-generated-components.ts +41 -26
  168. package/core/server/live/index.ts +14 -0
  169. package/core/server/live/websocket-plugin.ts +233 -72
  170. package/core/server/middleware/elysia-helpers.ts +7 -2
  171. package/core/server/middleware/errorHandling.ts +1 -1
  172. package/core/server/middleware/index.ts +31 -31
  173. package/core/server/plugins/database.ts +180 -180
  174. package/core/server/plugins/static-files-plugin.ts +69 -260
  175. package/core/server/plugins/swagger.ts +33 -33
  176. package/core/server/rooms/RoomBroadcaster.ts +357 -0
  177. package/core/server/rooms/RoomSystem.ts +463 -0
  178. package/core/server/rooms/index.ts +13 -0
  179. package/core/server/services/BaseService.ts +1 -1
  180. package/core/server/services/ServiceContainer.ts +1 -1
  181. package/core/server/services/index.ts +8 -8
  182. package/core/templates/create-project.ts +12 -12
  183. package/core/testing/index.ts +9 -9
  184. package/core/testing/setup.ts +73 -73
  185. package/core/types/api.ts +168 -168
  186. package/core/types/build.ts +219 -218
  187. package/core/types/config.ts +56 -26
  188. package/core/types/index.ts +4 -4
  189. package/core/types/plugin.ts +107 -99
  190. package/core/types/types.ts +490 -14
  191. package/core/utils/build-logger.ts +324 -324
  192. package/core/utils/config-schema.ts +480 -480
  193. package/core/utils/env.ts +2 -8
  194. package/core/utils/errors/codes.ts +114 -114
  195. package/core/utils/errors/handlers.ts +36 -1
  196. package/core/utils/errors/index.ts +49 -5
  197. package/core/utils/errors/middleware.ts +113 -113
  198. package/core/utils/helpers.ts +6 -16
  199. package/core/utils/index.ts +17 -17
  200. package/core/utils/logger/colors.ts +114 -114
  201. package/core/utils/logger/config.ts +13 -9
  202. package/core/utils/logger/formatter.ts +82 -82
  203. package/core/utils/logger/group-logger.ts +101 -101
  204. package/core/utils/logger/index.ts +6 -1
  205. package/core/utils/logger/stack-trace.ts +3 -1
  206. package/core/utils/logger/startup-banner.ts +82 -66
  207. package/core/utils/logger/winston-logger.ts +152 -152
  208. package/core/utils/monitoring/index.ts +211 -211
  209. package/core/utils/sync-version.ts +66 -66
  210. package/core/utils/version.ts +1 -1
  211. package/create-fluxstack.ts +8 -7
  212. package/eslint.config.js +23 -23
  213. package/package.json +14 -15
  214. package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
  215. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  216. package/plugins/crypto-auth/client/components/index.ts +11 -11
  217. package/plugins/crypto-auth/client/index.ts +11 -11
  218. package/plugins/crypto-auth/config/index.ts +1 -1
  219. package/plugins/crypto-auth/index.ts +4 -4
  220. package/plugins/crypto-auth/package.json +65 -65
  221. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  222. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  223. package/plugins/crypto-auth/server/index.ts +21 -21
  224. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
  225. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
  226. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
  227. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
  228. package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
  229. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  230. package/plugins/crypto-auth/server/middlewares.ts +19 -19
  231. package/tsconfig.api-strict.json +16 -0
  232. package/tsconfig.json +10 -14
  233. package/{app/client/tsconfig.node.json → tsconfig.node.json} +1 -1
  234. package/types/global.d.ts +29 -29
  235. package/types/vitest.d.ts +8 -8
  236. package/vite.config.ts +38 -62
  237. package/vitest.config.live.ts +10 -9
  238. package/vitest.config.ts +29 -17
  239. package/workspace.json +5 -5
  240. package/app/client/README.md +0 -69
  241. package/app/client/SIMPLIFICATION.md +0 -140
  242. package/app/client/frontend-only.ts +0 -12
  243. package/app/client/tsconfig.app.json +0 -44
  244. package/app/client/tsconfig.json +0 -7
  245. package/app/client/zustand-setup.md +0 -65
  246. package/app/server/backend-only.ts +0 -18
  247. package/app/server/live/LiveClockComponent.ts +0 -215
  248. package/app/server/routes/env-test.ts +0 -110
  249. package/core/client/hooks/index.ts +0 -7
  250. package/core/client/hooks/useHybridLiveComponent.ts +0 -631
  251. package/core/client/hooks/useWebSocket.ts +0 -373
  252. package/core/config/env.ts +0 -546
  253. package/core/config/loader.ts +0 -522
  254. package/core/config/runtime-config.ts +0 -327
  255. package/core/config/validator.ts +0 -540
  256. package/core/server/backend-entry.ts +0 -51
  257. package/core/server/standalone.ts +0 -106
  258. package/core/utils/regenerate-files.ts +0 -69
  259. package/fluxstack.config.ts +0 -354
package/core/utils/env.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @example
11
11
  * ```ts
12
- * import { env } from '@/core/utils/env'
12
+ * import { env } from '@core/utils/env'
13
13
  *
14
14
  * const port = env.PORT // number (3000)
15
15
  * const debug = env.DEBUG // boolean (false)
@@ -51,13 +51,7 @@ class EnvLoader {
51
51
  return global['process']['env']
52
52
  }
53
53
 
54
- // Last resort: eval to bypass static analysis
55
- try {
56
- const proc = eval('typeof process !== "undefined" ? process : null')
57
- return proc?.env || {}
58
- } catch {
59
- return {}
60
- }
54
+ return {}
61
55
  }
62
56
  }
63
57
 
@@ -1,115 +1,115 @@
1
- export const ERROR_CODES = {
2
- // Validation errors (400)
3
- VALIDATION_ERROR: 'VALIDATION_ERROR',
4
- INVALID_INPUT: 'INVALID_INPUT',
5
- MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
6
- INVALID_FORMAT: 'INVALID_FORMAT',
7
-
8
- // Authentication errors (401)
9
- UNAUTHORIZED: 'UNAUTHORIZED',
10
- INVALID_TOKEN: 'INVALID_TOKEN',
11
- TOKEN_EXPIRED: 'TOKEN_EXPIRED',
12
- INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
13
-
14
- // Authorization errors (403)
15
- FORBIDDEN: 'FORBIDDEN',
16
- INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
17
- ACCESS_DENIED: 'ACCESS_DENIED',
18
-
19
- // Not found errors (404)
20
- NOT_FOUND: 'NOT_FOUND',
21
- RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
22
- ENDPOINT_NOT_FOUND: 'ENDPOINT_NOT_FOUND',
23
-
24
- // Conflict errors (409)
25
- CONFLICT: 'CONFLICT',
26
- RESOURCE_ALREADY_EXISTS: 'RESOURCE_ALREADY_EXISTS',
27
- DUPLICATE_ENTRY: 'DUPLICATE_ENTRY',
28
-
29
- // Server errors (500)
30
- INTERNAL_ERROR: 'INTERNAL_ERROR',
31
- INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
32
- DATABASE_ERROR: 'DATABASE_ERROR',
33
- EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',
34
-
35
- // Service unavailable (503)
36
- SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
37
- MAINTENANCE_MODE: 'MAINTENANCE_MODE',
38
- RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
39
-
40
- // Plugin errors
41
- PLUGIN_ERROR: 'PLUGIN_ERROR',
42
- PLUGIN_NOT_FOUND: 'PLUGIN_NOT_FOUND',
43
- PLUGIN_INITIALIZATION_ERROR: 'PLUGIN_INITIALIZATION_ERROR',
44
-
45
- // Configuration errors
46
- CONFIG_ERROR: 'CONFIG_ERROR',
47
- INVALID_CONFIG: 'INVALID_CONFIG',
48
- MISSING_CONFIG: 'MISSING_CONFIG',
49
-
50
- // Build errors
51
- BUILD_ERROR: 'BUILD_ERROR',
52
- COMPILATION_ERROR: 'COMPILATION_ERROR',
53
- BUNDLING_ERROR: 'BUNDLING_ERROR'
54
- } as const
55
-
56
- export type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES]
57
-
58
- export const getErrorMessage = (code: ErrorCode): string => {
59
- const messages: Record<ErrorCode, string> = {
60
- // Validation errors
61
- VALIDATION_ERROR: 'Validation failed',
62
- INVALID_INPUT: 'Invalid input provided',
63
- MISSING_REQUIRED_FIELD: 'Required field is missing',
64
- INVALID_FORMAT: 'Invalid format',
65
-
66
- // Authentication errors
67
- UNAUTHORIZED: 'Authentication required',
68
- INVALID_TOKEN: 'Invalid authentication token',
69
- TOKEN_EXPIRED: 'Authentication token has expired',
70
- INVALID_CREDENTIALS: 'Invalid credentials provided',
71
-
72
- // Authorization errors
73
- FORBIDDEN: 'Access forbidden',
74
- INSUFFICIENT_PERMISSIONS: 'Insufficient permissions',
75
- ACCESS_DENIED: 'Access denied',
76
-
77
- // Not found errors
78
- NOT_FOUND: 'Resource not found',
79
- RESOURCE_NOT_FOUND: 'Requested resource not found',
80
- ENDPOINT_NOT_FOUND: 'API endpoint not found',
81
-
82
- // Conflict errors
83
- CONFLICT: 'Resource conflict',
84
- RESOURCE_ALREADY_EXISTS: 'Resource already exists',
85
- DUPLICATE_ENTRY: 'Duplicate entry',
86
-
87
- // Server errors
88
- INTERNAL_ERROR: 'Internal server error',
89
- INTERNAL_SERVER_ERROR: 'Internal server error',
90
- DATABASE_ERROR: 'Database operation failed',
91
- EXTERNAL_SERVICE_ERROR: 'External service error',
92
-
93
- // Service unavailable
94
- SERVICE_UNAVAILABLE: 'Service temporarily unavailable',
95
- MAINTENANCE_MODE: 'Service is under maintenance',
96
- RATE_LIMIT_EXCEEDED: 'Rate limit exceeded',
97
-
98
- // Plugin errors
99
- PLUGIN_ERROR: 'Plugin error',
100
- PLUGIN_NOT_FOUND: 'Plugin not found',
101
- PLUGIN_INITIALIZATION_ERROR: 'Plugin initialization failed',
102
-
103
- // Configuration errors
104
- CONFIG_ERROR: 'Configuration error',
105
- INVALID_CONFIG: 'Invalid configuration',
106
- MISSING_CONFIG: 'Missing configuration',
107
-
108
- // Build errors
109
- BUILD_ERROR: 'Build error',
110
- COMPILATION_ERROR: 'Compilation failed',
111
- BUNDLING_ERROR: 'Bundling failed'
112
- }
113
-
114
- return messages[code] || 'Unknown error'
1
+ export const ERROR_CODES = {
2
+ // Validation errors (400)
3
+ VALIDATION_ERROR: 'VALIDATION_ERROR',
4
+ INVALID_INPUT: 'INVALID_INPUT',
5
+ MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
6
+ INVALID_FORMAT: 'INVALID_FORMAT',
7
+
8
+ // Authentication errors (401)
9
+ UNAUTHORIZED: 'UNAUTHORIZED',
10
+ INVALID_TOKEN: 'INVALID_TOKEN',
11
+ TOKEN_EXPIRED: 'TOKEN_EXPIRED',
12
+ INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
13
+
14
+ // Authorization errors (403)
15
+ FORBIDDEN: 'FORBIDDEN',
16
+ INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
17
+ ACCESS_DENIED: 'ACCESS_DENIED',
18
+
19
+ // Not found errors (404)
20
+ NOT_FOUND: 'NOT_FOUND',
21
+ RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
22
+ ENDPOINT_NOT_FOUND: 'ENDPOINT_NOT_FOUND',
23
+
24
+ // Conflict errors (409)
25
+ CONFLICT: 'CONFLICT',
26
+ RESOURCE_ALREADY_EXISTS: 'RESOURCE_ALREADY_EXISTS',
27
+ DUPLICATE_ENTRY: 'DUPLICATE_ENTRY',
28
+
29
+ // Server errors (500)
30
+ INTERNAL_ERROR: 'INTERNAL_ERROR',
31
+ INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
32
+ DATABASE_ERROR: 'DATABASE_ERROR',
33
+ EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',
34
+
35
+ // Service unavailable (503)
36
+ SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
37
+ MAINTENANCE_MODE: 'MAINTENANCE_MODE',
38
+ RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
39
+
40
+ // Plugin errors
41
+ PLUGIN_ERROR: 'PLUGIN_ERROR',
42
+ PLUGIN_NOT_FOUND: 'PLUGIN_NOT_FOUND',
43
+ PLUGIN_INITIALIZATION_ERROR: 'PLUGIN_INITIALIZATION_ERROR',
44
+
45
+ // Configuration errors
46
+ CONFIG_ERROR: 'CONFIG_ERROR',
47
+ INVALID_CONFIG: 'INVALID_CONFIG',
48
+ MISSING_CONFIG: 'MISSING_CONFIG',
49
+
50
+ // Build errors
51
+ BUILD_ERROR: 'BUILD_ERROR',
52
+ COMPILATION_ERROR: 'COMPILATION_ERROR',
53
+ BUNDLING_ERROR: 'BUNDLING_ERROR'
54
+ } as const
55
+
56
+ export type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES]
57
+
58
+ export const getErrorMessage = (code: ErrorCode): string => {
59
+ const messages: Record<ErrorCode, string> = {
60
+ // Validation errors
61
+ VALIDATION_ERROR: 'Validation failed',
62
+ INVALID_INPUT: 'Invalid input provided',
63
+ MISSING_REQUIRED_FIELD: 'Required field is missing',
64
+ INVALID_FORMAT: 'Invalid format',
65
+
66
+ // Authentication errors
67
+ UNAUTHORIZED: 'Authentication required',
68
+ INVALID_TOKEN: 'Invalid authentication token',
69
+ TOKEN_EXPIRED: 'Authentication token has expired',
70
+ INVALID_CREDENTIALS: 'Invalid credentials provided',
71
+
72
+ // Authorization errors
73
+ FORBIDDEN: 'Access forbidden',
74
+ INSUFFICIENT_PERMISSIONS: 'Insufficient permissions',
75
+ ACCESS_DENIED: 'Access denied',
76
+
77
+ // Not found errors
78
+ NOT_FOUND: 'Resource not found',
79
+ RESOURCE_NOT_FOUND: 'Requested resource not found',
80
+ ENDPOINT_NOT_FOUND: 'API endpoint not found',
81
+
82
+ // Conflict errors
83
+ CONFLICT: 'Resource conflict',
84
+ RESOURCE_ALREADY_EXISTS: 'Resource already exists',
85
+ DUPLICATE_ENTRY: 'Duplicate entry',
86
+
87
+ // Server errors
88
+ INTERNAL_ERROR: 'Internal server error',
89
+ INTERNAL_SERVER_ERROR: 'Internal server error',
90
+ DATABASE_ERROR: 'Database operation failed',
91
+ EXTERNAL_SERVICE_ERROR: 'External service error',
92
+
93
+ // Service unavailable
94
+ SERVICE_UNAVAILABLE: 'Service temporarily unavailable',
95
+ MAINTENANCE_MODE: 'Service is under maintenance',
96
+ RATE_LIMIT_EXCEEDED: 'Rate limit exceeded',
97
+
98
+ // Plugin errors
99
+ PLUGIN_ERROR: 'Plugin error',
100
+ PLUGIN_NOT_FOUND: 'Plugin not found',
101
+ PLUGIN_INITIALIZATION_ERROR: 'Plugin initialization failed',
102
+
103
+ // Configuration errors
104
+ CONFIG_ERROR: 'Configuration error',
105
+ INVALID_CONFIG: 'Invalid configuration',
106
+ MISSING_CONFIG: 'Missing configuration',
107
+
108
+ // Build errors
109
+ BUILD_ERROR: 'Build error',
110
+ COMPILATION_ERROR: 'Compilation failed',
111
+ BUNDLING_ERROR: 'Bundling failed'
112
+ }
113
+
114
+ return messages[code] || 'Unknown error'
115
115
  }
@@ -120,13 +120,17 @@ export class EnhancedErrorHandler {
120
120
 
121
121
  private logError(error: FluxStackError, logger: Logger, isDevelopment: boolean): void {
122
122
  const logLevel = this.getLogLevel(error)
123
+
124
+ // Format stack trace properly (handles CallSite objects from Bun)
125
+ const formattedStack = isDevelopment ? this.formatErrorStack(error.stack) : undefined
126
+
123
127
  const logData = {
124
128
  code: error.code,
125
129
  statusCode: error.statusCode,
126
130
  context: error.context,
127
131
  metadata: error.metadata,
128
132
  isOperational: error.isOperational,
129
- ...(isDevelopment && { stack: error.stack })
133
+ ...(formattedStack && { stack: formattedStack })
130
134
  }
131
135
 
132
136
  // Skip logging for certain errors to reduce noise
@@ -137,6 +141,37 @@ export class EnhancedErrorHandler {
137
141
  logger[logLevel](error.message, logData)
138
142
  }
139
143
 
144
+ /**
145
+ * Format stack trace to readable string (handles Bun CallSite objects)
146
+ */
147
+ private formatErrorStack(stack: any): string | undefined {
148
+ if (!stack) return undefined
149
+
150
+ // If stack is already a string, return it
151
+ if (typeof stack === 'string') return stack
152
+
153
+ // If stack is an array of CallSite objects (Bun), format them
154
+ if (Array.isArray(stack)) {
155
+ return stack
156
+ .map((site: any, index: number) => {
157
+ try {
158
+ const fileName = site.getFileName?.() || 'unknown'
159
+ const lineNumber = site.getLineNumber?.() || 0
160
+ const columnNumber = site.getColumnNumber?.() || 0
161
+ const functionName = site.getFunctionName?.() || 'anonymous'
162
+
163
+ return ` at ${functionName} (${fileName}:${lineNumber}:${columnNumber})`
164
+ } catch {
165
+ return ` at ${String(site)}`
166
+ }
167
+ })
168
+ .join('\n')
169
+ }
170
+
171
+ // Fallback: convert to string
172
+ return String(stack)
173
+ }
174
+
140
175
  private getLogLevel(error: FluxStackError): 'error' | 'warn' | 'info' {
141
176
  if (!error.isOperational) {
142
177
  return 'error'
@@ -46,13 +46,45 @@ export class FluxStackError extends Error {
46
46
  this.metadata = metadata
47
47
  this.isOperational = isOperational
48
48
  this.userMessage = userMessage
49
-
49
+
50
50
  // Maintain proper stack trace
51
51
  if (Error.captureStackTrace) {
52
52
  Error.captureStackTrace(this, FluxStackError)
53
53
  }
54
54
  }
55
55
 
56
+ /**
57
+ * Format stack trace to string (handles both string and CallSite array)
58
+ */
59
+ private formatStack(): string | undefined {
60
+ if (!this.stack) return undefined
61
+
62
+ // If stack is already a string, return it
63
+ if (typeof this.stack === 'string') return this.stack
64
+
65
+ // If stack is an array of CallSite objects (Bun), format them
66
+ const stackValue = this.stack as unknown
67
+ if (Array.isArray(stackValue)) {
68
+ return stackValue
69
+ .map((site: any) => {
70
+ try {
71
+ const fileName = site.getFileName?.() || 'unknown'
72
+ const lineNumber = site.getLineNumber?.() || 0
73
+ const columnNumber = site.getColumnNumber?.() || 0
74
+ const functionName = site.getFunctionName?.() || 'anonymous'
75
+
76
+ return ` at ${functionName} (${fileName}:${lineNumber}:${columnNumber})`
77
+ } catch {
78
+ return ` at ${String(site)}`
79
+ }
80
+ })
81
+ .join('\n')
82
+ }
83
+
84
+ // Fallback: convert to string
85
+ return String(this.stack)
86
+ }
87
+
56
88
  toJSON() {
57
89
  return {
58
90
  name: this.name,
@@ -64,7 +96,7 @@ export class FluxStackError extends Error {
64
96
  metadata: this.metadata,
65
97
  isOperational: this.isOperational,
66
98
  userMessage: this.userMessage,
67
- stack: this.stack
99
+ stack: this.formatStack()
68
100
  }
69
101
  }
70
102
 
@@ -77,7 +109,7 @@ export class FluxStackError extends Error {
77
109
  ...(this.context && { details: this.context }),
78
110
  timestamp: this.timestamp.toISOString(),
79
111
  ...(this.metadata.correlationId && { correlationId: this.metadata.correlationId }),
80
- ...(isDevelopment && { stack: this.stack })
112
+ ...(isDevelopment && { stack: this.formatStack() })
81
113
  }
82
114
  }
83
115
  }
@@ -583,9 +615,21 @@ export const wrapError = (error: Error, metadata?: ErrorMetadata): FluxStackErro
583
615
  if (isFluxStackError(error)) {
584
616
  return metadata ? error.withMetadata(metadata) : error
585
617
  }
586
-
618
+
619
+ // Detect Elysia validation errors (thrown by TypeBox schema validation)
620
+ const errorAny = error as any
621
+ if (
622
+ error.constructor?.name === 'ValidationError' ||
623
+ error.constructor?.name === 'TransformDecodeError' ||
624
+ (typeof errorAny.status === 'number' && errorAny.status >= 400 && errorAny.status < 500)
625
+ ) {
626
+ const status = errorAny.status ?? 422
627
+ const message = error.message || 'Validation failed'
628
+ return new ValidationError(message, { originalError: error.name, status }, metadata)
629
+ }
630
+
587
631
  return new InternalServerError(error.message, { originalError: error.name }, metadata)
588
632
  }
589
633
 
590
634
  // Re-export error codes for convenience
591
- export { ERROR_CODES, type ErrorCode, getErrorMessage } from './codes'
635
+ export { ERROR_CODES, type ErrorCode, getErrorMessage } from './codes'
@@ -1,114 +1,114 @@
1
- import { Elysia } from 'elysia'
2
- import { EnhancedErrorHandler, type ErrorHandlerContext, type ErrorHandlerOptions, type ErrorMetricsCollector } from './handlers'
3
- import type { Logger } from '../logger/index'
4
-
5
- export interface ErrorMiddlewareOptions extends ErrorHandlerOptions {
6
- logger?: Logger
7
- isDevelopment?: boolean
8
- enableRequestContext?: boolean
9
- metricsCollector?: ErrorMetricsCollector
10
- }
11
-
12
- export const errorMiddleware = (options: ErrorMiddlewareOptions = {}) => {
13
- const handler = new EnhancedErrorHandler(options)
14
-
15
- return new Elysia({ name: 'error-handler' })
16
- .onError(async ({ error, request, path, set }) => {
17
- // Extract request context
18
- const context: ErrorHandlerContext = {
19
- logger: options.logger || console as any, // Fallback to console if no logger provided
20
- isDevelopment: options.isDevelopment ?? process.env.NODE_ENV === 'development',
21
- request,
22
- path,
23
- method: request.method,
24
- correlationId: request.headers.get('x-correlation-id') || undefined,
25
- userId: request.headers.get('x-user-id') || undefined,
26
- userAgent: request.headers.get('user-agent') || undefined,
27
- ip: request.headers.get('x-forwarded-for') ||
28
- request.headers.get('x-real-ip') ||
29
- 'unknown',
30
- metricsCollector: options.metricsCollector
31
- }
32
-
33
- try {
34
- // Convert Elysia error to standard Error if needed
35
- const standardError = error instanceof Error ? error : new Error(String(error))
36
- const errorResponse = await handler.handle(standardError, context)
37
-
38
- // Set response status code
39
- set.status = errorResponse.error.statusCode
40
-
41
- // Set correlation ID header if available
42
- if (errorResponse.error.correlationId) {
43
- set.headers['x-correlation-id'] = errorResponse.error.correlationId
44
- }
45
-
46
- return errorResponse
47
- } catch (handlerError) {
48
- // Fallback error handling if the error handler itself fails
49
- const fallbackLogger = options.logger || console as any
50
- fallbackLogger.error('Error handler failed', {
51
- originalError: error instanceof Error ? error.message : String(error),
52
- handlerError: handlerError instanceof Error ? handlerError.message : handlerError
53
- })
54
-
55
- set.status = 500
56
- return {
57
- error: {
58
- message: 'Internal server error',
59
- code: 'INTERNAL_ERROR',
60
- statusCode: 500,
61
- timestamp: new Date().toISOString()
62
- }
63
- }
64
- }
65
- })
66
- }
67
-
68
- // Correlation ID middleware to add correlation IDs to requests
69
- export const correlationIdMiddleware = () => {
70
- return new Elysia({ name: 'correlation-id' })
71
- .onRequest(({ request, set }) => {
72
- // Check if correlation ID already exists in headers
73
- let correlationId = request.headers.get('x-correlation-id')
74
-
75
- // Generate new correlation ID if not present
76
- if (!correlationId) {
77
- correlationId = crypto.randomUUID()
78
- }
79
-
80
- // Add correlation ID to response headers
81
- set.headers['x-correlation-id'] = correlationId
82
-
83
- // Store correlation ID in request context for later use
84
- // Note: This would typically be stored in a request-scoped context
85
- // For now, we'll rely on the error handler to extract it from headers
86
- })
87
- }
88
-
89
- // Request context middleware to extract and store request information
90
- export const requestContextMiddleware = () => {
91
- return new Elysia({ name: 'request-context' })
92
- .onRequest(({ request, set }) => {
93
- // Extract useful request information and store in headers for error handling
94
- const userAgent = request.headers.get('user-agent')
95
- const ip = request.headers.get('x-forwarded-for') ||
96
- request.headers.get('x-real-ip') ||
97
- 'unknown'
98
-
99
- // Store in custom headers for error handler access
100
- // In a real implementation, this would use request-scoped storage
101
- if (userAgent) {
102
- set.headers['x-internal-user-agent'] = userAgent
103
- }
104
- set.headers['x-internal-ip'] = ip
105
- })
106
- }
107
-
108
- // Combined error handling middleware with all features
109
- export const fullErrorHandlingMiddleware = (options: ErrorMiddlewareOptions = {}) => {
110
- return new Elysia({ name: 'full-error-handling' })
111
- .use(correlationIdMiddleware())
112
- .use(requestContextMiddleware())
113
- .use(errorMiddleware(options))
1
+ import { Elysia } from 'elysia'
2
+ import { EnhancedErrorHandler, type ErrorHandlerContext, type ErrorHandlerOptions, type ErrorMetricsCollector } from './handlers'
3
+ import type { Logger } from '../logger/index'
4
+
5
+ export interface ErrorMiddlewareOptions extends ErrorHandlerOptions {
6
+ logger?: Logger
7
+ isDevelopment?: boolean
8
+ enableRequestContext?: boolean
9
+ metricsCollector?: ErrorMetricsCollector
10
+ }
11
+
12
+ export const errorMiddleware = (options: ErrorMiddlewareOptions = {}) => {
13
+ const handler = new EnhancedErrorHandler(options)
14
+
15
+ return new Elysia({ name: 'error-handler' })
16
+ .onError(async ({ error, request, path, set }) => {
17
+ // Extract request context
18
+ const context: ErrorHandlerContext = {
19
+ logger: options.logger || console as any, // Fallback to console if no logger provided
20
+ isDevelopment: options.isDevelopment ?? process.env.NODE_ENV === 'development',
21
+ request,
22
+ path,
23
+ method: request.method,
24
+ correlationId: request.headers.get('x-correlation-id') || undefined,
25
+ userId: request.headers.get('x-user-id') || undefined,
26
+ userAgent: request.headers.get('user-agent') || undefined,
27
+ ip: request.headers.get('x-forwarded-for') ||
28
+ request.headers.get('x-real-ip') ||
29
+ 'unknown',
30
+ metricsCollector: options.metricsCollector
31
+ }
32
+
33
+ try {
34
+ // Convert Elysia error to standard Error if needed
35
+ const standardError = error instanceof Error ? error : new Error(String(error))
36
+ const errorResponse = await handler.handle(standardError, context)
37
+
38
+ // Set response status code
39
+ set.status = errorResponse.error.statusCode
40
+
41
+ // Set correlation ID header if available
42
+ if (errorResponse.error.correlationId) {
43
+ set.headers['x-correlation-id'] = errorResponse.error.correlationId
44
+ }
45
+
46
+ return errorResponse
47
+ } catch (handlerError) {
48
+ // Fallback error handling if the error handler itself fails
49
+ const fallbackLogger = options.logger || console as any
50
+ fallbackLogger.error('Error handler failed', {
51
+ originalError: error instanceof Error ? error.message : String(error),
52
+ handlerError: handlerError instanceof Error ? handlerError.message : handlerError
53
+ })
54
+
55
+ set.status = 500
56
+ return {
57
+ error: {
58
+ message: 'Internal server error',
59
+ code: 'INTERNAL_ERROR',
60
+ statusCode: 500,
61
+ timestamp: new Date().toISOString()
62
+ }
63
+ }
64
+ }
65
+ })
66
+ }
67
+
68
+ // Correlation ID middleware to add correlation IDs to requests
69
+ export const correlationIdMiddleware = () => {
70
+ return new Elysia({ name: 'correlation-id' })
71
+ .onRequest(({ request, set }) => {
72
+ // Check if correlation ID already exists in headers
73
+ let correlationId = request.headers.get('x-correlation-id')
74
+
75
+ // Generate new correlation ID if not present
76
+ if (!correlationId) {
77
+ correlationId = crypto.randomUUID()
78
+ }
79
+
80
+ // Add correlation ID to response headers
81
+ set.headers['x-correlation-id'] = correlationId
82
+
83
+ // Store correlation ID in request context for later use
84
+ // Note: This would typically be stored in a request-scoped context
85
+ // For now, we'll rely on the error handler to extract it from headers
86
+ })
87
+ }
88
+
89
+ // Request context middleware to extract and store request information
90
+ export const requestContextMiddleware = () => {
91
+ return new Elysia({ name: 'request-context' })
92
+ .onRequest(({ request, set }) => {
93
+ // Extract useful request information and store in headers for error handling
94
+ const userAgent = request.headers.get('user-agent')
95
+ const ip = request.headers.get('x-forwarded-for') ||
96
+ request.headers.get('x-real-ip') ||
97
+ 'unknown'
98
+
99
+ // Store in custom headers for error handler access
100
+ // In a real implementation, this would use request-scoped storage
101
+ if (userAgent) {
102
+ set.headers['x-internal-user-agent'] = userAgent
103
+ }
104
+ set.headers['x-internal-ip'] = ip
105
+ })
106
+ }
107
+
108
+ // Combined error handling middleware with all features
109
+ export const fullErrorHandlingMiddleware = (options: ErrorMiddlewareOptions = {}) => {
110
+ return new Elysia({ name: 'full-error-handling' })
111
+ .use(correlationIdMiddleware())
112
+ .use(requestContextMiddleware())
113
+ .use(errorMiddleware(options))
114
114
  }
@@ -91,23 +91,13 @@ export const throttle = <T extends (...args: any[]) => any>(
91
91
  * Uses declarative config system instead of legacy env
92
92
  */
93
93
 
94
- export const isProduction = (): boolean => {
95
- // Lazy import to avoid circular dependency during module initialization
96
- const { appConfig } = require('@/config/app.config')
97
- return appConfig.env === 'production'
98
- }
94
+ const getNodeEnv = (): string => process.env.NODE_ENV || 'development'
99
95
 
100
- export const isDevelopment = (): boolean => {
101
- // Lazy import to avoid circular dependency during module initialization
102
- const { appConfig } = require('@/config/app.config')
103
- return appConfig.env === 'development'
104
- }
96
+ export const isProduction = (): boolean => getNodeEnv() === 'production'
105
97
 
106
- export const isTest = (): boolean => {
107
- // Lazy import to avoid circular dependency during module initialization
108
- const { appConfig } = require('@/config/app.config')
109
- return appConfig.env === 'test'
110
- }
98
+ export const isDevelopment = (): boolean => getNodeEnv() === 'development'
99
+
100
+ export const isTest = (): boolean => getNodeEnv() === 'test'
111
101
 
112
102
  export const deepMerge = <T extends Record<string, any>>(target: T, source: Partial<T>): T => {
113
103
  const result = { ...target }
@@ -188,4 +178,4 @@ export const safeJsonStringify = (obj: any, fallback: string = '{}'): string =>
188
178
  } catch {
189
179
  return fallback
190
180
  }
191
- }
181
+ }