create-fluxstack 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.env.example +29 -29
  2. package/app/client/README.md +69 -69
  3. package/app/client/index.html +14 -13
  4. package/app/client/src/App.tsx +157 -524
  5. package/app/client/src/components/ErrorBoundary.tsx +107 -0
  6. package/app/client/src/components/ErrorDisplay.css +365 -0
  7. package/app/client/src/components/ErrorDisplay.tsx +258 -0
  8. package/app/client/src/components/FluxStackConfig.tsx +1321 -0
  9. package/app/client/src/components/HybridLiveCounter.tsx +140 -0
  10. package/app/client/src/components/LiveClock.tsx +286 -0
  11. package/app/client/src/components/MainLayout.tsx +390 -0
  12. package/app/client/src/components/SidebarNavigation.tsx +391 -0
  13. package/app/client/src/components/StateDemo.tsx +178 -0
  14. package/app/client/src/components/SystemMonitor.tsx +1038 -0
  15. package/app/client/src/components/Teste.tsx +104 -0
  16. package/app/client/src/components/UserProfile.tsx +809 -0
  17. package/app/client/src/hooks/useAuth.ts +39 -0
  18. package/app/client/src/hooks/useNotifications.ts +56 -0
  19. package/app/client/src/lib/eden-api.ts +189 -53
  20. package/app/client/src/lib/errors.ts +340 -0
  21. package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
  22. package/app/client/src/lib/index.ts +45 -0
  23. package/app/client/src/main.tsx +3 -2
  24. package/app/client/src/pages/ApiDocs.tsx +182 -0
  25. package/app/client/src/pages/Demo.tsx +174 -0
  26. package/app/client/src/pages/HybridLive.tsx +263 -0
  27. package/app/client/src/pages/Overview.tsx +155 -0
  28. package/app/client/src/store/README.md +43 -0
  29. package/app/client/src/store/index.ts +16 -0
  30. package/app/client/src/store/slices/uiSlice.ts +151 -0
  31. package/app/client/src/store/slices/userSlice.ts +161 -0
  32. package/app/client/src/test/README.md +257 -0
  33. package/app/client/src/test/setup.ts +70 -0
  34. package/app/client/src/test/types.ts +12 -0
  35. package/app/client/src/vite-env.d.ts +1 -1
  36. package/app/client/tsconfig.app.json +44 -43
  37. package/app/client/tsconfig.json +7 -7
  38. package/app/client/tsconfig.node.json +25 -25
  39. package/app/client/zustand-setup.md +65 -0
  40. package/app/server/controllers/users.controller.ts +68 -68
  41. package/app/server/index.ts +9 -1
  42. package/app/server/live/CounterComponent.ts +191 -0
  43. package/app/server/live/FluxStackConfig.ts +529 -0
  44. package/app/server/live/LiveClockComponent.ts +214 -0
  45. package/app/server/live/SidebarNavigation.ts +156 -0
  46. package/app/server/live/SystemMonitor.ts +594 -0
  47. package/app/server/live/SystemMonitorIntegration.ts +151 -0
  48. package/app/server/live/TesteComponent.ts +87 -0
  49. package/app/server/live/UserProfileComponent.ts +135 -0
  50. package/app/server/live/register-components.ts +28 -0
  51. package/app/server/middleware/auth.ts +136 -0
  52. package/app/server/middleware/errorHandling.ts +250 -0
  53. package/app/server/middleware/index.ts +10 -0
  54. package/app/server/middleware/rateLimit.ts +193 -0
  55. package/app/server/middleware/requestLogging.ts +215 -0
  56. package/app/server/middleware/validation.ts +270 -0
  57. package/app/server/routes/index.ts +14 -2
  58. package/app/server/routes/upload.ts +92 -0
  59. package/app/server/routes/users.routes.ts +2 -9
  60. package/app/server/services/NotificationService.ts +302 -0
  61. package/app/server/services/UserService.ts +222 -0
  62. package/app/server/services/index.ts +46 -0
  63. package/core/cli/commands/plugin-deps.ts +263 -0
  64. package/core/cli/generators/README.md +339 -0
  65. package/core/cli/generators/component.ts +770 -0
  66. package/core/cli/generators/controller.ts +299 -0
  67. package/core/cli/generators/index.ts +144 -0
  68. package/core/cli/generators/interactive.ts +228 -0
  69. package/core/cli/generators/prompts.ts +83 -0
  70. package/core/cli/generators/route.ts +513 -0
  71. package/core/cli/generators/service.ts +465 -0
  72. package/core/cli/generators/template-engine.ts +154 -0
  73. package/core/cli/generators/types.ts +71 -0
  74. package/core/cli/generators/utils.ts +192 -0
  75. package/core/cli/index.ts +69 -0
  76. package/core/cli/plugin-discovery.ts +16 -85
  77. package/core/client/fluxstack.ts +17 -0
  78. package/core/client/hooks/index.ts +7 -0
  79. package/core/client/hooks/state-validator.ts +130 -0
  80. package/core/client/hooks/useAuth.ts +49 -0
  81. package/core/client/hooks/useChunkedUpload.ts +258 -0
  82. package/core/client/hooks/useHybridLiveComponent.ts +967 -0
  83. package/core/client/hooks/useWebSocket.ts +373 -0
  84. package/core/client/index.ts +47 -0
  85. package/core/client/state/createStore.ts +193 -0
  86. package/core/client/state/index.ts +15 -0
  87. package/core/config/env-dynamic.ts +1 -1
  88. package/core/config/env.ts +2 -1
  89. package/core/config/runtime-config.ts +3 -3
  90. package/core/config/schema.ts +84 -49
  91. package/core/framework/server.ts +30 -0
  92. package/core/index.ts +25 -0
  93. package/core/live/ComponentRegistry.ts +399 -0
  94. package/core/live/types.ts +164 -0
  95. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
  96. package/core/plugins/built-in/live-components/index.ts +27 -0
  97. package/core/plugins/built-in/logger/index.ts +1 -1
  98. package/core/plugins/built-in/monitoring/index.ts +1 -1
  99. package/core/plugins/built-in/static/index.ts +1 -1
  100. package/core/plugins/built-in/swagger/index.ts +1 -1
  101. package/core/plugins/built-in/vite/index.ts +1 -1
  102. package/core/plugins/dependency-manager.ts +384 -0
  103. package/core/plugins/index.ts +5 -1
  104. package/core/plugins/manager.ts +7 -3
  105. package/core/plugins/registry.ts +88 -10
  106. package/core/plugins/types.ts +11 -11
  107. package/core/server/framework.ts +43 -0
  108. package/core/server/index.ts +11 -1
  109. package/core/server/live/ComponentRegistry.ts +1017 -0
  110. package/core/server/live/FileUploadManager.ts +272 -0
  111. package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
  112. package/core/server/live/SingleConnectionManager.ts +0 -0
  113. package/core/server/live/StateSignature.ts +644 -0
  114. package/core/server/live/WebSocketConnectionManager.ts +688 -0
  115. package/core/server/live/websocket-plugin.ts +435 -0
  116. package/core/server/middleware/errorHandling.ts +141 -0
  117. package/core/server/middleware/index.ts +16 -0
  118. package/core/server/plugins/static-files-plugin.ts +232 -0
  119. package/core/server/services/BaseService.ts +95 -0
  120. package/core/server/services/ServiceContainer.ts +144 -0
  121. package/core/server/services/index.ts +9 -0
  122. package/core/templates/create-project.ts +196 -33
  123. package/core/testing/index.ts +10 -0
  124. package/core/testing/setup.ts +74 -0
  125. package/core/types/build.ts +38 -14
  126. package/core/types/types.ts +319 -0
  127. package/core/utils/env-runtime.ts +7 -0
  128. package/core/utils/errors/handlers.ts +264 -39
  129. package/core/utils/errors/index.ts +528 -18
  130. package/core/utils/errors/middleware.ts +114 -0
  131. package/core/utils/logger/formatters.ts +222 -0
  132. package/core/utils/logger/index.ts +167 -48
  133. package/core/utils/logger/middleware.ts +253 -0
  134. package/core/utils/logger/performance.ts +384 -0
  135. package/core/utils/logger/transports.ts +365 -0
  136. package/create-fluxstack.ts +296 -296
  137. package/fluxstack.config.ts +17 -1
  138. package/package-template.json +66 -66
  139. package/package.json +31 -6
  140. package/public/README.md +16 -0
  141. package/vite.config.ts +29 -14
  142. package/.claude/settings.local.json +0 -74
  143. package/.github/workflows/ci-build-tests.yml +0 -480
  144. package/.github/workflows/dependency-management.yml +0 -324
  145. package/.github/workflows/release-validation.yml +0 -355
  146. package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
  147. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
  148. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
  149. package/CLAUDE.md +0 -200
  150. package/Dockerfile +0 -58
  151. package/Dockerfile.backend +0 -52
  152. package/Dockerfile.frontend +0 -54
  153. package/README-Docker.md +0 -85
  154. package/ai-context/00-QUICK-START.md +0 -86
  155. package/ai-context/README.md +0 -88
  156. package/ai-context/development/eden-treaty-guide.md +0 -362
  157. package/ai-context/development/patterns.md +0 -382
  158. package/ai-context/development/plugins-guide.md +0 -572
  159. package/ai-context/examples/crud-complete.md +0 -626
  160. package/ai-context/project/architecture.md +0 -399
  161. package/ai-context/project/overview.md +0 -213
  162. package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
  163. package/ai-context/recent-changes/type-inference-fix.md +0 -223
  164. package/ai-context/reference/environment-vars.md +0 -384
  165. package/ai-context/reference/troubleshooting.md +0 -407
  166. package/app/client/src/components/TestPage.tsx +0 -453
  167. package/bun.lock +0 -1063
  168. package/bunfig.toml +0 -16
  169. package/core/__tests__/integration.test.ts +0 -227
  170. package/core/build/index.ts +0 -186
  171. package/core/config/__tests__/config-loader.test.ts +0 -554
  172. package/core/config/__tests__/config-merger.test.ts +0 -657
  173. package/core/config/__tests__/env-converter.test.ts +0 -372
  174. package/core/config/__tests__/env-processor.test.ts +0 -431
  175. package/core/config/__tests__/env.test.ts +0 -452
  176. package/core/config/__tests__/integration.test.ts +0 -418
  177. package/core/config/__tests__/loader.test.ts +0 -331
  178. package/core/config/__tests__/schema.test.ts +0 -129
  179. package/core/config/__tests__/validator.test.ts +0 -318
  180. package/core/framework/__tests__/server.test.ts +0 -233
  181. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  182. package/core/plugins/__tests__/manager.test.ts +0 -398
  183. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  184. package/core/plugins/__tests__/registry.test.ts +0 -335
  185. package/core/utils/__tests__/errors.test.ts +0 -139
  186. package/core/utils/__tests__/helpers.test.ts +0 -297
  187. package/core/utils/__tests__/logger.test.ts +0 -141
  188. package/create-test-app.ts +0 -156
  189. package/docker-compose.microservices.yml +0 -75
  190. package/docker-compose.simple.yml +0 -57
  191. package/docker-compose.yml +0 -71
  192. package/eslint.config.js +0 -23
  193. package/flux-cli.ts +0 -214
  194. package/nginx-lb.conf +0 -37
  195. package/publish.sh +0 -63
  196. package/run-clean.ts +0 -26
  197. package/run-env-tests.ts +0 -313
  198. package/tailwind.config.js +0 -34
  199. package/tests/__mocks__/api.ts +0 -56
  200. package/tests/fixtures/users.ts +0 -69
  201. package/tests/integration/api/users.routes.test.ts +0 -221
  202. package/tests/setup.ts +0 -29
  203. package/tests/unit/app/client/App-simple.test.tsx +0 -56
  204. package/tests/unit/app/client/App.test.tsx.skip +0 -237
  205. package/tests/unit/app/client/eden-api.test.ts +0 -186
  206. package/tests/unit/app/client/simple.test.tsx +0 -23
  207. package/tests/unit/app/controllers/users.controller.test.ts +0 -150
  208. package/tests/unit/core/create-project.test.ts.skip +0 -95
  209. package/tests/unit/core/framework.test.ts +0 -144
  210. package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
  211. package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
  212. package/tests/utils/test-helpers.ts +0 -61
  213. package/vitest.config.ts +0 -50
  214. package/workspace.json +0 -6
