create-fluxstack 1.1.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1 -1
- 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/index.ts +10 -4
- package/core/cli/generators/index.ts +5 -2
- package/core/cli/generators/plugin.ts +290 -0
- package/core/cli/index.ts +117 -15
- package/core/config/env.ts +37 -95
- package/core/config/runtime-config.ts +61 -58
- package/core/config/schema.ts +4 -0
- package/core/framework/server.ts +22 -10
- package/core/plugins/built-in/index.ts +7 -17
- 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 +12 -12
- 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 +4 -4
- 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 +118 -8
- package/fluxstack.config.ts +2 -2
- package/package.json +117 -115
- 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,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
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System Runtime Configuration
|
|
3
|
+
* System information and environment variables
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* System environment variables config
|
|
10
|
+
*/
|
|
11
|
+
export const systemConfig = defineConfig({
|
|
12
|
+
// User/System info
|
|
13
|
+
user: config.string('USER', ''),
|
|
14
|
+
username: config.string('USERNAME', ''),
|
|
15
|
+
home: config.string('HOME', ''),
|
|
16
|
+
userProfile: config.string('USERPROFILE', ''),
|
|
17
|
+
|
|
18
|
+
// Paths
|
|
19
|
+
pwd: config.string('PWD', ''),
|
|
20
|
+
path: config.string('PATH', ''),
|
|
21
|
+
|
|
22
|
+
// Shell
|
|
23
|
+
shell: config.string('SHELL', ''),
|
|
24
|
+
term: config.string('TERM', ''),
|
|
25
|
+
|
|
26
|
+
// Common environment variables
|
|
27
|
+
lang: config.string('LANG', 'en_US.UTF-8'),
|
|
28
|
+
tmpDir: config.string('TMPDIR', ''),
|
|
29
|
+
|
|
30
|
+
// CI/CD detection
|
|
31
|
+
ci: config.boolean('CI', false),
|
|
32
|
+
|
|
33
|
+
// Computed helpers (not from env)
|
|
34
|
+
get currentUser() {
|
|
35
|
+
return this.user || this.username || 'unknown'
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
get homeDirectory() {
|
|
39
|
+
return this.home || this.userProfile || ''
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
get isCI() {
|
|
43
|
+
return this.ci
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* System runtime info (from Node.js/Bun process)
|
|
49
|
+
* These are not from environment variables, but from runtime
|
|
50
|
+
*/
|
|
51
|
+
export const systemRuntimeInfo = {
|
|
52
|
+
get nodeVersion() {
|
|
53
|
+
return process.version
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
get bunVersion() {
|
|
57
|
+
return (process.versions as any).bun || 'N/A'
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
get platform() {
|
|
61
|
+
return process.platform
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
get architecture() {
|
|
65
|
+
return process.arch
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
get cpuCount() {
|
|
69
|
+
return require('os').cpus().length
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
get totalMemory() {
|
|
73
|
+
const os = require('os')
|
|
74
|
+
return Math.round(os.totalmem() / 1024 / 1024 / 1024 * 100) / 100 // GB
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
get workingDirectory() {
|
|
78
|
+
return process.cwd()
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
get executablePath() {
|
|
82
|
+
return process.execPath
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
get uptime() {
|
|
86
|
+
return process.uptime()
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
get memoryUsage() {
|
|
90
|
+
const usage = process.memoryUsage()
|
|
91
|
+
return {
|
|
92
|
+
rss: Math.round(usage.rss / 1024 / 1024 * 100) / 100, // MB
|
|
93
|
+
heapTotal: Math.round(usage.heapTotal / 1024 / 1024 * 100) / 100,
|
|
94
|
+
heapUsed: Math.round(usage.heapUsed / 1024 / 1024 * 100) / 100,
|
|
95
|
+
external: Math.round(usage.external / 1024 / 1024 * 100) / 100
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Export types
|
|
101
|
+
export type SystemConfig = typeof systemConfig
|
|
102
|
+
export type SystemRuntimeInfo = typeof systemRuntimeInfo
|
|
103
|
+
|
|
104
|
+
// Export default
|
|
105
|
+
export default systemConfig
|
package/core/build/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { copyFileSync, writeFileSync, existsSync, mkdirSync } from "fs"
|
|
1
|
+
import { copyFileSync, writeFileSync, existsSync, mkdirSync, readFileSync } from "fs"
|
|
2
2
|
import { join } from "path"
|
|
3
3
|
import type { FluxStackConfig } from "../config"
|
|
4
4
|
import type { BuildResult, BuildManifest } from "../types/build"
|
|
@@ -177,9 +177,15 @@ coverage
|
|
|
177
177
|
console.log(` - target path: ${distEnvPath}`)
|
|
178
178
|
|
|
179
179
|
if (existsSync(envPath)) {
|
|
180
|
-
console.log(`📄 Copying .env file...`)
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
console.log(`📄 Copying .env file and setting production mode...`)
|
|
181
|
+
// Read .env content
|
|
182
|
+
let envContent = readFileSync(envPath, 'utf-8')
|
|
183
|
+
// Replace development with production
|
|
184
|
+
envContent = envContent.replace(/NODE_ENV=development/g, 'NODE_ENV=production')
|
|
185
|
+
envContent = envContent.replace(/VITE_NODE_ENV=development/g, 'VITE_NODE_ENV=production')
|
|
186
|
+
// Write to dist
|
|
187
|
+
writeFileSync(distEnvPath, envContent)
|
|
188
|
+
console.log("📄 Environment file copied to dist/ (NODE_ENV=production)")
|
|
183
189
|
} else if (existsSync(envExamplePath)) {
|
|
184
190
|
console.log(`📄 Copying .env.example file...`)
|
|
185
191
|
copyFileSync(envExamplePath, distEnvPath)
|
|
@@ -3,6 +3,7 @@ import { ControllerGenerator } from "./controller.js"
|
|
|
3
3
|
import { RouteGenerator } from "./route.js"
|
|
4
4
|
import { ComponentGenerator } from "./component.js"
|
|
5
5
|
import { ServiceGenerator } from "./service.js"
|
|
6
|
+
import { PluginGenerator } from "./plugin.js"
|
|
6
7
|
import type { GeneratorContext, GeneratorOptions } from "./types.js"
|
|
7
8
|
|
|
8
9
|
export interface Generator {
|
|
@@ -23,6 +24,7 @@ export class GeneratorRegistry {
|
|
|
23
24
|
this.register(new RouteGenerator())
|
|
24
25
|
this.register(new ComponentGenerator())
|
|
25
26
|
this.register(new ServiceGenerator())
|
|
27
|
+
this.register(new PluginGenerator())
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
register(generator: Generator): void {
|
|
@@ -58,7 +60,8 @@ export const generateCommand: CliCommand = {
|
|
|
58
60
|
'flux generate controller user',
|
|
59
61
|
'flux generate component UserCard',
|
|
60
62
|
'flux generate service auth',
|
|
61
|
-
'flux generate route api/users'
|
|
63
|
+
'flux generate route api/users',
|
|
64
|
+
'flux generate plugin my-plugin'
|
|
62
65
|
],
|
|
63
66
|
arguments: [
|
|
64
67
|
{
|
|
@@ -66,7 +69,7 @@ export const generateCommand: CliCommand = {
|
|
|
66
69
|
description: 'Type of code to generate',
|
|
67
70
|
required: true,
|
|
68
71
|
type: 'string',
|
|
69
|
-
choices: ['controller', 'route', 'component', 'service']
|
|
72
|
+
choices: ['controller', 'route', 'component', 'service', 'plugin']
|
|
70
73
|
},
|
|
71
74
|
{
|
|
72
75
|
name: 'name',
|