create-fluxstack 1.10.1 → 1.12.1

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 (257) hide show
  1. package/.dockerignore +1 -2
  2. package/Dockerfile +8 -8
  3. package/LLMD/INDEX.md +64 -0
  4. package/LLMD/MAINTENANCE.md +197 -0
  5. package/LLMD/MIGRATION.md +156 -0
  6. package/LLMD/config/.gitkeep +1 -0
  7. package/LLMD/config/declarative-system.md +268 -0
  8. package/LLMD/config/environment-vars.md +327 -0
  9. package/LLMD/config/runtime-reload.md +401 -0
  10. package/LLMD/core/.gitkeep +1 -0
  11. package/LLMD/core/build-system.md +599 -0
  12. package/LLMD/core/framework-lifecycle.md +229 -0
  13. package/LLMD/core/plugin-system.md +451 -0
  14. package/LLMD/patterns/.gitkeep +1 -0
  15. package/LLMD/patterns/anti-patterns.md +297 -0
  16. package/LLMD/patterns/project-structure.md +264 -0
  17. package/LLMD/patterns/type-safety.md +440 -0
  18. package/LLMD/reference/.gitkeep +1 -0
  19. package/LLMD/reference/cli-commands.md +250 -0
  20. package/LLMD/reference/plugin-hooks.md +357 -0
  21. package/LLMD/reference/routing.md +39 -0
  22. package/LLMD/reference/troubleshooting.md +364 -0
  23. package/LLMD/resources/.gitkeep +1 -0
  24. package/LLMD/resources/controllers.md +465 -0
  25. package/LLMD/resources/live-components.md +703 -0
  26. package/LLMD/resources/live-rooms.md +482 -0
  27. package/LLMD/resources/live-upload.md +130 -0
  28. package/LLMD/resources/plugins-external.md +617 -0
  29. package/LLMD/resources/routes-eden.md +254 -0
  30. package/README.md +37 -17
  31. package/app/client/index.html +0 -1
  32. package/app/client/src/App.tsx +107 -150
  33. package/app/client/src/components/AppLayout.tsx +68 -0
  34. package/app/client/src/components/BackButton.tsx +13 -0
  35. package/app/client/src/components/DemoPage.tsx +20 -0
  36. package/app/client/src/components/LiveUploadWidget.tsx +204 -0
  37. package/app/client/src/lib/eden-api.ts +85 -60
  38. package/app/client/src/live/ChatDemo.tsx +107 -0
  39. package/app/client/src/live/CounterDemo.tsx +206 -0
  40. package/app/client/src/live/FormDemo.tsx +119 -0
  41. package/app/client/src/live/RoomChatDemo.tsx +161 -0
  42. package/app/client/src/live/UploadDemo.tsx +21 -0
  43. package/app/client/src/main.tsx +4 -1
  44. package/app/client/src/pages/ApiTestPage.tsx +108 -0
  45. package/app/client/src/pages/HomePage.tsx +76 -0
  46. package/app/server/app.ts +1 -4
  47. package/app/server/controllers/users.controller.ts +36 -44
  48. package/app/server/index.ts +25 -35
  49. package/app/server/live/LiveChat.ts +77 -0
  50. package/app/server/live/LiveCounter.ts +67 -0
  51. package/app/server/live/LiveForm.ts +63 -0
  52. package/app/server/live/LiveLocalCounter.ts +32 -0
  53. package/app/server/live/LiveRoomChat.ts +127 -0
  54. package/app/server/live/LiveUpload.ts +81 -0
  55. package/app/server/routes/index.ts +3 -1
  56. package/app/server/routes/room.routes.ts +117 -0
  57. package/app/server/routes/users.routes.ts +35 -27
  58. package/app/shared/types/index.ts +14 -2
  59. package/config/app.config.ts +2 -62
  60. package/config/client.config.ts +2 -95
  61. package/config/database.config.ts +2 -99
  62. package/config/fluxstack.config.ts +25 -45
  63. package/config/index.ts +57 -38
  64. package/config/monitoring.config.ts +2 -114
  65. package/config/plugins.config.ts +2 -80
  66. package/config/server.config.ts +2 -68
  67. package/config/services.config.ts +2 -130
  68. package/config/system/app.config.ts +29 -0
  69. package/config/system/build.config.ts +49 -0
  70. package/config/system/client.config.ts +68 -0
  71. package/config/system/database.config.ts +17 -0
  72. package/config/system/fluxstack.config.ts +114 -0
  73. package/config/{logger.config.ts → system/logger.config.ts} +3 -1
  74. package/config/system/monitoring.config.ts +114 -0
  75. package/config/system/plugins.config.ts +84 -0
  76. package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
  77. package/config/system/server.config.ts +68 -0
  78. package/config/system/services.config.ts +46 -0
  79. package/config/{system.config.ts → system/system.config.ts} +1 -1
  80. package/core/build/flux-plugins-generator.ts +325 -325
  81. package/core/build/index.ts +39 -27
  82. package/core/build/live-components-generator.ts +3 -3
  83. package/core/build/optimizer.ts +235 -235
  84. package/core/cli/command-registry.ts +6 -4
  85. package/core/cli/commands/build.ts +79 -0
  86. package/core/cli/commands/create.ts +54 -0
  87. package/core/cli/commands/dev.ts +101 -0
  88. package/core/cli/commands/help.ts +34 -0
  89. package/core/cli/commands/index.ts +34 -0
  90. package/core/cli/commands/make-plugin.ts +90 -0
  91. package/core/cli/commands/plugin-add.ts +197 -0
  92. package/core/cli/commands/plugin-deps.ts +2 -2
  93. package/core/cli/commands/plugin-list.ts +208 -0
  94. package/core/cli/commands/plugin-remove.ts +170 -0
  95. package/core/cli/generators/component.ts +769 -769
  96. package/core/cli/generators/controller.ts +1 -1
  97. package/core/cli/generators/index.ts +146 -146
  98. package/core/cli/generators/interactive.ts +227 -227
  99. package/core/cli/generators/plugin.ts +2 -2
  100. package/core/cli/generators/prompts.ts +82 -82
  101. package/core/cli/generators/route.ts +6 -6
  102. package/core/cli/generators/service.ts +2 -2
  103. package/core/cli/generators/template-engine.ts +4 -3
  104. package/core/cli/generators/types.ts +2 -2
  105. package/core/cli/generators/utils.ts +191 -191
  106. package/core/cli/index.ts +115 -686
  107. package/core/cli/plugin-discovery.ts +2 -2
  108. package/core/client/LiveComponentsProvider.tsx +60 -8
  109. package/core/client/api/eden.ts +183 -0
  110. package/core/client/api/index.ts +11 -0
  111. package/core/client/components/Live.tsx +104 -0
  112. package/core/client/fluxstack.ts +1 -9
  113. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
  114. package/core/client/hooks/state-validator.ts +1 -1
  115. package/core/client/hooks/useAuth.ts +48 -48
  116. package/core/client/hooks/useChunkedUpload.ts +85 -35
  117. package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
  118. package/core/client/hooks/useLiveComponent.ts +800 -0
  119. package/core/client/hooks/useLiveUpload.ts +71 -0
  120. package/core/client/hooks/useRoom.ts +409 -0
  121. package/core/client/hooks/useRoomProxy.ts +382 -0
  122. package/core/client/index.ts +17 -68
  123. package/core/client/standalone-entry.ts +8 -0
  124. package/core/client/standalone.ts +74 -53
  125. package/core/client/state/createStore.ts +192 -192
  126. package/core/client/state/index.ts +14 -14
  127. package/core/config/index.ts +70 -291
  128. package/core/config/schema.ts +42 -723
  129. package/core/framework/client.ts +131 -131
  130. package/core/framework/index.ts +7 -7
  131. package/core/framework/server.ts +47 -40
  132. package/core/framework/types.ts +2 -2
  133. package/core/index.ts +23 -4
  134. package/core/live/ComponentRegistry.ts +3 -3
  135. package/core/live/types.ts +77 -0
  136. package/core/plugins/built-in/index.ts +134 -134
  137. package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1066
  138. package/core/plugins/built-in/live-components/index.ts +1 -1
  139. package/core/plugins/built-in/monitoring/index.ts +111 -47
  140. package/core/plugins/built-in/static/index.ts +1 -1
  141. package/core/plugins/built-in/swagger/index.ts +68 -265
  142. package/core/plugins/built-in/vite/index.ts +85 -185
  143. package/core/plugins/built-in/vite/vite-dev.ts +10 -16
  144. package/core/plugins/config.ts +9 -7
  145. package/core/plugins/dependency-manager.ts +31 -1
  146. package/core/plugins/discovery.ts +19 -7
  147. package/core/plugins/executor.ts +2 -2
  148. package/core/plugins/index.ts +203 -203
  149. package/core/plugins/manager.ts +27 -39
  150. package/core/plugins/module-resolver.ts +19 -8
  151. package/core/plugins/registry.ts +255 -19
  152. package/core/plugins/types.ts +20 -53
  153. package/core/server/framework.ts +66 -43
  154. package/core/server/index.ts +15 -15
  155. package/core/server/live/ComponentRegistry.ts +78 -71
  156. package/core/server/live/FileUploadManager.ts +23 -10
  157. package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
  158. package/core/server/live/LiveRoomManager.ts +261 -0
  159. package/core/server/live/RoomEventBus.ts +234 -0
  160. package/core/server/live/RoomStateManager.ts +172 -0
  161. package/core/server/live/StateSignature.ts +643 -643
  162. package/core/server/live/WebSocketConnectionManager.ts +30 -19
  163. package/core/server/live/auto-generated-components.ts +21 -9
  164. package/core/server/live/index.ts +14 -0
  165. package/core/server/live/websocket-plugin.ts +214 -67
  166. package/core/server/middleware/elysia-helpers.ts +7 -2
  167. package/core/server/middleware/errorHandling.ts +1 -1
  168. package/core/server/middleware/index.ts +31 -31
  169. package/core/server/plugins/database.ts +180 -180
  170. package/core/server/plugins/static-files-plugin.ts +69 -69
  171. package/core/server/plugins/swagger.ts +1 -1
  172. package/core/server/rooms/RoomBroadcaster.ts +357 -0
  173. package/core/server/rooms/RoomSystem.ts +463 -0
  174. package/core/server/rooms/index.ts +13 -0
  175. package/core/server/services/BaseService.ts +1 -1
  176. package/core/server/services/ServiceContainer.ts +1 -1
  177. package/core/server/services/index.ts +8 -8
  178. package/core/templates/create-project.ts +12 -12
  179. package/core/testing/index.ts +9 -9
  180. package/core/testing/setup.ts +73 -73
  181. package/core/types/api.ts +168 -168
  182. package/core/types/build.ts +219 -219
  183. package/core/types/config.ts +56 -26
  184. package/core/types/index.ts +4 -4
  185. package/core/types/plugin.ts +107 -107
  186. package/core/types/types.ts +353 -14
  187. package/core/utils/build-logger.ts +324 -324
  188. package/core/utils/config-schema.ts +480 -480
  189. package/core/utils/env.ts +2 -8
  190. package/core/utils/errors/codes.ts +114 -114
  191. package/core/utils/errors/handlers.ts +36 -1
  192. package/core/utils/errors/index.ts +49 -5
  193. package/core/utils/errors/middleware.ts +113 -113
  194. package/core/utils/helpers.ts +6 -16
  195. package/core/utils/index.ts +17 -17
  196. package/core/utils/logger/colors.ts +114 -114
  197. package/core/utils/logger/config.ts +13 -9
  198. package/core/utils/logger/formatter.ts +82 -82
  199. package/core/utils/logger/group-logger.ts +101 -101
  200. package/core/utils/logger/index.ts +6 -1
  201. package/core/utils/logger/stack-trace.ts +3 -1
  202. package/core/utils/logger/startup-banner.ts +82 -82
  203. package/core/utils/logger/winston-logger.ts +152 -152
  204. package/core/utils/monitoring/index.ts +211 -211
  205. package/core/utils/sync-version.ts +66 -66
  206. package/core/utils/version.ts +1 -1
  207. package/create-fluxstack.ts +8 -7
  208. package/package.json +12 -13
  209. package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
  210. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  211. package/plugins/crypto-auth/client/components/index.ts +11 -11
  212. package/plugins/crypto-auth/client/index.ts +11 -11
  213. package/plugins/crypto-auth/config/index.ts +1 -1
  214. package/plugins/crypto-auth/index.ts +4 -4
  215. package/plugins/crypto-auth/package.json +65 -65
  216. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  217. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  218. package/plugins/crypto-auth/server/index.ts +21 -21
  219. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
  220. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
  221. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
  222. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
  223. package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
  224. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  225. package/tsconfig.api-strict.json +16 -0
  226. package/tsconfig.json +48 -52
  227. package/{app/client/tsconfig.node.json → tsconfig.node.json} +25 -25
  228. package/types/global.d.ts +29 -29
  229. package/types/vitest.d.ts +8 -8
  230. package/vite.config.ts +38 -62
  231. package/vitest.config.live.ts +10 -9
  232. package/vitest.config.ts +29 -17
  233. package/app/client/README.md +0 -69
  234. package/app/client/SIMPLIFICATION.md +0 -140
  235. package/app/client/frontend-only.ts +0 -12
  236. package/app/client/src/live/FileUploadExample.tsx +0 -359
  237. package/app/client/src/live/MinimalLiveClock.tsx +0 -47
  238. package/app/client/src/live/QuickUploadTest.tsx +0 -193
  239. package/app/client/tsconfig.app.json +0 -45
  240. package/app/client/tsconfig.json +0 -7
  241. package/app/client/zustand-setup.md +0 -65
  242. package/app/server/backend-only.ts +0 -18
  243. package/app/server/live/LiveClockComponent.ts +0 -215
  244. package/app/server/live/LiveFileUploadComponent.ts +0 -77
  245. package/app/server/routes/env-test.ts +0 -110
  246. package/core/client/hooks/index.ts +0 -7
  247. package/core/client/hooks/useHybridLiveComponent.ts +0 -685
  248. package/core/client/hooks/useTypedLiveComponent.ts +0 -133
  249. package/core/client/hooks/useWebSocket.ts +0 -361
  250. package/core/config/env.ts +0 -546
  251. package/core/config/loader.ts +0 -522
  252. package/core/config/runtime-config.ts +0 -327
  253. package/core/config/validator.ts +0 -540
  254. package/core/server/backend-entry.ts +0 -51
  255. package/core/server/standalone.ts +0 -106
  256. package/core/utils/regenerate-files.ts +0 -69
  257. package/fluxstack.config.ts +0 -354
