create-fluxstack 1.1.0 → 1.4.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 (62) hide show
  1. package/app/server/backend-only.ts +5 -5
  2. package/app/server/index.ts +63 -54
  3. package/app/server/live/FluxStackConfig.ts +43 -39
  4. package/app/server/live/SystemMonitorIntegration.ts +2 -2
  5. package/app/server/live/register-components.ts +1 -1
  6. package/app/server/middleware/errorHandling.ts +6 -4
  7. package/app/server/routes/config.ts +145 -0
  8. package/app/server/routes/index.ts +5 -3
  9. package/config/app.config.ts +113 -0
  10. package/config/build.config.ts +24 -0
  11. package/config/database.config.ts +99 -0
  12. package/config/index.ts +68 -0
  13. package/config/logger.config.ts +27 -0
  14. package/config/runtime.config.ts +92 -0
  15. package/config/server.config.ts +46 -0
  16. package/config/services.config.ts +130 -0
  17. package/config/system.config.ts +105 -0
  18. package/core/build/index.ts +10 -4
  19. package/core/cli/index.ts +29 -12
  20. package/core/config/env.ts +37 -95
  21. package/core/config/runtime-config.ts +61 -58
  22. package/core/config/schema.ts +4 -0
  23. package/core/framework/server.ts +22 -10
  24. package/core/plugins/built-in/index.ts +7 -17
  25. package/core/plugins/built-in/swagger/index.ts +228 -228
  26. package/core/plugins/built-in/vite/index.ts +374 -358
  27. package/core/plugins/dependency-manager.ts +5 -5
  28. package/core/plugins/manager.ts +12 -12
  29. package/core/plugins/registry.ts +3 -3
  30. package/core/server/index.ts +0 -1
  31. package/core/server/live/ComponentRegistry.ts +34 -8
  32. package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
  33. package/core/server/live/websocket-plugin.ts +434 -434
  34. package/core/server/middleware/README.md +488 -0
  35. package/core/server/middleware/elysia-helpers.ts +227 -0
  36. package/core/server/middleware/index.ts +25 -9
  37. package/core/server/plugins/static-files-plugin.ts +231 -231
  38. package/core/utils/config-schema.ts +484 -0
  39. package/core/utils/env.ts +306 -0
  40. package/core/utils/helpers.ts +4 -4
  41. package/core/utils/logger/colors.ts +114 -0
  42. package/core/utils/logger/config.ts +35 -0
  43. package/core/utils/logger/formatter.ts +82 -0
  44. package/core/utils/logger/group-logger.ts +101 -0
  45. package/core/utils/logger/index.ts +199 -250
  46. package/core/utils/logger/stack-trace.ts +92 -0
  47. package/core/utils/logger/startup-banner.ts +92 -0
  48. package/core/utils/logger/winston-logger.ts +152 -0
  49. package/core/utils/version.ts +5 -0
  50. package/create-fluxstack.ts +1 -0
  51. package/fluxstack.config.ts +2 -2
  52. package/package.json +117 -115
  53. package/core/config/env-dynamic.ts +0 -326
  54. package/core/plugins/built-in/logger/index.ts +0 -180
  55. package/core/server/plugins/logger.ts +0 -47
  56. package/core/utils/env-runtime-v2.ts +0 -232
  57. package/core/utils/env-runtime.ts +0 -259
  58. package/core/utils/logger/formatters.ts +0 -222
  59. package/core/utils/logger/middleware.ts +0 -253
  60. package/core/utils/logger/performance.ts +0 -384
  61. package/core/utils/logger/transports.ts +0 -365
  62. package/core/utils/logger.ts +0 -106
@@ -1,15 +1,15 @@
1
1
  // Backend standalone entry point
2
2
  import { startBackendOnly } from "@/core/server/standalone"
3
3
  import { apiRoutes } from "./routes"
4
- import { env } from "@/core/utils/env-runtime"
4
+ import { serverConfig } from "@/config/server.config"
5
5
 
6
- // Configuração para backend standalone com env dinâmico
6
+ // Configuração para backend standalone usando config declarativo
7
7
  const backendConfig = {
8
- port: env.get('BACKEND_PORT', 3001), // Casting automático para number
9
- apiPrefix: env.API_PREFIX // Direto! (string)
8
+ port: serverConfig.backendPort,
9
+ apiPrefix: serverConfig.apiPrefix
10
10
  }
