create-fluxstack 1.0.22 → 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.
- package/app/server/backend-only.ts +5 -5
- package/app/server/index.ts +63 -54
- package/app/server/live/FluxStackConfig.ts +43 -39
- package/app/server/live/SystemMonitorIntegration.ts +2 -2
- package/app/server/live/register-components.ts +6 -26
- package/app/server/middleware/errorHandling.ts +6 -4
- package/app/server/routes/config.ts +145 -0
- package/app/server/routes/index.ts +5 -3
- package/config/app.config.ts +113 -0
- package/config/build.config.ts +24 -0
- package/config/database.config.ts +99 -0
- package/config/index.ts +68 -0
- package/config/logger.config.ts +27 -0
- package/config/runtime.config.ts +92 -0
- package/config/server.config.ts +46 -0
- package/config/services.config.ts +130 -0
- package/config/system.config.ts +105 -0
- package/core/build/bundler.ts +53 -5
- package/core/build/flux-plugins-generator.ts +315 -0
- package/core/build/index.ts +11 -7
- package/core/build/live-components-generator.ts +231 -0
- package/core/build/optimizer.ts +2 -54
- package/core/cli/index.ts +31 -13
- package/core/config/env.ts +38 -94
- package/core/config/runtime-config.ts +61 -58
- package/core/config/schema.ts +1 -0
- package/core/framework/server.ts +55 -11
- package/core/plugins/built-in/index.ts +7 -17
- package/core/plugins/built-in/static/index.ts +24 -10
- package/core/plugins/built-in/swagger/index.ts +228 -228
- package/core/plugins/built-in/vite/index.ts +374 -358
- package/core/plugins/dependency-manager.ts +5 -5
- package/core/plugins/manager.ts +57 -14
- package/core/plugins/registry.ts +3 -3
- package/core/server/index.ts +0 -1
- package/core/server/live/ComponentRegistry.ts +34 -8
- package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
- package/core/server/live/websocket-plugin.ts +434 -434
- package/core/server/middleware/README.md +488 -0
- package/core/server/middleware/elysia-helpers.ts +227 -0
- package/core/server/middleware/index.ts +25 -9
- package/core/server/plugins/static-files-plugin.ts +231 -231
- package/core/utils/config-schema.ts +484 -0
- package/core/utils/env.ts +306 -0
- package/core/utils/helpers.ts +9 -3
- package/core/utils/logger/colors.ts +114 -0
- package/core/utils/logger/config.ts +35 -0
- package/core/utils/logger/formatter.ts +82 -0
- package/core/utils/logger/group-logger.ts +101 -0
- package/core/utils/logger/index.ts +199 -250
- package/core/utils/logger/stack-trace.ts +92 -0
- package/core/utils/logger/startup-banner.ts +92 -0
- package/core/utils/logger/winston-logger.ts +152 -0
- package/core/utils/version.ts +5 -0
- package/create-fluxstack.ts +1 -0
- package/fluxstack.config.ts +6 -12
- package/package.json +117 -114
- package/plugins/crypto-auth/README.md +238 -0
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +325 -0
- package/plugins/crypto-auth/client/components/AuthProvider.tsx +190 -0
- package/plugins/crypto-auth/client/components/LoginButton.tsx +155 -0
- package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +109 -0
- package/plugins/crypto-auth/client/components/SessionInfo.tsx +242 -0
- package/plugins/crypto-auth/client/components/index.ts +15 -0
- package/plugins/crypto-auth/client/index.ts +12 -0
- package/plugins/crypto-auth/index.ts +230 -0
- package/plugins/crypto-auth/package.json +65 -0
- package/plugins/crypto-auth/plugin.json +29 -0
- package/plugins/crypto-auth/server/AuthMiddleware.ts +237 -0
- package/plugins/crypto-auth/server/CryptoAuthService.ts +293 -0
- package/plugins/crypto-auth/server/index.ts +9 -0
- package/vite.config.ts +16 -0
- package/core/config/env-dynamic.ts +0 -326
- package/core/plugins/built-in/logger/index.ts +0 -180
- package/core/server/plugins/logger.ts +0 -47
- package/core/utils/env-runtime-v2.ts +0 -232
- package/core/utils/env-runtime.ts +0 -259
- package/core/utils/logger/formatters.ts +0 -222
- package/core/utils/logger/middleware.ts +0 -253
- package/core/utils/logger/performance.ts +0 -384
- package/core/utils/logger/transports.ts +0 -365
- package/core/utils/logger.ts +0 -106
|
@@ -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
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build & Client Configuration
|
|
3
|
+
* Declarative build and client config for FluxStack framework
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
export const buildConfig = defineConfig({
|
|
9
|
+
// Client build settings
|
|
10
|
+
clientBuildDir: config.string('CLIENT_BUILD_DIR', 'dist/client'),
|
|
11
|
+
clientSourceMaps: config.boolean('CLIENT_SOURCEMAPS', false),
|
|
12
|
+
clientMinify: config.boolean('CLIENT_MINIFY', true),
|
|
13
|
+
clientTarget: config.string('CLIENT_TARGET', 'es2020'),
|
|
14
|
+
|
|
15
|
+
// API proxy settings
|
|
16
|
+
apiUrl: config.string('API_URL', 'http://localhost:3000'),
|
|
17
|
+
proxyChangeOrigin: config.boolean('PROXY_CHANGE_ORIGIN', true),
|
|
18
|
+
|
|
19
|
+
// Monitoring
|
|
20
|
+
monitoringEnabled: config.boolean('MONITORING_ENABLED', false)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export type BuildConfig = typeof buildConfig
|
|
24
|
+
export default buildConfig
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Configuration
|
|
3
|
+
* Laravel-style declarative config with validation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Database configuration schema
|
|
10
|
+
*/
|
|
11
|
+
export const databaseConfig = defineConfig({
|
|
12
|
+
// Connection
|
|
13
|
+
url: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
env: 'DATABASE_URL',
|
|
16
|
+
default: undefined,
|
|
17
|
+
required: false,
|
|
18
|
+
validate: (value) => {
|
|
19
|
+
if (!value) return true // Optional
|
|
20
|
+
if (!value.includes('://')) {
|
|
21
|
+
return 'DATABASE_URL must be a valid connection string (e.g., postgres://...)'
|
|
22
|
+
}
|
|
23
|
+
return true
|
|
24
|
+
},
|
|
25
|
+
description: 'Full database connection URL (overrides individual settings)'
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
host: config.string('DB_HOST', 'localhost'),
|
|
29
|
+
|
|
30
|
+
port: config.number('DB_PORT', 5432),
|
|
31
|
+
|
|
32
|
+
database: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
env: 'DB_NAME',
|
|
35
|
+
default: undefined,
|
|
36
|
+
required: false,
|
|
37
|
+
description: 'Database name'
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
user: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
env: 'DB_USER',
|
|
43
|
+
default: undefined,
|
|
44
|
+
required: false
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
password: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
env: 'DB_PASSWORD',
|
|
50
|
+
default: undefined,
|
|
51
|
+
required: false
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Connection pool
|
|
55
|
+
poolMin: {
|
|
56
|
+
type: 'number',
|
|
57
|
+
env: 'DB_POOL_MIN',
|
|
58
|
+
default: 2,
|
|
59
|
+
validate: (value) => value >= 0 || 'Pool min must be >= 0'
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
poolMax: {
|
|
63
|
+
type: 'number',
|
|
64
|
+
env: 'DB_POOL_MAX',
|
|
65
|
+
default: 10,
|
|
66
|
+
validate: (value) => value > 0 || 'Pool max must be > 0'
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// SSL
|
|
70
|
+
ssl: config.boolean('DB_SSL', false),
|
|
71
|
+
|
|
72
|
+
// Timeouts
|
|
73
|
+
connectionTimeout: {
|
|
74
|
+
type: 'number',
|
|
75
|
+
env: 'DB_CONNECTION_TIMEOUT',
|
|
76
|
+
default: 30000,
|
|
77
|
+
description: 'Connection timeout in milliseconds'
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
queryTimeout: {
|
|
81
|
+
type: 'number',
|
|
82
|
+
env: 'DB_QUERY_TIMEOUT',
|
|
83
|
+
default: 60000,
|
|
84
|
+
description: 'Query timeout in milliseconds'
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// Features
|
|
88
|
+
enableLogging: config.boolean('DB_ENABLE_LOGGING', false),
|
|
89
|
+
|
|
90
|
+
enableMigrations: config.boolean('DB_ENABLE_MIGRATIONS', true),
|
|
91
|
+
|
|
92
|
+
migrationsTable: config.string('DB_MIGRATIONS_TABLE', 'migrations')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Export type
|
|
96
|
+
export type DatabaseConfig = typeof databaseConfig
|
|
97
|
+
|
|
98
|
+
// Export default
|
|
99
|
+
export default databaseConfig
|
package/config/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⚡ FluxStack Configuration Index
|
|
3
|
+
*
|
|
4
|
+
* Centralized configuration using Laravel-style declarative schemas
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { appConfig, databaseConfig, servicesConfig } from '@/config'
|
|
9
|
+
*
|
|
10
|
+
* // All configs are type-safe and validated!
|
|
11
|
+
* console.log(appConfig.name) // string
|
|
12
|
+
* console.log(appConfig.port) // number
|
|
13
|
+
* console.log(appConfig.debug) // boolean
|
|
14
|
+
*
|
|
15
|
+
* // Nested configs
|
|
16
|
+
* console.log(servicesConfig.email.host) // string
|
|
17
|
+
* console.log(servicesConfig.jwt.secret) // string
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export { appConfig } from './app.config'
|
|
22
|
+
export { databaseConfig } from './database.config'
|
|
23
|
+
export { servicesConfig } from './services.config'
|
|
24
|
+
export { serverConfig } from './server.config'
|
|
25
|
+
export { loggerConfig } from './logger.config'
|
|
26
|
+
export { buildConfig } from './build.config'
|
|
27
|
+
export { appRuntimeConfig } from './runtime.config'
|
|
28
|
+
export { systemConfig, systemRuntimeInfo } from './system.config'
|
|
29
|
+
|
|
30
|
+
// Re-export types
|
|
31
|
+
export type { AppConfig } from './app.config'
|
|
32
|
+
export type { DatabaseConfig } from './database.config'
|
|
33
|
+
export type { ServerConfig } from './server.config'
|
|
34
|
+
export type { LoggerConfig } from './logger.config'
|
|
35
|
+
export type { BuildConfig } from './build.config'
|
|
36
|
+
export type { SystemConfig, SystemRuntimeInfo } from './system.config'
|
|
37
|
+
export type {
|
|
38
|
+
EmailConfig,
|
|
39
|
+
JWTConfig,
|
|
40
|
+
StorageConfig,
|
|
41
|
+
RedisConfig
|
|
42
|
+
} from './services.config'
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* All configs in one object
|
|
46
|
+
*/
|
|
47
|
+
import { appConfig } from './app.config'
|
|
48
|
+
import { databaseConfig } from './database.config'
|
|
49
|
+
import { servicesConfig } from './services.config'
|
|
50
|
+
import { serverConfig } from './server.config'
|
|
51
|
+
import { loggerConfig } from './logger.config'
|
|
52
|
+
import { buildConfig } from './build.config'
|
|
53
|
+
import { appRuntimeConfig } from './runtime.config'
|
|
54
|
+
import { systemConfig, systemRuntimeInfo } from './system.config'
|
|
55
|
+
|
|
56
|
+
export const config = {
|
|
57
|
+
app: appConfig,
|
|
58
|
+
database: databaseConfig,
|
|
59
|
+
services: servicesConfig,
|
|
60
|
+
server: serverConfig,
|
|
61
|
+
logger: loggerConfig,
|
|
62
|
+
build: buildConfig,
|
|
63
|
+
runtime: appRuntimeConfig,
|
|
64
|
+
system: systemConfig,
|
|
65
|
+
systemRuntime: systemRuntimeInfo
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default config
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Configuration
|
|
3
|
+
* Declarative logger config using FluxStack config system
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
export const loggerConfig = defineConfig({
|
|
9
|
+
// Log level
|
|
10
|
+
level: config.enum('LOG_LEVEL', ['debug', 'info', 'warn', 'error'] as const, 'info'),
|
|
11
|
+
|
|
12
|
+
// Format settings
|
|
13
|
+
dateFormat: config.string('LOG_DATE_FORMAT', 'YYYY-MM-DD HH:mm:ss'),
|
|
14
|
+
objectDepth: config.number('LOG_OBJECT_DEPTH', 4),
|
|
15
|
+
|
|
16
|
+
// File logging
|
|
17
|
+
logToFile: config.boolean('LOG_TO_FILE', false),
|
|
18
|
+
maxSize: config.string('LOG_MAX_SIZE', '20m'),
|
|
19
|
+
maxFiles: config.string('LOG_MAX_FILES', '14d'),
|
|
20
|
+
|
|
21
|
+
// Display options
|
|
22
|
+
enableColors: config.boolean('LOG_COLORS', true),
|
|
23
|
+
enableStackTrace: config.boolean('LOG_STACK_TRACE', true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export type LoggerConfig = typeof loggerConfig
|
|
27
|
+
export default loggerConfig
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-Reloadable Configuration
|
|
3
|
+
* Configs that can be reloaded without server restart
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineReactiveConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Runtime app configuration
|
|
10
|
+
* Can be reloaded via appRuntimeConfig.reload()
|
|
11
|
+
*/
|
|
12
|
+
export const appRuntimeConfig = defineReactiveConfig({
|
|
13
|
+
// Features that can be toggled in runtime
|
|
14
|
+
enableSwagger: config.boolean('ENABLE_SWAGGER', true),
|
|
15
|
+
enableMetrics: config.boolean('ENABLE_METRICS', false),
|
|
16
|
+
enableMonitoring: config.boolean('ENABLE_MONITORING', false),
|
|
17
|
+
enableDebugMode: config.boolean('DEBUG', false),
|
|
18
|
+
|
|
19
|
+
// Logging level can be changed in runtime
|
|
20
|
+
logLevel: config.enum(
|
|
21
|
+
'LOG_LEVEL',
|
|
22
|
+
['debug', 'info', 'warn', 'error'] as const,
|
|
23
|
+
'info'
|
|
24
|
+
),
|
|
25
|
+
|
|
26
|
+
logFormat: config.enum(
|
|
27
|
+
'LOG_FORMAT',
|
|
28
|
+
['json', 'pretty'] as const,
|
|
29
|
+
'pretty'
|
|
30
|
+
),
|
|
31
|
+
|
|
32
|
+
// Rate limiting
|
|
33
|
+
rateLimitEnabled: config.boolean('RATE_LIMIT_ENABLED', true),
|
|
34
|
+
|
|
35
|
+
rateLimitMax: {
|
|
36
|
+
type: 'number' as const,
|
|
37
|
+
env: 'RATE_LIMIT_MAX',
|
|
38
|
+
default: 100,
|
|
39
|
+
validate: (value: number) => value > 0 || 'Rate limit must be positive'
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
rateLimitWindow: {
|
|
43
|
+
type: 'number' as const,
|
|
44
|
+
env: 'RATE_LIMIT_WINDOW',
|
|
45
|
+
default: 60000,
|
|
46
|
+
description: 'Rate limit window in milliseconds'
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Request timeout
|
|
50
|
+
requestTimeout: {
|
|
51
|
+
type: 'number' as const,
|
|
52
|
+
env: 'REQUEST_TIMEOUT',
|
|
53
|
+
default: 30000,
|
|
54
|
+
validate: (value: number) => value > 0 || 'Timeout must be positive'
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// Max upload size
|
|
58
|
+
maxUploadSize: {
|
|
59
|
+
type: 'number' as const,
|
|
60
|
+
env: 'MAX_UPLOAD_SIZE',
|
|
61
|
+
default: 10485760, // 10MB
|
|
62
|
+
validate: (value: number) => value > 0 || 'Max upload size must be positive'
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// Allowed origins (can be updated in runtime)
|
|
66
|
+
corsOrigins: config.array('CORS_ORIGINS', ['*']),
|
|
67
|
+
|
|
68
|
+
// Maintenance mode
|
|
69
|
+
maintenanceMode: config.boolean('MAINTENANCE_MODE', false),
|
|
70
|
+
|
|
71
|
+
maintenanceMessage: config.string(
|
|
72
|
+
'MAINTENANCE_MESSAGE',
|
|
73
|
+
'System is under maintenance. Please try again later.'
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Setup config watcher with logging
|
|
79
|
+
*/
|
|
80
|
+
appRuntimeConfig.watch((newConfig) => {
|
|
81
|
+
console.log('🔄 Runtime config reloaded:')
|
|
82
|
+
console.log(' Debug:', newConfig.enableDebugMode)
|
|
83
|
+
console.log(' Log Level:', newConfig.logLevel)
|
|
84
|
+
console.log(' Maintenance:', newConfig.maintenanceMode)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Export type
|
|
89
|
+
*/
|
|
90
|
+
export type AppRuntimeConfig = typeof appRuntimeConfig.values
|
|
91
|
+
|
|
92
|
+
export default appRuntimeConfig
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Configuration
|
|
3
|
+
* Declarative server config using FluxStack config system
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
const serverConfigSchema = {
|
|
9
|
+
// Server basics
|
|
10
|
+
port: config.number('PORT', 3000, true),
|
|
11
|
+
host: config.string('HOST', 'localhost', true),
|
|
12
|
+
apiPrefix: config.string('API_PREFIX', '/api'),
|
|
13
|
+
|
|
14
|
+
// CORS configuration
|
|
15
|
+
corsOrigins: config.array('CORS_ORIGINS', ['http://localhost:3000', 'http://localhost:5173']),
|
|
16
|
+
corsMethods: config.array('CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']),
|
|
17
|
+
corsHeaders: config.array('CORS_HEADERS', ['Content-Type', 'Authorization']),
|
|
18
|
+
corsCredentials: config.boolean('CORS_CREDENTIALS', false),
|
|
19
|
+
corsMaxAge: config.number('CORS_MAX_AGE', 86400),
|
|
20
|
+
|
|
21
|
+
// Client config
|
|
22
|
+
clientPort: config.number('VITE_PORT', 5173),
|
|
23
|
+
clientTarget: config.string('CLIENT_TARGET', 'es2020'),
|
|
24
|
+
clientOutDir: config.string('CLIENT_OUTDIR', 'dist'),
|
|
25
|
+
clientSourceMaps: config.boolean('CLIENT_SOURCEMAPS', false),
|
|
26
|
+
|
|
27
|
+
// Backend-only mode
|
|
28
|
+
backendPort: config.number('BACKEND_PORT', 3001),
|
|
29
|
+
|
|
30
|
+
// App info
|
|
31
|
+
appName: config.string('FLUXSTACK_APP_NAME', 'FluxStack'),
|
|
32
|
+
appVersion: config.string('FLUXSTACK_APP_VERSION', '1.0.0'),
|
|
33
|
+
|
|
34
|
+
// Features
|
|
35
|
+
enableSwagger: config.boolean('ENABLE_SWAGGER', true),
|
|
36
|
+
enableMetrics: config.boolean('ENABLE_METRICS', false),
|
|
37
|
+
enableMonitoring: config.boolean('ENABLE_MONITORING', false),
|
|
38
|
+
|
|
39
|
+
// Vite/Development
|
|
40
|
+
enableViteProxyLogs: config.boolean('ENABLE_VITE_PROXY_LOGS', false)
|
|
41
|
+
} as const
|
|
42
|
+
|
|
43
|
+
export const serverConfig = defineConfig(serverConfigSchema)
|
|
44
|
+
|
|
45
|
+
export type ServerConfig = typeof serverConfig
|
|
46
|
+
export default serverConfig
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Services Configuration
|
|
3
|
+
* Laravel-style declarative config for third-party services
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, defineNestedConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Email service configuration
|
|
10
|
+
*/
|
|
11
|
+
const emailSchema = {
|
|
12
|
+
// SMTP
|
|
13
|
+
host: config.string('SMTP_HOST'),
|
|
14
|
+
|
|
15
|
+
port: {
|
|
16
|
+
type: 'number' as const,
|
|
17
|
+
env: 'SMTP_PORT',
|
|
18
|
+
default: 587,
|
|
19
|
+
validate: (value: number) => value > 0 || 'SMTP port must be positive'
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
user: config.string('SMTP_USER'),
|
|
23
|
+
password: config.string('SMTP_PASSWORD'),
|
|
24
|
+
|
|
25
|
+
secure: config.boolean('SMTP_SECURE', false),
|
|
26
|
+
|
|
27
|
+
from: {
|
|
28
|
+
type: 'string' as const,
|
|
29
|
+
env: 'SMTP_FROM',
|
|
30
|
+
default: 'noreply@example.com',
|
|
31
|
+
validate: (value: string) => {
|
|
32
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
33
|
+
return emailRegex.test(value) || 'From email must be valid'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
replyTo: config.string('SMTP_REPLY_TO')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* JWT authentication configuration
|
|
42
|
+
*/
|
|
43
|
+
const jwtSchema = {
|
|
44
|
+
secret: {
|
|
45
|
+
type: 'string' as const,
|
|
46
|
+
env: 'JWT_SECRET',
|
|
47
|
+
default: undefined,
|
|
48
|
+
required: false,
|
|
49
|
+
validate: (value: string) => {
|
|
50
|
+
if (!value) return true // Optional
|
|
51
|
+
if (value.length < 32) {
|
|
52
|
+
return 'JWT secret must be at least 32 characters for security'
|
|
53
|
+
}
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
expiresIn: config.string('JWT_EXPIRES_IN', '24h'),
|
|
59
|
+
|
|
60
|
+
algorithm: config.enum(
|
|
61
|
+
'JWT_ALGORITHM',
|
|
62
|
+
['HS256', 'HS384', 'HS512', 'RS256', 'RS384', 'RS512'] as const,
|
|
63
|
+
'HS256'
|
|
64
|
+
),
|
|
65
|
+
|
|
66
|
+
issuer: config.string('JWT_ISSUER', 'fluxstack'),
|
|
67
|
+
|
|
68
|
+
audience: config.string('JWT_AUDIENCE')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Storage configuration
|
|
73
|
+
*/
|
|
74
|
+
const storageSchema = {
|
|
75
|
+
provider: config.enum(
|
|
76
|
+
'STORAGE_PROVIDER',
|
|
77
|
+
['local', 's3', 'gcs', 'azure'] as const,
|
|
78
|
+
'local'
|
|
79
|
+
),
|
|
80
|
+
|
|
81
|
+
uploadPath: config.string('UPLOAD_PATH', './uploads'),
|
|
82
|
+
|
|
83
|
+
maxFileSize: {
|
|
84
|
+
type: 'number' as const,
|
|
85
|
+
env: 'MAX_FILE_SIZE',
|
|
86
|
+
default: 10485760, // 10MB
|
|
87
|
+
validate: (value: number) => value > 0 || 'Max file size must be positive'
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
allowedTypes: config.array('ALLOWED_FILE_TYPES', ['image/*', 'application/pdf']),
|
|
91
|
+
|
|
92
|
+
// S3 specific
|
|
93
|
+
s3Bucket: config.string('S3_BUCKET'),
|
|
94
|
+
s3Region: config.string('S3_REGION', 'us-east-1'),
|
|
95
|
+
s3AccessKey: config.string('S3_ACCESS_KEY'),
|
|
96
|
+
s3SecretKey: config.string('S3_SECRET_KEY')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Redis configuration
|
|
101
|
+
*/
|
|
102
|
+
const redisSchema = {
|
|
103
|
+
host: config.string('REDIS_HOST', 'localhost'),
|
|
104
|
+
port: config.number('REDIS_PORT', 6379),
|
|
105
|
+
password: config.string('REDIS_PASSWORD'),
|
|
106
|
+
db: config.number('REDIS_DB', 0),
|
|
107
|
+
|
|
108
|
+
keyPrefix: config.string('REDIS_KEY_PREFIX', 'fluxstack:'),
|
|
109
|
+
|
|
110
|
+
enableTls: config.boolean('REDIS_TLS', false)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Export all service configs as nested object
|
|
115
|
+
*/
|
|
116
|
+
export const servicesConfig = defineNestedConfig({
|
|
117
|
+
email: emailSchema,
|
|
118
|
+
jwt: jwtSchema,
|
|
119
|
+
storage: storageSchema,
|
|
120
|
+
redis: redisSchema
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
// Export types
|
|
124
|
+
export type EmailConfig = typeof servicesConfig.email
|
|
125
|
+
export type JWTConfig = typeof servicesConfig.jwt
|
|
126
|
+
export type StorageConfig = typeof servicesConfig.storage
|
|
127
|
+
export type RedisConfig = typeof servicesConfig.redis
|
|
128
|
+
|
|
129
|
+
// Export default
|
|
130
|
+
export default servicesConfig
|