@@ -1,546 +0,0 @@
1
- /**
2
- * Enhanced Environment Configuration System for FluxStack
3
- * Handles environment variable processing and precedence
4
- */
5
-
6
- import { env, helpers } from '@/core/utils/env'
7
- import type { FluxStackConfig, LogLevel, BuildTarget, LogFormat } from './schema'
8
-
9
- export interface EnvironmentInfo {
10
- name: string
11
- isDevelopment: boolean
12
- isProduction: boolean
13
- isTest: boolean
14
- nodeEnv: string
15
- }
16
-
17
- export interface ConfigPrecedence {
18
- source: 'default' | 'file' | 'environment' | 'override'
19
- path: string
20
- value: any
21
- priority: number
22
- }
23
-
24
- /**
25
- * Get current environment information
26
- */
27
- export function getEnvironmentInfo(): EnvironmentInfo {
28
- const nodeEnv = env.NODE_ENV
29
-
30
- return {
31
- name: nodeEnv,
32
- isDevelopment: nodeEnv === 'development',
33
- isProduction: nodeEnv === 'production',
34
- isTest: nodeEnv === 'test',
35
- nodeEnv
36
- }
37
- }
38
-
39
- /**
40
- * Environment variable type conversion utilities
41
- */
42
- export class EnvConverter {
43
- static toNumber(value: string | undefined, defaultValue: number): number {
44
- if (!value) return defaultValue
45
- const parsed = parseInt(value, 10)
46
- return isNaN(parsed) ? defaultValue : parsed
47
- }
48
-
49
- static toBoolean(value: string | undefined, defaultValue: boolean): boolean {
50
- if (value === undefined) return defaultValue
51
- if (value === '') return false
52
- return ['true', '1', 'yes', 'on'].includes(value.toLowerCase())
53
- }
54
-
55
- static toArray(value: string | undefined, defaultValue: string[] = []): string[] {
56
- if (!value) return defaultValue
57
- return value.split(',').map(v => v.trim()).filter(Boolean)
58
- }
59
-
60
- static toLogLevel(value: string | undefined, defaultValue: LogLevel): LogLevel {
61
- if (!value) return defaultValue
62
- const level = value.toLowerCase() as LogLevel
63
- return ['debug', 'info', 'warn', 'error'].includes(level) ? level : defaultValue
64
- }
65
-
66
- static toBuildTarget(value: string | undefined, defaultValue: BuildTarget): BuildTarget {
67
- if (!value) return defaultValue
68
- const target = value.toLowerCase() as BuildTarget
69
- return ['bun', 'node', 'docker'].includes(target) ? target : defaultValue
70
- }
71
-
72
- static toLogFormat(value: string | undefined, defaultValue: LogFormat): LogFormat {
73
- if (!value) return defaultValue
74
- const format = value.toLowerCase() as LogFormat
75
- return ['json', 'pretty'].includes(format) ? format : defaultValue
76
- }
77
-
78
- static toObject<T = any>(value: string | undefined, defaultValue: T): T {
79
- if (!value) return defaultValue
80
- try {
81
- return JSON.parse(value)
82
- } catch {
83
- return defaultValue
84
- }
85
- }
86
- }
87
-
88
- /**
89
- * Environment variable processor with precedence handling
90
- */
91
- export class EnvironmentProcessor {
92
- private precedenceMap: Map<string, ConfigPrecedence> = new Map()
93
-
94
- /**
95
- * Process environment variables with type conversion and precedence tracking
96
- */
97
- processEnvironmentVariables(): Partial<FluxStackConfig> {
98
- const config: any = {}
99
-
100
- // App configuration
101
- this.setConfigValue(config, 'app.name', env.FLUXSTACK_APP_NAME, 'string')
102
- this.setConfigValue(config, 'app.version', env.FLUXSTACK_APP_VERSION, 'string')
103
-
104
- // Server configuration
105
- this.setConfigValue(config, 'server.port', env.PORT?.toString(), 'number')
106
- this.setConfigValue(config, 'server.host', env.HOST, 'string')
107
- this.setConfigValue(config, 'server.apiPrefix', env.API_PREFIX, 'string')
108
-
109
- // CORS configuration
110
- const corsOriginsStr = env.has('CORS_ORIGINS') ? env.all().CORS_ORIGINS : undefined
111
- const corsMethodsStr = env.has('CORS_METHODS') ? env.all().CORS_METHODS : undefined
112
- const corsHeadersStr = env.has('CORS_HEADERS') ? env.all().CORS_HEADERS : undefined
113
-
114
- this.setConfigValue(config, 'server.cors.origins', corsOriginsStr, 'array')
115
- this.setConfigValue(config, 'server.cors.methods', corsMethodsStr, 'array')
116
- this.setConfigValue(config, 'server.cors.headers', corsHeadersStr, 'array')
117
- this.setConfigValue(config, 'server.cors.credentials', env.CORS_CREDENTIALS?.toString(), 'boolean')
118
- this.setConfigValue(config, 'server.cors.maxAge', env.CORS_MAX_AGE?.toString(), 'number')
119
-
120
- // Client configuration
121
- this.setConfigValue(config, 'client.port', env.VITE_PORT?.toString(), 'number')
122
-
123
- // Build configuration
124
- const buildMinify = env.has('BUILD_MINIFY') ? env.all().BUILD_MINIFY : undefined
125
- this.setConfigValue(config, 'build.optimization.minify', buildMinify, 'boolean')
126
-
127
- // Logging configuration
128
- this.setConfigValue(config, 'logging.level', env.LOG_LEVEL, 'logLevel')
129
- this.setConfigValue(config, 'logging.format', env.LOG_FORMAT, 'logFormat')
130
-
131
- // Monitoring configuration
132
- this.setConfigValue(config, 'monitoring.enabled', env.ENABLE_MONITORING?.toString(), 'boolean')
133
- this.setConfigValue(config, 'monitoring.metrics.enabled', env.ENABLE_METRICS?.toString(), 'boolean')
134
-
135
- // Database configuration
136
- this.setConfigValue(config, 'database.url', env.DATABASE_URL, 'string')
137
- this.setConfigValue(config, 'database.host', env.DB_HOST, 'string')
138
- this.setConfigValue(config, 'database.port', env.DB_PORT?.toString(), 'number')
139
- this.setConfigValue(config, 'database.database', env.DB_NAME, 'string')
140
- this.setConfigValue(config, 'database.user', env.DB_USER, 'string')
141
- this.setConfigValue(config, 'database.password', env.DB_PASSWORD, 'string')
142
- this.setConfigValue(config, 'database.ssl', env.DB_SSL?.toString(), 'boolean')
143
-
144
- // Auth configuration
145
- this.setConfigValue(config, 'auth.secret', env.JWT_SECRET, 'string')
146
- this.setConfigValue(config, 'auth.expiresIn', env.JWT_EXPIRES_IN, 'string')
147
- this.setConfigValue(config, 'auth.algorithm', env.JWT_ALGORITHM, 'string')
148
-
149
- // Email configuration
150
- this.setConfigValue(config, 'email.host', env.SMTP_HOST, 'string')
151
- this.setConfigValue(config, 'email.port', env.SMTP_PORT?.toString(), 'number')
152
- this.setConfigValue(config, 'email.user', env.SMTP_USER, 'string')
153
- this.setConfigValue(config, 'email.password', env.SMTP_PASSWORD, 'string')
154
- this.setConfigValue(config, 'email.secure', env.SMTP_SECURE?.toString(), 'boolean')
155
-
156
- return this.cleanEmptyObjects(config)
157
- }
158
-
159
- private setConfigValue(
160
- config: any,
161
- path: string,
162
- value: string | undefined,
163
- type: string
164
- ): void {
165
- if (value === undefined) return
166
-
167
- const convertedValue = this.convertValue(value, type)
168
- if (convertedValue !== undefined) {
169
- this.setNestedProperty(config, path, convertedValue)
170
-
171
- // Track precedence
172
- this.precedenceMap.set(path, {
173
- source: 'environment',
174
- path,
175
- value: convertedValue,
176
- priority: 3 // Environment variables have high priority
177
- })
178
- }
179
- }
180
-
181
- private convertValue(value: string, type: string): any {
182
- switch (type) {
183
- case 'string':
184
- return value
185
- case 'number':
186
- return EnvConverter.toNumber(value, 0)
187
- case 'boolean':
188
- const boolValue = EnvConverter.toBoolean(value, false)
189
- return boolValue
190
- case 'array':
191
- return EnvConverter.toArray(value)
192
- case 'logLevel':
193
- return EnvConverter.toLogLevel(value, 'info')
194
- case 'buildTarget':
195
- return EnvConverter.toBuildTarget(value, 'bun')
196
- case 'logFormat':
197
- return EnvConverter.toLogFormat(value, 'pretty')
198
- case 'object':
199
- return EnvConverter.toObject(value, {})
200
- default:
201
- return value
202
- }
203
- }
204
-
205
- private setNestedProperty(obj: any, path: string, value: any): void {
206
- const keys = path.split('.')
207
- let current = obj
208
-
209
- for (let i = 0; i < keys.length - 1; i++) {
210
- const key = keys[i]
211
- if (!(key in current) || typeof current[key] !== 'object') {
212
- current[key] = {}
213
- }
214
- current = current[key]
215
- }
216
-
217
- current[keys[keys.length - 1]] = value
218
- }
219
-
220
- private cleanEmptyObjects(obj: any): any {
221
- if (typeof obj !== 'object' || obj === null) return obj
222
-
223
- const cleaned: any = {}
224
-
225
- for (const [key, value] of Object.entries(obj)) {
226
- if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
227
- const cleanedValue = this.cleanEmptyObjects(value)
228
- if (Object.keys(cleanedValue).length > 0) {
229
- cleaned[key] = cleanedValue
230
- }
231
- } else if (value !== undefined && value !== null) {
232
- cleaned[key] = value
233
- }
234
- }
235
-
236
- return cleaned
237
- }
238
-
239
- /**
240
- * Get precedence information for configuration values
241
- */
242
- getPrecedenceInfo(): Map<string, ConfigPrecedence> {
243
- return new Map(this.precedenceMap)
244
- }
245
-
246
- /**
247
- * Clear precedence tracking
248
- */
249
- clearPrecedence(): void {
250
- this.precedenceMap.clear()
251
- }
252
- }
253
-
254
- /**
255
- * Configuration merger with precedence handling
256
- */
257
- export class ConfigMerger {
258
- private precedenceOrder = ['default', 'file', 'environment', 'override']
259
-
260
- /**
261
- * Merge configurations with precedence handling
262
- * Higher precedence values override lower ones
263
- */
264
- merge(...configs: Array<{ config: Partial<FluxStackConfig>, source: string }>): FluxStackConfig {
265
- let result: any = {}
266
- const precedenceMap: Map<string, ConfigPrecedence> = new Map()
267
-
268
- // Process configs in precedence order
269
- for (const { config, source } of configs) {
270
- this.deepMergeWithPrecedence(result, config, source, precedenceMap)
271
- }
272
-
273
- return result as FluxStackConfig
274
- }
275
-
276
- private deepMergeWithPrecedence(
277
- target: any,
278
- source: any,
279
- sourceName: string,
280
- precedenceMap: Map<string, ConfigPrecedence>,
281
- currentPath = ''
282
- ): void {
283
- if (!source || typeof source !== 'object') return
284
-
285
- for (const [key, value] of Object.entries(source)) {
286
- const fullPath = currentPath ? `${currentPath}.${key}` : key
287
- const sourcePriority = this.precedenceOrder.indexOf(sourceName)
288
-
289
- if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
290
- // Ensure target has the nested object
291
- if (!(key in target) || typeof target[key] !== 'object') {
292
- target[key] = {}
293
- }
294
-
295
- // Recursively merge nested objects
296
- this.deepMergeWithPrecedence(target[key], value, sourceName, precedenceMap, fullPath)
297
- } else {
298
- // Check precedence before overriding
299
- const existingPrecedence = precedenceMap.get(fullPath)
300
-
301
- if (!existingPrecedence || sourcePriority >= existingPrecedence.priority) {
302
- target[key] = value
303
- precedenceMap.set(fullPath, {
304
- source: sourceName as any,
305
- path: fullPath,
306
- value,
307
- priority: sourcePriority
308
- })
309
- }
310
- }
311
- }
312
- }
313
- }
314
-
315
- /**
316
- * Environment-specific configuration applier
317
- */
318
- export class EnvironmentConfigApplier {
319
- /**
320
- * Apply environment-specific configuration overrides
321
- */
322
- applyEnvironmentConfig(
323
- baseConfig: FluxStackConfig,
324
- environment: string
325
- ): FluxStackConfig {
326
- const envConfig = baseConfig.environments?.[environment]
327
-
328
- if (!envConfig) {
329
- return baseConfig
330
- }
331
-
332
- const merger = new ConfigMerger()
333
- return merger.merge(
334
- { config: baseConfig, source: 'base' },
335
- { config: envConfig, source: `environment:${environment}` }
336
- )
337
- }
338
-
339
- /**
340
- * Get available environments from configuration
341
- */
342
- getAvailableEnvironments(config: FluxStackConfig): string[] {
343
- return config.environments ? Object.keys(config.environments) : []
344
- }
345
-
346
- /**
347
- * Validate environment-specific configuration
348
- */
349
- validateEnvironmentConfig(
350
- config: FluxStackConfig,
351
- environment: string
352
- ): { valid: boolean; errors: string[] } {
353
- const envConfig = config.environments?.[environment]
354
-
355
- if (!envConfig) {
356
- return { valid: true, errors: [] }
357
- }
358
-
359
- const errors: string[] = []
360
-
361
- // Check for conflicting configurations
362
- if (envConfig.server?.port === config.server.port && environment !== 'development') {
363
- errors.push(`Environment ${environment} uses same port as base configuration`)
364
- }
365
-
366
- // Check for missing required overrides in production
367
- if (environment === 'production') {
368
- if (!envConfig.logging?.level || envConfig.logging.level === 'debug') {
369
- errors.push('Production environment should not use debug logging')
370
- }
371
-
372
- if (!envConfig.monitoring?.enabled) {
373
- errors.push('Production environment should enable monitoring')
374
- }
375
- }
376
-
377
- return {
378
- valid: errors.length === 0,
379
- errors
380
- }
381
- }
382
- }
383
-
384
- // Singleton instances for global use
385
- export const environmentProcessor = new EnvironmentProcessor()
386
- export const configMerger = new ConfigMerger()
387
- export const environmentConfigApplier = new EnvironmentConfigApplier()
388
-
389
- /**
390
- * Utility functions for backward compatibility
391
- */
392
- export function isDevelopment(): boolean {
393
- return getEnvironmentInfo().isDevelopment
394
- }
395
-
396
- export function isProduction(): boolean {
397
- return getEnvironmentInfo().isProduction
398
- }
399
-
400
- export function isTest(): boolean {
401
- return getEnvironmentInfo().isTest
402
- }
403
-
404
- /**
405
- * Get environment-specific configuration recommendations
406
- */
407
- export function getEnvironmentRecommendations(environment: string): Partial<FluxStackConfig> {
408
- switch (environment) {
409
- case 'development':
410
- return {
411
- logging: {
412
- level: 'debug' as const,
413
- format: 'pretty' as const,
414
- transports: [{ type: 'console' as const, level: 'debug' as const, format: 'pretty' as const }]
415
- },
416
- build: {
417
- target: 'bun' as const,
418
- outDir: 'dist',
419
- clean: true,
420
- minify: false,
421
- treeshake: false,
422
- optimization: {
423
- minify: false,
424
- compress: false,
425
- treeshake: false,
426
- splitChunks: false,
427
- bundleAnalyzer: false
428
- },
429
- sourceMaps: true
430
- },
431
- monitoring: {
432
- enabled: false,
433
- metrics: {
434
- enabled: false,
435
- collectInterval: 60000,
436
- httpMetrics: true,
437
- systemMetrics: true,
438
- customMetrics: false
439
- },
440
- profiling: {
441
- enabled: false,
442
- sampleRate: 0.1,
443
- memoryProfiling: false,
444
- cpuProfiling: false
445
- },
446
- exporters: []
447
- }
448
- }
449
-
450
- case 'production':
451
- return {
452
- logging: {
453
- level: 'warn' as const,
454
- format: 'json' as const,
455
- transports: [
456
- { type: 'console' as const, level: 'warn' as const, format: 'json' as const },
457
- { type: 'file' as const, level: 'warn' as const, format: 'json' as const, options: { filename: 'app.log' } }
458
- ]
459
- },
460
- build: {
461
- target: 'bun' as const,
462
- outDir: 'dist',
463
- clean: true,
464
- minify: true,
465
- treeshake: true,
466
- optimization: {
467
- minify: true,
468
- compress: true,
469
- treeshake: true,
470
- splitChunks: true,
471
- bundleAnalyzer: false
472
- },
473
- sourceMaps: false
474
- },
475
- monitoring: {
476
- enabled: true,
477
- metrics: {
478
- enabled: true,
479
- collectInterval: 30000,
480
- httpMetrics: true,
481
- systemMetrics: true,
482
- customMetrics: false
483
- },
484
- profiling: {
485
- enabled: true,
486
- sampleRate: 0.01,
487
- memoryProfiling: true,
488
- cpuProfiling: true
489
- },
490
- exporters: ['prometheus']
491
- }
492
- }
493
-
494
- case 'test':
495
- return {
496
- logging: {
497
- level: 'error' as const,
498
- format: 'json' as const,
499
- transports: [{ type: 'console' as const, level: 'error' as const, format: 'json' as const }]
500
- },
501
- server: {
502
- port: 0, // Random port
503
- host: 'localhost',
504
- apiPrefix: '/api',
505
- cors: {
506
- origins: ['*'],
507
- methods: ['GET', 'POST', 'PUT', 'DELETE'],
508
- headers: ['Content-Type', 'Authorization'],
509
- credentials: false,
510
- maxAge: 86400
511
- },
512
- middleware: []
513
- },
514
- client: {
515
- port: 0,
516
- proxy: { target: 'http://localhost:3000' },
517
- build: {
518
- target: 'es2020' as const,
519
- outDir: 'dist/client',
520
- sourceMaps: false,
521
- minify: false
522
- }
523
- },
524
- monitoring: {
525
- enabled: false,
526
- metrics: {
527
- enabled: false,
528
- collectInterval: 60000,
529
- httpMetrics: true,
530
- systemMetrics: true,
531
- customMetrics: false
532
- },
533
- profiling: {
534
- enabled: false,
535
- sampleRate: 0.1,
536
- memoryProfiling: false,
537
- cpuProfiling: false
538
- },
539
- exporters: []
540
- }
541
- }
542
-
543
- default:
544
- return {}
545
- }
546
- }