11
11
 
12
- console.log(`🚀 Backend standalone: ${env.HOST}:${backendConfig.port}`)
12
+ console.log(`🚀 Backend standalone: ${serverConfig.host}:${backendConfig.port}`)
13
13
 
14
14
  // Iniciar apenas o backend
15
15
  startBackendOnly(apiRoutes, backendConfig)
@@ -1,52 +1,54 @@
1
1
  // User application entry point
2
- import { FluxStackFramework, loggerPlugin, vitePlugin, swaggerPlugin, staticPlugin, liveComponentsPlugin, staticFilesPlugin } from "@/core/server"
2
+ import { FluxStackFramework, vitePlugin, swaggerPlugin, staticPlugin, liveComponentsPlugin, staticFilesPlugin } from "@/core/server"
3
3
  import { isDevelopment } from "@/core/utils/helpers"
4
+ import { DEBUG } from "@/core/utils/logger"
4
5
  import { apiRoutes } from "./routes"
5
- // Import sistema de env dinâmico simplificado
6
- import { env, helpers } from "@/core/utils/env-runtime-v2"
7
- // Import live components registration
6
+ import { helpers } from "@/core/utils/env"
7
+ import { serverConfig } from "@/config/server.config"
8
+ import { appConfig } from "@/config/app.config"
9
+ import { loggerConfig } from "@/config/logger.config"
8
10
  import "./live/register-components"
9
11
 
10
- console.log('🔧 Loading dynamic environment configuration...')
11
- console.log(`📊 Environment: ${env.NODE_ENV}`) // Direto!
12
- console.log(`🚀 Port: ${env.PORT}`) // Direto!
13
- console.log(`🌐 Host: ${env.HOST}`) // Direto!
12
+ // Startup info moved to DEBUG level (set LOG_LEVEL=debug to see details)
13
+ DEBUG('🔧 Loading declarative configuration...')
14
+ DEBUG(`📊 Environment: ${appConfig.env}`)
15
+ DEBUG(`🚀 Port: ${serverConfig.port}`)
16
+ DEBUG(`🌐 Host: ${serverConfig.host}`)
14
17
 
15
- // Criar aplicação com configuração dinâmica simplificada
18
+ // Criar aplicação com configuração declarativa
16
19
  const app = new FluxStackFramework({
17
20
  server: {
18
- port: env.PORT, // Direto! (number)
19
- host: env.HOST, // Direto! (string)
20
- apiPrefix: env.API_PREFIX, // Direto! (string)
21
+ port: serverConfig.port,
22
+ host: serverConfig.host,
23
+ apiPrefix: serverConfig.apiPrefix,
21
24
  cors: {
22
- origins: env.CORS_ORIGINS, // Direto! (string[])
23
- methods: env.get('CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']),
24
- headers: env.get('CORS_HEADERS', ['*']),
25
- credentials: env.get('CORS_CREDENTIALS', false)
25
+ origins: serverConfig.corsOrigins,
26
+ methods: serverConfig.corsMethods,
27
+ headers: serverConfig.corsHeaders,
28
+ credentials: serverConfig.corsCredentials
26
29
  },
27
30
  middleware: []
28
31
  },
29
32
  app: {
30
- name: env.FLUXSTACK_APP_NAME, // Direto! (string)
31
- version: env.FLUXSTACK_APP_VERSION // Direto! (string)
33
+ name: serverConfig.appName,
34
+ version: serverConfig.appVersion
32
35
  },
33
36
  client: {
34
- port: env.VITE_PORT, // Direto! (number)
37
+ port: serverConfig.clientPort,
35
38
  proxy: {
36
- target: helpers.getServerUrl() // Helper inteligente
39
+ target: helpers.getServerUrl()
37
40
  },
38
41
  build: {
39
- sourceMaps: env.get('CLIENT_SOURCEMAPS', env.NODE_ENV !== 'production'),
40
- minify: env.get('CLIENT_MINIFY', env.NODE_ENV === 'production'),
41
- target: env.get('CLIENT_TARGET', 'es2020'),
42
- outDir: env.get('CLIENT_OUTDIR', 'dist')
42
+ sourceMaps: serverConfig.clientSourceMaps,
43
+ minify: false,
44
+ target: serverConfig.clientTarget as any,
45
+ outDir: serverConfig.clientOutDir
43
46
  }
44
47
  }
45
48
  })