@@ -1,657 +0,0 @@
1
- /**
2
- * Tests for ConfigMerger and EnvironmentConfigApplier
3
- * Tests configuration merging with precedence and environment-specific configs
4
- */
5
-
6
- import { describe, test, expect } from 'vitest'
7
- import {
8
- ConfigMerger,
9
- EnvironmentConfigApplier
10
- } from '../env'
11
- import type { FluxStackConfig } from '../schema'
12
-
13
- describe('ConfigMerger', () => {
14
- let merger: ConfigMerger
15
-
16
- beforeEach(() => {
17
- merger = new ConfigMerger()
18
- })
19
-
20
- describe('merge', () => {
21
- test('merges simple configurations', () => {
22
- const config1 = {
23
- config: {
24
- app: { name: 'TestApp', version: '1.0.0' },
25
- server: { port: 3000 }
26
- } as Partial<FluxStackConfig>,
27
- source: 'default'
28
- }
29
-
30
- const config2 = {
31
- config: {
32
- app: { version: '2.0.0' },
33
- server: { host: 'localhost' }
34
- } as Partial<FluxStackConfig>,
35
- source: 'file'
36
- }
37
-
38
- const result = merger.merge(config1, config2)
39
-
40
- expect(result.app?.name).toBe('TestApp') // from config1
41
- expect(result.app?.version).toBe('2.0.0') // overridden by config2
42
- expect(result.server?.port).toBe(3000) // from config1
43
- expect(result.server?.host).toBe('localhost') // from config2
44
- })
45
-
46
- test('respects precedence order', () => {
47
- const defaultConfig = {
48
- config: {
49
- server: { port: 3000, host: 'localhost' }
50
- } as Partial<FluxStackConfig>,
51
- source: 'default'
52
- }
53
-
54
- const fileConfig = {
55
- config: {
56
- server: { port: 4000 }
57
- } as Partial<FluxStackConfig>,
58
- source: 'file'
59
- }
60
-
61
- const envConfig = {
62
- config: {
63
- server: { port: 5000 }
64
- } as Partial<FluxStackConfig>,
65
- source: 'environment'
66
- }
67
-
68
- const overrideConfig = {
69
- config: {
70
- server: { port: 6000 }
71
- } as Partial<FluxStackConfig>,
72
- source: 'override'
73
- }
74
-
75
- const result = merger.merge(defaultConfig, fileConfig, envConfig, overrideConfig)
76
-
77
- // Override should win (highest precedence)
78
- expect(result.server?.port).toBe(6000)
79
- expect(result.server?.host).toBe('localhost') // from default (not overridden)
80
- })
81
-
82
- test('handles nested object merging', () => {
83
- const config1 = {
84
- config: {
85
- server: {
86
- cors: {
87
- origins: ['http://localhost:3000'],
88
- methods: ['GET', 'POST'],
89
- credentials: true
90
- }
91
- }
92
- } as Partial<FluxStackConfig>,
93
- source: 'default'
94
- }
95
-
96
- const config2 = {
97
- config: {
98
- server: {
99
- cors: {
100
- origins: ['http://localhost:5173'],
101
- headers: ['Content-Type']
102
- }
103
- }
104
- } as Partial<FluxStackConfig>,
105
- source: 'environment'
106
- }
107
-
108
- const result = merger.merge(config1, config2)
109
-
110
- expect(result.server?.cors?.origins).toEqual(['http://localhost:5173']) // overridden
111
- expect(result.server?.cors?.methods).toEqual(['GET', 'POST']) // preserved
112
- expect(result.server?.cors?.headers).toEqual(['Content-Type']) // added
113
- expect(result.server?.cors?.credentials).toBe(true) // preserved
114
- })
115
-
116
- test('handles array replacement (not merging)', () => {
117
- const config1 = {
118
- config: {
119
- plugins: {
120
- enabled: ['plugin1', 'plugin2', 'plugin3']
121
- }
122
- } as Partial<FluxStackConfig>,
123
- source: 'default'
124
- }
125
-
126
- const config2 = {
127
- config: {
128
- plugins: {
129
- enabled: ['plugin4', 'plugin5']
130
- }
131
- } as Partial<FluxStackConfig>,
132
- source: 'environment'
133
- }
134
-
135
- const result = merger.merge(config1, config2)
136
-
137
- // Arrays should be replaced, not merged
138
- expect(result.plugins?.enabled).toEqual(['plugin4', 'plugin5'])
139
- })
140
-
141
- test('handles null and undefined values', () => {
142
- const config1 = {
143
- config: {
144
- database: {
145
- host: 'localhost',
146
- port: 5432,
147
- ssl: true
148
- }
149
- } as Partial<FluxStackConfig>,
150
- source: 'default'
151
- }
152
-
153
- const config2 = {
154
- config: {
155
- database: {
156
- port: null,
157
- ssl: undefined
158
- }
159
- } as any,
160
- source: 'environment'
161
- }
162
-
163
- const result = merger.merge(config1, config2)
164
-
165
- expect(result.database?.host).toBe('localhost') // preserved
166
- expect(result.database?.port).toBe(null) // overridden with null
167
- expect(result.database?.ssl).toBe(true) // undefined doesn't override
168
- })
169
-
170
- test('merges complex nested structures', () => {
171
- const config1 = {
172
- config: {
173
- monitoring: {
174
- enabled: true,
175
- metrics: {
176
- enabled: true,
177
- collectInterval: 5000,
178
- httpMetrics: true,
179
- systemMetrics: false
180
- },
181
- profiling: {
182
- enabled: false,
183
- sampleRate: 0.1
184
- }
185
- }
186
- } as Partial<FluxStackConfig>,
187
- source: 'default'
188
- }
189
-
190
- const config2 = {
191
- config: {
192
- monitoring: {
193
- metrics: {
194
- collectInterval: 10000,
195
- systemMetrics: true,
196
- customMetrics: true
197
- },
198
- profiling: {
199
- enabled: true,
200
- memoryProfiling: true
201
- }
202
- }
203
- } as Partial<FluxStackConfig>,
204
- source: 'environment'
205
- }
206
-
207
- const result = merger.merge(config1, config2)
208
-
209
- expect(result.monitoring?.enabled).toBe(true) // from config1
210
- expect(result.monitoring?.metrics?.enabled).toBe(true) // from config1
211
- expect(result.monitoring?.metrics?.collectInterval).toBe(10000) // from config2
212
- expect(result.monitoring?.metrics?.httpMetrics).toBe(true) // from config1
213
- expect(result.monitoring?.metrics?.systemMetrics).toBe(true) // from config2
214
- expect((result.monitoring?.metrics as any)?.customMetrics).toBe(true) // from config2
215
- expect(result.monitoring?.profiling?.enabled).toBe(true) // from config2
216
- expect(result.monitoring?.profiling?.sampleRate).toBe(0.1) // from config1
217
- expect((result.monitoring?.profiling as any)?.memoryProfiling).toBe(true) // from config2
218
- })
219
-
220
- test('handles empty configurations', () => {
221
- const emptyConfig = {
222
- config: {} as Partial<FluxStackConfig>,
223
- source: 'default'
224
- }
225
-
226
- const config2 = {
227
- config: {
228
- app: { name: 'TestApp' }
229
- } as Partial<FluxStackConfig>,
230
- source: 'file'
231
- }
232
-
233
- const result = merger.merge(emptyConfig, config2)
234
-
235
- expect(result.app?.name).toBe('TestApp')
236
- })
237
-
238
- test('precedence works with same source priority', () => {
239
- const config1 = {
240
- config: {
241
- server: { port: 3000 }
242
- } as Partial<FluxStackConfig>,
243
- source: 'file'
244
- }
245
-
246
- const config2 = {
247
- config: {
248
- server: { port: 4000 }
249
- } as Partial<FluxStackConfig>,
250
- source: 'file'
251
- }
252
-
253
- const result = merger.merge(config1, config2)
254
-
255
- // Later config should win when precedence is equal
256
- expect(result.server?.port).toBe(4000)
257
- })
258
- })
259
- })
260
-
261
- describe('EnvironmentConfigApplier', () => {
262
- let applier: EnvironmentConfigApplier
263
-
264
- beforeEach(() => {
265
- applier = new EnvironmentConfigApplier()
266
- })
267
-
268
- describe('applyEnvironmentConfig', () => {
269
- test('applies environment-specific configuration', () => {
270
- const baseConfig: FluxStackConfig = {
271
- app: { name: 'TestApp', version: '1.0.0' },
272
- server: {
273
- port: 3000,
274
- host: 'localhost',
275
- apiPrefix: '/api',
276
- cors: {
277
- origins: ['*'],
278
- methods: ['GET', 'POST'],
279
- headers: ['Content-Type'],
280
- credentials: false,
281
- maxAge: 86400
282
- },
283
- middleware: []
284
- },
285
- client: {
286
- port: 5173,
287
- proxy: { target: 'http://localhost:3000' },
288
- build: {
289
- target: 'es2020',
290
- outDir: 'dist/client',
291
- sourceMaps: true,
292
- minify: false
293
- }
294
- },
295
- build: {
296
- target: 'bun',
297
- outDir: 'dist',
298
- clean: true,
299
- optimization: {
300
- minify: false,
301
- compress: false,
302
- treeshake: false,
303
- splitChunks: false,
304
- bundleAnalyzer: false
305
- },
306
- sourceMaps: true
307
- },
308
- logging: {
309
- level: 'info',
310
- format: 'pretty',
311
- transports: [
312
- { type: 'console', level: 'info', format: 'pretty' }
313
- ]
314
- },
315
- monitoring: {
316
- enabled: false,
317
- metrics: {
318
- enabled: false,
319
- collectInterval: 60000,
320
- httpMetrics: true,
321
- systemMetrics: true,
322
- customMetrics: false
323
- },
324
- profiling: {
325
- enabled: false,
326
- sampleRate: 0.1,
327
- memoryProfiling: false,
328
- cpuProfiling: false
329
- },
330
- exporters: []
331
- },
332
- plugins: {
333
- enabled: [],
334
- disabled: [],
335
- config: {}
336
- },
337
- environments: {
338
- production: {
339
- logging: {
340
- level: 'warn',
341
- format: 'json'
342
- },
343
- build: {
344
- optimization: {
345
- minify: true,
346
- compress: true,
347
- treeshake: true
348
- },
349
- sourceMaps: false
350
- },
351
- monitoring: {
352
- enabled: true,
353
- metrics: {
354
- enabled: true,
355
- collectInterval: 30000
356
- }
357
- }
358
- },
359
- development: {
360
- logging: {
361
- level: 'debug'
362
- },
363
- monitoring: {
364
- enabled: false
365
- }
366
- }
367
- }
368
- } as FluxStackConfig
369
-
370
- const result = applier.applyEnvironmentConfig(baseConfig, 'production')
371
-
372
- expect(result.logging?.level).toBe('warn') // overridden
373
- expect(result.logging?.format).toBe('json') // overridden
374
- expect(result.build?.optimization?.minify).toBe(true) // overridden
375
- expect(result.build?.optimization?.compress).toBe(true) // overridden
376
- expect(result.build?.optimization?.treeshake).toBe(true) // overridden
377
- expect(result.build?.sourceMaps).toBe(false) // overridden
378
- expect(result.monitoring?.enabled).toBe(true) // overridden
379
- expect(result.monitoring?.metrics?.enabled).toBe(true) // overridden
380
- expect(result.monitoring?.metrics?.collectInterval).toBe(30000) // overridden
381
-
382
- // Original values should be preserved where not overridden
383
- expect(result.app?.name).toBe('TestApp')
384
- expect(result.server?.port).toBe(3000)
385
- })
386
-
387
- test('applies development environment configuration', () => {
388
- const baseConfig: FluxStackConfig = {
389
- app: { name: 'TestApp', version: '1.0.0' },
390
- server: {
391
- port: 3000,
392
- host: 'localhost',
393
- apiPrefix: '/api',
394
- cors: {
395
- origins: ['*'],
396
- methods: ['GET', 'POST'],
397
- headers: ['Content-Type'],
398
- credentials: false,
399
- maxAge: 86400
400
- },
401
- middleware: []
402
- },
403
- client: {
404
- port: 5173,
405
- proxy: { target: 'http://localhost:3000' },
406
- build: {
407
- target: 'es2020',
408
- outDir: 'dist/client',
409
- sourceMaps: true,
410
- minify: false
411
- }
412
- },
413
- build: {
414
- target: 'bun',
415
- outDir: 'dist',
416
- clean: true,
417
- optimization: {
418
- minify: false,
419
- compress: false,
420
- treeshake: false,
421
- splitChunks: false,
422
- bundleAnalyzer: false
423
- },
424
- sourceMaps: true
425
- },
426
- logging: {
427
- level: 'info',
428
- format: 'pretty',
429
- transports: [
430
- { type: 'console', level: 'info', format: 'pretty' }
431
- ]
432
- },
433
- monitoring: {
434
- enabled: true,
435
- metrics: {
436
- enabled: false,
437
- collectInterval: 60000,
438
- httpMetrics: true,
439
- systemMetrics: true,
440
- customMetrics: false
441
- },
442
- profiling: {
443
- enabled: false,
444
- sampleRate: 0.1,
445
- memoryProfiling: false,
446
- cpuProfiling: false
447
- },
448
- exporters: []
449
- },
450
- plugins: {
451
- enabled: [],
452
- disabled: [],
453
- config: {}
454
- },
455
- environments: {
456
- development: {
457
- logging: {
458
- level: 'debug'
459
- },
460
- monitoring: {
461
- enabled: false
462
- }
463
- }
464
- }
465
- } as FluxStackConfig
466
-
467
- const result = applier.applyEnvironmentConfig(baseConfig, 'development')
468
-
469
- expect(result.logging?.level).toBe('debug') // overridden
470
- expect(result.monitoring?.enabled).toBe(false) // overridden
471
- expect(result.app?.name).toBe('TestApp') // preserved
472
- })
473
-
474
- test('returns original config when environment not found', () => {
475
- const baseConfig: FluxStackConfig = {
476
- app: { name: 'TestApp', version: '1.0.0' },
477
- server: {
478
- port: 3000,
479
- host: 'localhost',
480
- apiPrefix: '/api',
481
- cors: {
482
- origins: ['*'],
483
- methods: ['GET', 'POST'],
484
- headers: ['Content-Type'],
485
- credentials: false,
486
- maxAge: 86400
487
- },
488
- middleware: []
489
- },
490
- client: {
491
- port: 5173,
492
- proxy: { target: 'http://localhost:3000' },
493
- build: {
494
- target: 'es2020',
495
- outDir: 'dist/client',
496
- sourceMaps: true,
497
- minify: false
498
- }
499
- },
500
- build: {
501
- target: 'bun',
502
- outDir: 'dist',
503
- clean: true,
504
- optimization: {
505
- minify: false,
506
- compress: false,
507
- treeshake: false,
508
- splitChunks: false,
509
- bundleAnalyzer: false
510
- },
511
- sourceMaps: true
512
- },
513
- logging: {
514
- level: 'info',
515
- format: 'pretty',
516
- transports: [
517
- { type: 'console', level: 'info', format: 'pretty' }
518
- ]
519
- },
520
- monitoring: {
521
- enabled: false,
522
- metrics: {
523
- enabled: false,
524
- collectInterval: 60000,
525
- httpMetrics: true,
526
- systemMetrics: true,
527
- customMetrics: false
528
- },
529
- profiling: {
530
- enabled: false,
531
- sampleRate: 0.1,
532
- memoryProfiling: false,
533
- cpuProfiling: false
534
- },
535
- exporters: []
536
- },
537
- plugins: {
538
- enabled: [],
539
- disabled: [],
540
- config: {}
541
- }
542
- } as FluxStackConfig
543
-
544
- const result = applier.applyEnvironmentConfig(baseConfig, 'nonexistent')
545
-
546
- expect(result).toBe(baseConfig) // Should return the same object
547
- })
548
- })
549
-
550
- describe('getAvailableEnvironments', () => {
551
- test('returns available environments', () => {
552
- const config = {
553
- environments: {
554
- development: {},
555
- production: {},
556
- staging: {},
557
- test: {}
558
- }
559
- } as FluxStackConfig
560
-
561
- const environments = applier.getAvailableEnvironments(config)
562
-
563
- expect(environments).toEqual(['development', 'production', 'staging', 'test'])
564
- })
565
-
566
- test('returns empty array when no environments defined', () => {
567
- const config = {} as FluxStackConfig
568
-
569
- const environments = applier.getAvailableEnvironments(config)
570
-
571
- expect(environments).toEqual([])
572
- })
573
- })
574
-
575
- describe('validateEnvironmentConfig', () => {
576
- test('validates production environment requirements', () => {
577
- const config = {
578
- server: { port: 3000 },
579
- logging: { level: 'info' as const },
580
- monitoring: { enabled: false },
581
- environments: {
582
- production: {
583
- logging: { level: 'debug' as const }, // Invalid for production
584
- monitoring: { enabled: false } // Invalid for production
585
- }
586
- }
587
- } as FluxStackConfig
588
-
589
- const result = applier.validateEnvironmentConfig(config, 'production')
590
-
591
- expect(result.valid).toBe(false)
592
- expect(result.errors).toContain('Production environment should not use debug logging')
593
- expect(result.errors).toContain('Production environment should enable monitoring')
594
- })
595
-
596
- test('validates port conflicts', () => {
597
- const config = {
598
- server: { port: 3000 },
599
- environments: {
600
- staging: {
601
- server: { port: 3000 } // Same as base - conflict
602
- }
603
- }
604
- } as FluxStackConfig
605
-
606
- const result = applier.validateEnvironmentConfig(config, 'staging')
607
-
608
- expect(result.valid).toBe(false)
609
- expect(result.errors).toContain('Environment staging uses same port as base configuration')
610
- })
611
-
612
- test('allows port conflicts in development', () => {
613
- const config = {
614
- server: { port: 3000 },
615
- environments: {
616
- development: {
617
- server: { port: 3000 } // Same as base - allowed in development
618
- }
619
- }
620
- } as FluxStackConfig
621
-
622
- const result = applier.validateEnvironmentConfig(config, 'development')
623
-
624
- expect(result.valid).toBe(true)
625
- expect(result.errors).toHaveLength(0)
626
- })
627
-
628
- test('passes validation for valid production config', () => {
629
- const config = {
630
- server: { port: 3000 },
631
- logging: { level: 'info' as const },
632
- monitoring: { enabled: false },
633
- environments: {
634
- production: {
635
- server: { port: 8080 }, // Different port
636
- logging: { level: 'warn' as const }, // Valid for production
637
- monitoring: { enabled: true } // Valid for production
638
- }
639
- }
640
- } as FluxStackConfig
641
-
642
- const result = applier.validateEnvironmentConfig(config, 'production')
643
-
644
- expect(result.valid).toBe(true)
645
- expect(result.errors).toHaveLength(0)
646
- })
647
-
648
- test('returns valid for non-existent environment', () => {
649
- const config = {} as FluxStackConfig
650
-
651
- const result = applier.validateEnvironmentConfig(config, 'nonexistent')
652
-
653
- expect(result.valid).toBe(true)
654
- expect(result.errors).toHaveLength(0)
655
- })
656
- })
657
- })