create-fluxstack 1.10.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 (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 +242 -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 +285 -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,522 +0,0 @@
1
- /**
2
- * Configuration Loader for FluxStack
3
- * Handles loading, merging, and environment variable integration
4
- */
5
-
6
- import { existsSync } from 'fs'
7
- import { join } from 'path'
8
- import type {
9
- FluxStackConfig
10
- } from './schema'
11
- import {
12
- defaultFluxStackConfig,
13
- environmentDefaults
14
- } from './schema'
15
-
16
- export interface ConfigLoadOptions {
17
- configPath?: string
18
- environment?: string
19
- envPrefix?: string
20
- validateSchema?: boolean
21
- }
22
-
23
- export interface ConfigLoadResult {
24
- config: FluxStackConfig
25
- sources: string[]
26
- warnings: string[]
27
- errors: string[]
28
- }
29
-
30
- export interface ValidationResult {
31
- valid: boolean
32
- errors: ValidationError[]
33
- warnings: ValidationWarning[]
34
- }
35
-
36
- export interface ValidationError {
37
- path: string
38
- message: string
39
- value?: any
40
- }
41
-
42
- export interface ValidationWarning {
43
- path: string
44
- message: string
45
- value?: any
46
- }
47
-
48
- /**
49
- * Environment variable mapping for FluxStack configuration
50
- */
51
- const ENV_MAPPINGS = {
52
- // App configuration
53
- 'FLUXSTACK_APP_NAME': 'app.name',
54
- 'FLUXSTACK_APP_VERSION': 'app.version',
55
- 'FLUXSTACK_APP_DESCRIPTION': 'app.description',
56
-
57
- // Server configuration
58
- 'PORT': 'server.port',
59
- 'FLUXSTACK_PORT': 'server.port',
60
- 'HOST': 'server.host',
61
- 'FLUXSTACK_API_PREFIX': 'server.apiPrefix',
62
- 'CORS_ORIGINS': 'server.cors.origins',
63
- 'FLUXSTACK_CORS_ORIGINS': 'server.cors.origins',
64
- 'CORS_METHODS': 'server.cors.methods',
65
- 'FLUXSTACK_CORS_METHODS': 'server.cors.methods',
66
- 'CORS_HEADERS': 'server.cors.headers',
67
- 'FLUXSTACK_CORS_HEADERS': 'server.cors.headers',
68
- 'CORS_CREDENTIALS': 'server.cors.credentials',
69
- 'FLUXSTACK_CORS_CREDENTIALS': 'server.cors.credentials',
70
- 'CORS_MAX_AGE': 'server.cors.maxAge',
71
- 'FLUXSTACK_CORS_MAX_AGE': 'server.cors.maxAge',
72
-
73
- // Client configuration
74
- 'VITE_PORT': 'client.port',
75
- 'FLUXSTACK_CLIENT_PORT': 'client.port',
76
- 'FLUXSTACK_PROXY_TARGET': 'client.proxy.target',
77
- 'FLUXSTACK_CLIENT_SOURCEMAPS': 'client.build.sourceMaps',
78
- 'FLUXSTACK_CLIENT_MINIFY': 'client.build.minify',
79
- 'FLUXSTACK_CLIENT_TARGET': 'client.build.target',
80
- 'FLUXSTACK_CLIENT_OUTDIR': 'client.build.outDir',
81
-
82
- // Build configuration
83
- 'FLUXSTACK_BUILD_TARGET': 'build.target',
84
- 'FLUXSTACK_BUILD_OUTDIR': 'build.outDir',
85
- 'FLUXSTACK_BUILD_SOURCEMAPS': 'build.sourceMaps',
86
- 'FLUXSTACK_BUILD_CLEAN': 'build.clean',
87
- 'FLUXSTACK_BUILD_MINIFY': 'build.optimization.minify',
88
- 'FLUXSTACK_BUILD_TREESHAKE': 'build.optimization.treeshake',
89
- 'FLUXSTACK_BUILD_COMPRESS': 'build.optimization.compress',
90
- 'FLUXSTACK_BUILD_SPLIT_CHUNKS': 'build.optimization.splitChunks',
91
- 'FLUXSTACK_BUILD_ANALYZER': 'build.optimization.bundleAnalyzer',
92
-
93
- // Logging configuration
94
- 'LOG_LEVEL': 'logging.level',
95
- 'FLUXSTACK_LOG_LEVEL': 'logging.level',
96
- 'LOG_FORMAT': 'logging.format',
97
- 'FLUXSTACK_LOG_FORMAT': 'logging.format',
98
-
99
- // Monitoring configuration
100
- 'MONITORING_ENABLED': 'monitoring.enabled',
101
- 'FLUXSTACK_MONITORING_ENABLED': 'monitoring.enabled',
102
- 'METRICS_ENABLED': 'monitoring.metrics.enabled',
103
- 'FLUXSTACK_METRICS_ENABLED': 'monitoring.metrics.enabled',
104
- 'METRICS_INTERVAL': 'monitoring.metrics.collectInterval',
105
- 'FLUXSTACK_METRICS_INTERVAL': 'monitoring.metrics.collectInterval',
106
- 'PROFILING_ENABLED': 'monitoring.profiling.enabled',
107
- 'FLUXSTACK_PROFILING_ENABLED': 'monitoring.profiling.enabled',
108
- 'PROFILING_SAMPLE_RATE': 'monitoring.profiling.sampleRate',
109
- 'FLUXSTACK_PROFILING_SAMPLE_RATE': 'monitoring.profiling.sampleRate',
110
-
111
- // Plugin configuration
112
- 'FLUXSTACK_PLUGINS_ENABLED': 'plugins.enabled',
113
- 'FLUXSTACK_PLUGINS_DISABLED': 'plugins.disabled'
114
- } as const
115
-
116
- /**
117
- * Parse environment variable value to appropriate type
118
- */
119
- function parseEnvValue(value: string, targetType?: string): any {
120
- if (!value) return undefined
121
-
122
- // Handle different types based on target or value format
123
- if (targetType === 'number' || /^\d+$/.test(value)) {
124
- const parsed = parseInt(value, 10)
125
- return isNaN(parsed) ? undefined : parsed
126
- }
127
-
128
- if (targetType === 'boolean' || ['true', 'false', '1', '0'].includes(value.toLowerCase())) {
129
- return ['true', '1'].includes(value.toLowerCase())
130
- }
131
-
132
- if (targetType === 'array' || value.includes(',')) {
133
- return value.split(',').map(v => v.trim()).filter(Boolean)
134
- }
135
-
136
- // Try to parse as JSON for complex objects
137
- if (value.startsWith('{') || value.startsWith('[')) {
138
- try {
139
- return JSON.parse(value)
140
- } catch {
141
- // Fall back to string if JSON parsing fails
142
- }
143
- }
144
-
145
- return value
146
- }
147
-
148
- /**
149
- * Set nested object property using dot notation
150
- */
151
- function setNestedProperty(obj: any, path: string, value: any): void {
152
- const keys = path.split('.')
153
- let current = obj
154
-
155
- for (let i = 0; i < keys.length - 1; i++) {
156
- const key = keys[i]
157
- if (!(key in current) || typeof current[key] !== 'object') {
158
- current[key] = {}
159
- }
160
- current = current[key]
161
- }
162
-
163
- current[keys[keys.length - 1]] = value
164
- }
165
-
166
- /**
167
- * Get nested object property using dot notation
168
- */
169
- function getNestedProperty(obj: any, path: string): any {
170
- return path.split('.').reduce((current, key) => current?.[key], obj)
171
- }
172
-
173
- /**
174
- * Deep merge two configuration objects
175
- */
176
- function deepMerge(target: any, source: any): any {
177
- if (!source || typeof source !== 'object') return target
178
- if (!target || typeof target !== 'object') return source
179
-
180
- const result = { ...target }
181
-
182
- for (const key in source) {
183
- if (source.hasOwnProperty(key)) {
184
- if (Array.isArray(source[key])) {
185
- result[key] = [...source[key]]
186
- } else if (typeof source[key] === 'object' && source[key] !== null) {
187
- result[key] = deepMerge(target[key], source[key])
188
- } else {
189
- result[key] = source[key]
190
- }
191
- }
192
- }
193
-
194
- return result
195
- }
196
-
197
- /**
198
- * Load configuration from environment variables
199
- */
200
- function loadFromEnvironment(prefix = 'FLUXSTACK_'): Partial<FluxStackConfig> {
201
- const config: any = {}
202
-
203
- // Process known environment variable mappings
204
- for (const [envKey, configPath] of Object.entries(ENV_MAPPINGS)) {
205
- const envValue = process.env[envKey]
206
- if (envValue !== undefined && envValue !== '') {
207
- try {
208
- // Determine target type from config path
209
- let targetType = 'string'
210
- if (configPath.includes('port') || configPath.includes('maxAge') || configPath.includes('collectInterval') || configPath.includes('sampleRate')) {
211
- targetType = 'number'
212
- } else if (configPath.includes('origins') || configPath.includes('methods') || configPath.includes('headers') || configPath.includes('exporters') || configPath.includes('plugins.enabled') || configPath.includes('plugins.disabled')) {
213
- targetType = 'array'
214
- } else if (configPath.includes('enabled') || configPath.includes('credentials') || configPath.includes('minify') || configPath.includes('treeshake') || configPath.includes('compress') || configPath.includes('splitChunks') || configPath.includes('bundleAnalyzer') || configPath.includes('sourceMaps') || configPath.includes('clean')) {
215
- targetType = 'boolean'
216
- }
217
-
218
- const parsedValue = parseEnvValue(envValue, targetType)
219
- if (parsedValue !== undefined) {
220
- setNestedProperty(config, configPath, parsedValue)
221
- }
222
- } catch (error) {
223
- console.warn(`Failed to parse environment variable ${envKey}: ${error}`)
224
- }
225
- }
226
- }
227
-
228
- // Process custom environment variables with prefix
229
- for (const [key, value] of Object.entries(process.env)) {
230
- if (key.startsWith(prefix) && !ENV_MAPPINGS[key as keyof typeof ENV_MAPPINGS] && value !== undefined && value !== '') {
231
- const configKey = key.slice(prefix.length).toLowerCase().replace(/_/g, '.')
232
- try {
233
- const parsedValue = parseEnvValue(value!)
234
- if (parsedValue !== undefined) {
235
- if (!config.custom) config.custom = {}
236
- config.custom[configKey] = parsedValue
237
- }
238
- } catch (error) {
239
- console.warn(`Failed to parse custom environment variable ${key}: ${error}`)
240
- }
241
- }
242
- }
243
-
244
- return config
245
- }
246
-
247
- /**
248
- * Load configuration from file
249
- */
250
- async function loadFromFile(configPath: string): Promise<Partial<FluxStackConfig>> {
251
- if (!existsSync(configPath)) {
252
- throw new Error(`Configuration file not found: ${configPath}`)
253
- }
254
-
255
- try {
256
- // Dynamic import to support both .ts and .js files
257
- const configModule = await import(configPath)
258
- const config = configModule.default || configModule.config || configModule
259
-
260
- if (typeof config === 'function') {
261
- return config()
262
- }
263
-
264
- return config
265
- } catch (error) {
266
- throw new Error(`Failed to load configuration from ${configPath}: ${error}`)
267
- }
268
- }
269
-
270
- /**
271
- * Find configuration file in common locations
272
- */
273
- function findConfigFile(startDir = process.cwd()): string | null {
274
- const configNames = [
275
- 'fluxstack.config.ts',
276
- 'fluxstack.config.js',
277
- 'fluxstack.config.mjs',
278
- 'config/fluxstack.config.ts',
279
- 'config/fluxstack.config.js'
280
- ]
281
-
282
- for (const name of configNames) {
283
- const fullPath = join(startDir, name)
284
- if (existsSync(fullPath)) {
285
- return fullPath
286
- }
287
- }
288
-
289
- return null
290
- }
291
-
292
- /**
293
- * Apply environment-specific configuration
294
- */
295
- export function applyEnvironmentConfig(
296
- config: FluxStackConfig,
297
- environment: string
298
- ): FluxStackConfig {
299
- const envDefaults = environmentDefaults[environment as keyof typeof environmentDefaults]
300
- const envOverrides = config.environments?.[environment]
301
-
302
- let result = config
303
-
304
- // Apply environment defaults only for values that haven't been explicitly set
305
- if (envDefaults) {
306
- result = smartMerge(result, envDefaults)
307
- }
308
-
309
- // Apply environment-specific overrides from config
310
- if (envOverrides) {
311
- result = deepMerge(result, envOverrides)
312
- }
313
-
314
- return result
315
- }
316
-
317
- /**
318
- * Smart merge that only applies defaults for undefined values
319
- */
320
- function smartMerge(target: any, defaults: any): any {
321
- if (!defaults || typeof defaults !== 'object') return target
322
- if (!target || typeof target !== 'object') return defaults
323
-
324
- const result = { ...target }
325
-
326
- for (const key in defaults) {
327
- if (defaults.hasOwnProperty(key)) {
328
- if (target[key] === undefined) {
329
- // Value not set in target, use default
330
- result[key] = defaults[key]
331
- } else if (typeof defaults[key] === 'object' && defaults[key] !== null && !Array.isArray(defaults[key])) {
332
- // Recursively merge nested objects
333
- result[key] = smartMerge(target[key], defaults[key])
334
- }
335
- // Otherwise keep the target value (don't override)
336
- }
337
- }
338
-
339
- return result
340
- }
341
-
342
- /**
343
- * Main configuration loader
344
- */
345
- export async function loadConfig(options: ConfigLoadOptions = {}): Promise<ConfigLoadResult> {
346
- const {
347
- configPath,
348
- environment = process.env.NODE_ENV || 'development',
349
- envPrefix = 'FLUXSTACK_',
350
- validateSchema = true
351
- } = options
352
-
353
- const sources: string[] = []
354
- const warnings: string[] = []
355
- const errors: string[] = []
356
-
357
- try {
358
- // Start with default configuration
359
- let config: FluxStackConfig = JSON.parse(JSON.stringify(defaultFluxStackConfig))
360
- sources.push('defaults')
361
-
362
- // Load from configuration file
363
- let fileConfig: any = null
364
- const actualConfigPath = configPath || findConfigFile()
365
- if (actualConfigPath) {
366
- try {
367
- fileConfig = await loadFromFile(actualConfigPath)
368
- config = deepMerge(config, fileConfig)
369
- sources.push(`file:${actualConfigPath}`)
370
- } catch (error) {
371
- errors.push(`Failed to load config file: ${error}`)
372
- }
373
- } else if (configPath) {
374
- errors.push(`Specified config file not found: ${configPath}`)
375
- }
376
-
377
- // Load from environment variables
378
- const envConfig = loadFromEnvironment(envPrefix)
379
- if (Object.keys(envConfig).length > 0) {
380
- config = deepMerge(config, envConfig)
381
- sources.push('environment')
382
- }
383
-
384
- // Apply environment-specific configuration (only if no file config or env vars override)
385
- const envDefaults = environmentDefaults[environment as keyof typeof environmentDefaults]
386
- if (envDefaults) {
387
- // Apply environment defaults but don't override existing values
388
- config = smartMerge(config, envDefaults)
389
- sources.push(`environment:${environment}`)
390
- }
391
-
392
- // Validate configuration if requested
393
- if (validateSchema) {
394
- try {
395
- const { validateConfig } = await import('./validator')
396
- const validationResult = validateConfig(config)
397
-
398
- if (!validationResult.valid) {
399
- errors.push(...validationResult.errors)
400
- }
401
-
402
- warnings.push(...validationResult.warnings)
403
- } catch (error) {
404
- warnings.push(`Validation failed: ${error}`)
405
- }
406
- }
407
-
408
- return {
409
- config,
410
- sources,
411
- warnings,
412
- errors
413
- }
414
- } catch (error) {
415
- errors.push(`Configuration loading failed: ${error}`)
416
-
417
- return {
418
- config: defaultFluxStackConfig,
419
- sources: ['defaults'],
420
- warnings,
421
- errors
422
- }
423
- }
424
- }
425
-
426
- /**
427
- * Load configuration synchronously (limited functionality)
428
- */
429
- export function loadConfigSync(options: ConfigLoadOptions = {}): ConfigLoadResult {
430
- const {
431
- environment = process.env.NODE_ENV || 'development',
432
- envPrefix = 'FLUXSTACK_'
433
- } = options
434
-
435
- const sources: string[] = []
436
- const warnings: string[] = []
437
- const errors: string[] = []
438
-
439
- try {
440
- // Start with default configuration
441
- let config: FluxStackConfig = JSON.parse(JSON.stringify(defaultFluxStackConfig))
442
- sources.push('defaults')
443
-
444
- // Load from environment variables
445
- const envConfig = loadFromEnvironment(envPrefix)
446
- if (Object.keys(envConfig).length > 0) {
447
- config = deepMerge(config, envConfig)
448
- sources.push('environment')
449
- }
450
-
451
- // Apply environment-specific configuration
452
- const envDefaults = environmentDefaults[environment as keyof typeof environmentDefaults]
453
- if (envDefaults) {
454
- // Apply environment defaults first
455
- const configWithEnvDefaults = deepMerge(config, envDefaults)
456
-
457
- // Re-apply environment variables last (highest priority)
458
- if (Object.keys(envConfig).length > 0) {
459
- config = deepMerge(configWithEnvDefaults, envConfig)
460
- } else {
461
- config = configWithEnvDefaults
462
- }
463
-
464
- sources.push(`environment:${environment}`)
465
- } else if (environment !== 'development') {
466
- // Still add the environment source even if no defaults
467
- sources.push(`environment:${environment}`)
468
- }
469
-
470
- return {
471
- config,
472
- sources,
473
- warnings,
474
- errors
475
- }
476
- } catch (error) {
477
- errors.push(`Synchronous configuration loading failed: ${error}`)
478
-
479
- return {
480
- config: defaultFluxStackConfig,
481
- sources: ['defaults'],
482
- warnings,
483
- errors
484
- }
485
- }
486
- }
487
-
488
- /**
489
- * Get configuration value using dot notation
490
- */
491
- export function getConfigValue<T = any>(config: FluxStackConfig, path: string): T | undefined
492
- export function getConfigValue<T = any>(config: FluxStackConfig, path: string, defaultValue: T): T
493
- export function getConfigValue<T = any>(config: FluxStackConfig, path: string, defaultValue?: T): T | undefined {
494
- const value = getNestedProperty(config, path)
495
- return value !== undefined ? value : defaultValue
496
- }
497
-
498
- /**
499
- * Check if configuration has a specific value
500
- */
501
- export function hasConfigValue(config: FluxStackConfig, path: string): boolean {
502
- return getNestedProperty(config, path) !== undefined
503
- }
504
-
505
- /**
506
- * Create a configuration subset for a specific plugin or module
507
- */
508
- export function createConfigSubset(
509
- config: FluxStackConfig,
510
- paths: string[]
511
- ): Record<string, any> {
512
- const subset: Record<string, any> = {}
513
-
514
- for (const path of paths) {
515
- const value = getNestedProperty(config, path)
516
- if (value !== undefined) {
517
- setNestedProperty(subset, path, value)
518
- }
519
- }
520
-
521
- return subset
522
- }