46
49
 
47
50
 
48
- // Usar plugins de infraestrutura primeiro (mas NÃO o Swagger ainda)
49
- app.use(loggerPlugin)
51
+ // Usar plugins de infraestrutura primeiro (Logger é core, não é plugin)
50
52
 
51
53
  // Usar plugins condicionalmente baseado no ambiente
52
54
  if (isDevelopment()) {
@@ -60,30 +62,47 @@ app.use(staticFilesPlugin) // Add Static Files support
60
62
  app.use(liveComponentsPlugin) // Add Live Components support
61
63
 
62
64
 
63
- // Adicionar rota de teste para mostrar env dinâmico (antes das rotas)
65
+ // Adicionar rota de teste para mostrar config declarativo (antes das rotas)
64
66
  app.getApp().get('/api/env-test', () => {
65
67
  return {
66
- message: '🔥 Environment Variables Simplificado!',
68
+ message: ' Declarative Config System!',
67
69
  timestamp: new Date().toISOString(),
70
+ serverConfig: {
71
+ port: serverConfig.port,
72
+ host: serverConfig.host,
73
+ apiPrefix: serverConfig.apiPrefix,
74
+ appName: serverConfig.appName,
75
+ appVersion: serverConfig.appVersion,
76
+ cors: {
77
+ origins: serverConfig.corsOrigins,
78
+ methods: serverConfig.corsMethods,
79
+ credentials: serverConfig.corsCredentials
80
+ },
81
+ client: {
82
+ port: serverConfig.clientPort,
83
+ target: serverConfig.clientTarget,
84
+ sourceMaps: serverConfig.clientSourceMaps
85
+ },
86
+ features: {
87
+ enableSwagger: serverConfig.enableSwagger,
88
+ enableMetrics: serverConfig.enableMetrics,
89
+ enableMonitoring: serverConfig.enableMonitoring
90
+ }
91
+ },
68
92
  environment: {
69
- NODE_ENV: env.NODE_ENV, // Direto!
70
- PORT: env.PORT, // Direto!
71
- HOST: env.HOST, // Direto!
72
- DEBUG: env.DEBUG, // Direto!
73
- CORS_ORIGINS: env.CORS_ORIGINS, // Direto!
74
- ENABLE_SWAGGER: env.ENABLE_SWAGGER, // Direto!
75
-
76
- // Vars customizadas com casting automático
77
- CUSTOM_VAR: env.get('CUSTOM_VAR', 'not-set'),
78
- MAX_RETRIES: env.get('MAX_RETRIES', 3), // number
79
- ENABLE_CACHE: env.get('ENABLE_CACHE', false), // boolean
80
- ALLOWED_IPS: env.get('ALLOWED_IPS', []) // string[]
93
+ NODE_ENV: appConfig.env,
94
+ DEBUG: appConfig.debug,
95
+ LOG_LEVEL: loggerConfig.level
81
96
  },
82
97
  urls: {
83
- server: helpers.getServerUrl(), // Helper!
98
+ server: helpers.getServerUrl(),
99
+ client: helpers.getClientUrl(),
84
100
  swagger: `${helpers.getServerUrl()}/swagger`
85
101
  },
86
- note: 'API simplificada com casting automático! 🚀'
102
+ system: {
103
+ version: 'declarative-config',
104
+ features: ['type-safe', 'validated', 'declarative', 'runtime-reload']
105
+ }
87
106
  }
88
107
  })
89
108
 
@@ -93,18 +112,8 @@ app.routes(apiRoutes)
93
112
  // Swagger por último para descobrir todas as rotas
94
113
  app.use(swaggerPlugin)
95
114
 
96
- // Iniciar servidor
97
- app.listen(() => {
98
- console.log('\n✅ FluxStack com Environment Variables Simplificado!')
99
- console.log(`🔗 Server: ${helpers.getServerUrl()}`)
100
- console.log(`🔗 Teste dinâmico: ${helpers.getServerUrl()}/api/env-test`)
101
-
102
- if (env.ENABLE_SWAGGER) {
103
- console.log(`📋 Swagger: ${helpers.getServerUrl()}/swagger`)
104
- }
105
-
106
- console.log('💡 Mude as env vars e reinicie para ver a diferença!')
107
- })
115
+ // Iniciar servidor (banner displayed by framework)
116
+ app.listen()
108
117
 
109
118
 
110
119
 
@@ -1,6 +1,10 @@
1
1
  // 🔥 FluxStack Configuration Live Component
2
2
 
3
3
  import { LiveComponent } from '@/core/types/types'
4
+ import { appConfig } from '@/config/app.config'
5
+ import { serverConfig } from '@/config/server.config'
6
+ import { loggerConfig } from '@/config/logger.config'
7
+ import { systemConfig, systemRuntimeInfo } from '@/config/system.config'
4
8
 
5
9
  export interface FluxStackConfigState {
6
10
  // Environment Configuration
@@ -154,10 +158,10 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
154
158
 
155
159
  // Set default state with real configuration
156
160
  this.state = {
157
- environment: (process.env.NODE_ENV as any) || 'development',
158
- port: parseInt(process.env.PORT || '3000'),
159
- host: process.env.HOST || 'localhost',
160
- apiPrefix: '/api',
161
+ environment: appConfig.env,
162
+ port: serverConfig.port,
163
+ host: serverConfig.host,
164
+ apiPrefix: serverConfig.apiPrefix,
161
165
 
162
166
  framework: {
163
167
  name: 'FluxStack',
@@ -195,7 +199,7 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
195
199
  enabled: true,
196
200
  dependencies: [],
197
201
  config: {
198
- level: process.env.LOG_LEVEL || 'info',
202
+ level: loggerConfig.level,
199
203
  format: 'pretty'
200
204
  }
201
205
  },
@@ -244,17 +248,15 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
244
248
 
245
249
  // Get runtime configuration
246
250
  private getRuntimeConfiguration() {
247
- const os = require('os')
248
-
249
251
  return {
250
- nodeVersion: process.version,
251
- bunVersion: process.versions.bun || 'N/A',
252
- platform: process.platform,
253
- architecture: process.arch,
254
- cpuCount: os.cpus().length,
255
- totalMemory: Math.round(os.totalmem() / 1024 / 1024 / 1024 * 100) / 100, // GB
256
- workingDirectory: process.cwd(),
257
- executablePath: process.execPath
252
+ nodeVersion: systemRuntimeInfo.nodeVersion,
253
+ bunVersion: systemRuntimeInfo.bunVersion,
254
+ platform: systemRuntimeInfo.platform,
255
+ architecture: systemRuntimeInfo.architecture,
256
+ cpuCount: systemRuntimeInfo.cpuCount,
257
+ totalMemory: systemRuntimeInfo.totalMemory,
258
+ workingDirectory: systemRuntimeInfo.workingDirectory,
259
+ executablePath: systemRuntimeInfo.executablePath
258
260
  }
259
261
  }
260
262
 
@@ -355,17 +357,17 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
355
357
  // Get Logging configuration
356
358
  private getLoggingConfiguration() {
357
359
  return {
358
- level: (process.env.LOG_LEVEL as any) || 'info',
359
- format: 'pretty',
360
+ level: loggerConfig.level as 'debug' | 'info' | 'warn' | 'error',
361
+ format: 'pretty' as 'json' | 'pretty' | 'compact',
360
362
  file: {
361
- enabled: false,
362
- path: undefined,
363
- maxSize: undefined,
364
- maxFiles: undefined
363
+ enabled: loggerConfig.logToFile,
364
+ path: loggerConfig.logToFile ? 'logs/app.log' : undefined,
365
+ maxSize: loggerConfig.maxSize,
366
+ maxFiles: parseInt(loggerConfig.maxFiles) || undefined
365
367
  },
366
368
  console: {
367
369
  enabled: true,
368
- colors: true
370
+ colors: loggerConfig.enableColors
369
371
  }
370
372
  }
371
373
  }
@@ -408,16 +410,18 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
408
410
  // Update specific configuration section
409
411
  async updateConfiguration(data: { section: string; config: Record<string, any> }) {
410
412
  const { section, config } = data
411
-
413
+
412
414
  if (!this.state[section as keyof FluxStackConfigState]) {
413
415
  throw new Error(`Invalid configuration section: ${section}`)
414
416
  }
415
-
417
+
418
+ const currentSection = this.state[section as keyof FluxStackConfigState]
419
+ const updatedSection = typeof currentSection === 'object' && currentSection !== null
420
+ ? { ...currentSection as object, ...config }
421
+ : config
422
+
416
423
  this.setState({
417
- [section]: {
418
- ...this.state[section as keyof FluxStackConfigState],
419
- ...config
420
- },
424
+ [section]: updatedSection,
421
425
  lastUpdated: Date.now()
422
426
  } as Partial<FluxStackConfigState>)
423
427
 
@@ -433,22 +437,22 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
433
437
  // Get environment variables
434
438
  async getEnvironmentVariables() {
435
439
  const envVars = {
436
- NODE_ENV: process.env.NODE_ENV,
437
- PORT: process.env.PORT,
438
- HOST: process.env.HOST,
439
- LOG_LEVEL: process.env.LOG_LEVEL,
440
- // Add other non-sensitive env vars
441
- PWD: process.env.PWD,
442
- PATH: process.env.PATH ? '***truncated***' : undefined,
443
- USER: process.env.USER || process.env.USERNAME,
444
- HOME: process.env.HOME || process.env.USERPROFILE
440
+ NODE_ENV: appConfig.env,
441
+ PORT: serverConfig.port.toString(),
442
+ HOST: serverConfig.host,
443
+ LOG_LEVEL: loggerConfig.level,
444
+ // Add other non-sensitive env vars from system config
445
+ PWD: systemConfig.pwd || undefined,
446
+ PATH: systemConfig.path ? '***truncated***' : undefined,
447
+ USER: systemConfig.currentUser,
448
+ HOME: systemConfig.homeDirectory || undefined
445
449
  }
446
-
450
+
447
451
  this.emit('ENVIRONMENT_VARIABLES_REQUESTED', {
448
452
  count: Object.keys(envVars).length,
449
453
  timestamp: Date.now()
450
454
  })
451
-
455
+
452
456
  return envVars
453
457
  }
454
458
 
@@ -87,8 +87,8 @@ export class SystemMonitorIntegration {
87
87
  this.recordMessage(action, componentId, success, responseTime)
88
88
  }
89
89
  }
90
-
91
- console.log('🔗 SystemMonitor integration hooks setup completed')
90
+
91
+ // Setup completed - logged in auto-discovery group
92
92
  }
93
93
 
94
94
  // Record a connection event
@@ -5,4 +5,4 @@
5
5
  // NOTE: If you see this in production, auto-generation worked!
6
6
  // All Live Components should be discovered and registered automatically during build
7
7
 
8
- console.log('🧪 Manual registration file loaded - auto-generation should handle components')
8
+ // Removed startup log to keep output clean - auto-generation handles everything
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { Context } from 'elysia'
7
+ import { appConfig } from '@/config/app.config'
7
8
 
8
9
  export interface ErrorResponse {
9
10
  error: string
@@ -139,14 +140,15 @@ export const errorHandlingMiddleware = {
139
140
  }
140
141
 
141
142
  // Default to internal server error
143
+ const isProduction = appConfig.env === 'production'
142
144
  return createErrorResponse(
143
145
  500,
144
- process.env.NODE_ENV === 'production'
145
- ? 'Internal server error'
146
+ isProduction
147
+ ? 'Internal server error'
146
148
  : error.message,
147
149
  'INTERNAL_ERROR',
148
- process.env.NODE_ENV === 'production'
149
- ? undefined
150
+ isProduction
151
+ ? undefined
150
152
  : { stack: error.stack },
151
153
  requestId
152
154
  )
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Config Management Routes
3
+ * Allows runtime configuration reload and inspection
4
+ */
5
+
6
+ import { Elysia, t } from 'elysia'
7
+ import { appRuntimeConfig } from '@/config/runtime.config'
8
+
9
+ export const configRoutes = new Elysia({ prefix: '/config' })
10
+ /**
11
+ * Get current runtime configuration
12
+ */
13
+ .get('/', () => {
14
+ return {
15
+ success: true,
16
+ config: appRuntimeConfig.values,
17
+ timestamp: new Date().toISOString()
18
+ }
19
+ }, {
20
+ detail: {
21
+ summary: 'Get current runtime configuration',
22
+ tags: ['Config']
23
+ }
24
+ })
25
+
26
+ /**
27
+ * Reload configuration from environment
28
+ */
29
+ .post('/reload', () => {
30
+ try {
31
+ const oldConfig = { ...appRuntimeConfig.values }
32
+ const newConfig = appRuntimeConfig.reload()
33
+
34
+ // Find changed fields
35
+ const changes: Record<string, { old: any, new: any }> = {}
36
+ for (const key in newConfig) {
37
+ if (oldConfig[key] !== newConfig[key]) {
38
+ changes[key] = {
39
+ old: oldConfig[key],
40
+ new: newConfig[key]
41
+ }
42
+ }
43
+ }
44
+
45
+ return {
46
+ success: true,
47
+ message: 'Configuration reloaded successfully',
48
+ changes,
49
+ timestamp: new Date().toISOString()
50
+ }
51
+ } catch (error: any) {
52
+ return {
53
+ success: false,
54
+ error: error.message,
55
+ timestamp: new Date().toISOString()
56
+ }
57
+ }
58
+ }, {
59
+ detail: {
60
+ summary: 'Reload configuration from environment variables',
61
+ description: 'Reloads configuration without restarting the server. Validates new values before applying.',
62
+ tags: ['Config']
63
+ }
64
+ })
65
+
66
+ /**
67
+ * Get specific config field
68
+ */
69
+ .get('/:field', ({ params: { field } }) => {
70
+ const value = appRuntimeConfig.get(field as any)
71
+
72
+ if (value === undefined) {
73
+ return {
74
+ success: false,
75
+ error: `Field '${field}' not found`,
76
+ timestamp: new Date().toISOString()
77
+ }
78
+ }
79
+
80
+ return {
81
+ success: true,
82
+ field,
83
+ value,
84
+ type: typeof value,
85
+ timestamp: new Date().toISOString()
86
+ }
87
+ }, {
88
+ detail: {
89
+ summary: 'Get specific configuration field',
90
+ tags: ['Config']
91
+ },
92
+ params: t.Object({
93
+ field: t.String()
94
+ })
95
+ })
96
+
97
+ /**
98
+ * Check if config field exists
99
+ */
100
+ .get('/:field/exists', ({ params: { field } }) => {
101
+ const exists = appRuntimeConfig.has(field as any)
102
+
103
+ return {
104
+ success: true,
105
+ field,
106
+ exists,
107
+ timestamp: new Date().toISOString()
108
+ }
109
+ }, {
110
+ detail: {
111
+ summary: 'Check if configuration field exists',
112
+ tags: ['Config']
113
+ },
114
+ params: t.Object({
115
+ field: t.String()
116
+ })
117
+ })
118
+
119
+ /**
120
+ * Health check for config system
121
+ */
122
+ .get('/health', () => {
123
+ try {
124
+ const config = appRuntimeConfig.values
125
+
126
+ return {
127
+ success: true,
128
+ status: 'healthy',
129
+ fieldsLoaded: Object.keys(config).length,
130
+ timestamp: new Date().toISOString()
131
+ }
132
+ } catch (error: any) {
133
+ return {
134
+ success: false,
135
+ status: 'unhealthy',
136
+ error: error.message,
137
+ timestamp: new Date().toISOString()
138
+ }
139
+ }
140
+ }, {
141
+ detail: {
142
+ summary: 'Config system health check',
143
+ tags: ['Config']
144
+ }
145
+ })
@@ -1,6 +1,7 @@
1
1
  import { Elysia, t } from "elysia"
2
2
  import { usersRoutes } from "./users.routes"
3
3
  import { uploadRoutes } from "./upload"
4
+ import { configRoutes } from "./config"
4
5
 
5
6
  export const apiRoutes = new Elysia({ prefix: "/api" })
6
7
  .get("/", () => ({ message: "🔥 Hot Reload funcionando! FluxStack API v1.4.0 ⚡" }), {
@@ -13,8 +14,8 @@ export const apiRoutes = new Elysia({ prefix: "/api" })
13
14
  description: 'Returns a welcome message from the FluxStack API'
14
15
  }
15
16
  })
16
- .get("/health", () => ({
17
- status: "🚀 Hot Reload ativo!",
17
+ .get("/health", () => ({
18
+ status: "🚀 Hot Reload ativo!",
18
19
  timestamp: new Date().toISOString(),
19
20
  uptime: `${Math.floor(process.uptime())}s`,
20
21
  version: "1.4.0",
@@ -34,4 +35,5 @@ export const apiRoutes = new Elysia({ prefix: "/api" })
34
35
  }
35
36
  })
36
37
  .use(usersRoutes)
37
- .use(uploadRoutes)
38
+ .use(uploadRoutes)
39
+ .use(configRoutes)
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Application Configuration
3
+ * Laravel-style declarative config with validation
4
+ */
5
+
6
+ import { defineConfig, config } from '@/core/utils/config-schema'
7
+
8
+ /**
9
+ * App configuration schema
10
+ */
11
+ const appConfigSchema = {
12
+ // App basics
13
+ name: config.string('APP_NAME', 'FluxStack', true),
14
+
15
+ version: {
16
+ type: 'string' as const,
17
+ env: 'APP_VERSION',
18
+ default: '1.0.0',
19
+ validate: (value: string) => /^\d+\.\d+\.\d+$/.test(value) || 'Version must be semver format (e.g., 1.0.0)'
20
+ },
21
+
22
+ description: config.string('APP_DESCRIPTION', 'A FluxStack application'),
23
+
24
+ // Environment
25
+ env: config.enum('NODE_ENV', ['development', 'production', 'test'] as const, 'development', true),
26
+
27
+ debug: config.boolean('DEBUG', false),
28
+
29
+ // Server
30
+ port: {
31
+ type: 'number' as const,
32
+ env: 'PORT',
33
+ default: 3000,
34
+ required: true,
35
+ validate: (value: number) => {
36
+ if (value < 1 || value > 65535) {
37
+ return 'Port must be between 1 and 65535'
38
+ }
39
+ return true
40
+ }
41
+ },
42
+
43
+ host: config.string('HOST', 'localhost', true),
44
+
45
+ apiPrefix: {
46
+ type: 'string' as const,
47
+ env: 'API_PREFIX',
48
+ default: '/api',
49
+ validate: (value: string) => value.startsWith('/') || 'API prefix must start with /'
50
+ },
51
+
52
+ // URLs
53
+ url: config.string('APP_URL', undefined, false),
54
+
55
+ // Features
56
+ enableSwagger: config.boolean('ENABLE_SWAGGER', true),
57
+ enableMetrics: config.boolean('ENABLE_METRICS', false),
58
+ enableMonitoring: config.boolean('ENABLE_MONITORING', false),
59
+
60
+ // Client
61
+ clientPort: config.number('VITE_PORT', 5173),
62
+
63
+ // Logging
64
+ logLevel: config.enum('LOG_LEVEL', ['debug', 'info', 'warn', 'error'] as const, 'info'),
65
+ logFormat: config.enum('LOG_FORMAT', ['json', 'pretty'] as const, 'pretty'),
66
+
67
+ // CORS
68
+ corsOrigins: config.array('CORS_ORIGINS', ['*']),
69
+ corsMethods: config.array('CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']),
70
+ corsHeaders: config.array('CORS_HEADERS', ['Content-Type', 'Authorization']),
71
+ corsCredentials: config.boolean('CORS_CREDENTIALS', false),
72
+
73
+ // Security
74
+ trustProxy: config.boolean('TRUST_PROXY', false),
75
+
76
+ sessionSecret: {
77
+ type: 'string' as const,
78
+ env: 'SESSION_SECRET',
79
+ default: undefined,
80
+ required: false,
81
+ validate: (value: string) => {
82
+ if (!value) return true // Optional
83
+ if (value.length < 32) {
84
+ return 'Session secret must be at least 32 characters'
85
+ }
86
+ return true
87
+ }
88
+ }
89
+ } as const
90
+
91
+ export const appConfig = defineConfig(appConfigSchema)
92
+
93
+ // Export type for use in other files
94
+ export type AppConfig = typeof appConfig
95
+
96
+ /**
97
+ * Type-safe environment type
98
+ * Use this when you need the literal type explicitly
99
+ */
100
+ export type Environment = typeof appConfig.env
101
+
102
+ /**
103
+ * Type-safe log level type
104
+ */
105
+ export type LogLevel = typeof appConfig.logLevel
106
+
107
+ /**
108
+ * Type-safe log format type
109
+ */
110
+ export type LogFormat = typeof appConfig.logFormat
111
+
112
+ // Export default
113
+ export default appConfig