create-fluxstack 1.7.5 โ 1.8.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/.dockerignore +82 -0
- package/Dockerfile +70 -0
- package/app/server/app.ts +20 -5
- package/app/server/backend-only.ts +15 -12
- package/app/server/index.ts +83 -96
- package/app/server/live/FluxStackConfig.ts +5 -5
- package/app/server/routes/env-test.ts +59 -0
- package/config/app.config.ts +2 -54
- package/config/client.config.ts +95 -0
- package/config/index.ts +57 -22
- package/config/monitoring.config.ts +114 -0
- package/config/plugins.config.ts +59 -0
- package/config/runtime.config.ts +0 -17
- package/config/server.config.ts +50 -30
- package/core/build/bundler.ts +17 -16
- package/core/build/flux-plugins-generator.ts +29 -18
- package/core/build/index.ts +32 -31
- package/core/build/live-components-generator.ts +29 -18
- package/core/build/optimizer.ts +37 -17
- package/core/cli/index.ts +6 -2
- package/core/config/env.ts +4 -0
- package/core/config/runtime-config.ts +10 -8
- package/core/config/schema.ts +24 -2
- package/core/framework/server.ts +1 -0
- package/core/index.ts +31 -23
- package/core/plugins/built-in/static/index.ts +73 -246
- package/core/plugins/built-in/vite/index.ts +377 -377
- package/core/plugins/registry.ts +22 -18
- package/core/server/backend-entry.ts +51 -0
- package/core/types/plugin.ts +6 -0
- package/core/utils/build-logger.ts +324 -0
- package/core/utils/config-schema.ts +2 -6
- package/core/utils/helpers.ts +14 -9
- package/core/utils/regenerate-files.ts +69 -0
- package/core/utils/version.ts +1 -1
- package/fluxstack.config.ts +138 -252
- package/package.json +2 -17
- package/vitest.config.ts +8 -26
- package/config/build.config.ts +0 -24
package/config/index.ts
CHANGED
|
@@ -5,72 +5,107 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```ts
|
|
8
|
-
* import { appConfig,
|
|
8
|
+
* import { appConfig, serverConfig, databaseConfig } from '@/config'
|
|
9
9
|
*
|
|
10
10
|
* // All configs are type-safe and validated!
|
|
11
|
-
* console.log(appConfig.name)
|
|
12
|
-
* console.log(
|
|
13
|
-
* console.log(
|
|
11
|
+
* console.log(appConfig.name) // string
|
|
12
|
+
* console.log(serverConfig.server.port) // number
|
|
13
|
+
* console.log(clientConfig.vite.port) // number
|
|
14
14
|
*
|
|
15
15
|
* // Nested configs
|
|
16
|
-
* console.log(servicesConfig.email.host)
|
|
17
|
-
* console.log(
|
|
16
|
+
* console.log(servicesConfig.email.host) // string
|
|
17
|
+
* console.log(monitoringConfig.metrics.enabled) // boolean
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// ๐ฆ CONFIG EXPORTS
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
21
25
|
export { appConfig } from './app.config'
|
|
26
|
+
export { serverConfig } from './server.config'
|
|
27
|
+
export { clientConfig } from './client.config'
|
|
22
28
|
export { databaseConfig } from './database.config'
|
|
23
29
|
export { servicesConfig } from './services.config'
|
|
24
|
-
export { serverConfig } from './server.config'
|
|
25
30
|
export { loggerConfig } from './logger.config'
|
|
26
|
-
export {
|
|
31
|
+
export { pluginsConfig } from './plugins.config'
|
|
32
|
+
export { monitoringConfig } from './monitoring.config'
|
|
27
33
|
export { appRuntimeConfig } from './runtime.config'
|
|
28
34
|
export { systemConfig, systemRuntimeInfo } from './system.config'
|
|
29
35
|
|
|
30
36
|
// Plugin configs (re-exported for convenience)
|
|
31
37
|
export { cryptoAuthConfig } from '../plugins/crypto-auth/config'
|
|
32
38
|
|
|
33
|
-
//
|
|
34
|
-
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// ๐ TYPE EXPORTS
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
// Core types
|
|
44
|
+
export type { AppConfig, Environment } from './app.config'
|
|
45
|
+
export type {
|
|
46
|
+
ServerConfig,
|
|
47
|
+
CorsConfig,
|
|
48
|
+
ServerFullConfig
|
|
49
|
+
} from './server.config'
|
|
50
|
+
export type {
|
|
51
|
+
ClientConfig,
|
|
52
|
+
ViteConfig,
|
|
53
|
+
ProxyConfig,
|
|
54
|
+
ClientBuildConfig
|
|
55
|
+
} from './client.config'
|
|
35
56
|
export type { DatabaseConfig } from './database.config'
|
|
36
|
-
export type { ServerConfig } from './server.config'
|
|
37
|
-
export type { LoggerConfig } from './logger.config'
|
|
38
|
-
export type { BuildConfig } from './build.config'
|
|
39
|
-
export type { SystemConfig, SystemRuntimeInfo } from './system.config'
|
|
40
57
|
export type {
|
|
41
58
|
EmailConfig,
|
|
42
59
|
JWTConfig,
|
|
43
60
|
StorageConfig,
|
|
44
61
|
RedisConfig
|
|
45
62
|
} from './services.config'
|
|
63
|
+
export type { LoggerConfig } from './logger.config'
|
|
64
|
+
export type { PluginsConfig } from './plugins.config'
|
|
65
|
+
export type {
|
|
66
|
+
MonitoringConfig,
|
|
67
|
+
MetricsConfig,
|
|
68
|
+
ProfilingConfig,
|
|
69
|
+
MonitoringFullConfig
|
|
70
|
+
} from './monitoring.config'
|
|
71
|
+
export type { SystemConfig, SystemRuntimeInfo } from './system.config'
|
|
46
72
|
|
|
47
73
|
// Plugin types
|
|
48
74
|
export type { CryptoAuthConfig } from '../plugins/crypto-auth/config'
|
|
49
75
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// ๐ฏ UNIFIED CONFIG OBJECT
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
53
80
|
import { appConfig } from './app.config'
|
|
81
|
+
import { serverConfig } from './server.config'
|
|
82
|
+
import { clientConfig } from './client.config'
|
|
54
83
|
import { databaseConfig } from './database.config'
|
|
55
84
|
import { servicesConfig } from './services.config'
|
|
56
|
-
import { serverConfig } from './server.config'
|
|
57
85
|
import { loggerConfig } from './logger.config'
|
|
58
|
-
import {
|
|
86
|
+
import { pluginsConfig } from './plugins.config'
|
|
87
|
+
import { monitoringConfig } from './monitoring.config'
|
|
59
88
|
import { appRuntimeConfig } from './runtime.config'
|
|
60
89
|
import { systemConfig, systemRuntimeInfo } from './system.config'
|
|
61
90
|
import { cryptoAuthConfig } from '../plugins/crypto-auth/config'
|
|
62
91
|
|
|
92
|
+
/**
|
|
93
|
+
* All configs in one object
|
|
94
|
+
* Use this when you need access to multiple configs at once
|
|
95
|
+
*/
|
|
63
96
|
export const config = {
|
|
64
97
|
app: appConfig,
|
|
98
|
+
server: serverConfig,
|
|
99
|
+
client: clientConfig,
|
|
65
100
|
database: databaseConfig,
|
|
66
101
|
services: servicesConfig,
|
|
67
|
-
server: serverConfig,
|
|
68
102
|
logger: loggerConfig,
|
|
69
|
-
|
|
103
|
+
plugins: pluginsConfig,
|
|
104
|
+
monitoring: monitoringConfig,
|
|
70
105
|
runtime: appRuntimeConfig,
|
|
71
106
|
system: systemConfig,
|
|
72
107
|
systemRuntime: systemRuntimeInfo,
|
|
73
108
|
cryptoAuth: cryptoAuthConfig
|
|
74
|
-
}
|
|
109
|
+
} as const
|
|
75
110
|
|
|
76
111
|
export default config
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monitoring Configuration
|
|
3
|
+
* Declarative monitoring, metrics and profiling configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, defineNestedConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
import { helpers } from '@/core/utils/env'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Metrics Configuration Schema
|
|
11
|
+
*/
|
|
12
|
+
const metricsSchema = {
|
|
13
|
+
enabled: config.boolean('ENABLE_METRICS', false),
|
|
14
|
+
|
|
15
|
+
collectInterval: {
|
|
16
|
+
type: 'number' as const,
|
|
17
|
+
env: 'METRICS_INTERVAL',
|
|
18
|
+
default: 5000,
|
|
19
|
+
validate: (value: number) => {
|
|
20
|
+
if (value < 1000) {
|
|
21
|
+
return 'Metrics interval must be at least 1000ms'
|
|
22
|
+
}
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
httpMetrics: config.boolean('HTTP_METRICS', true),
|
|
28
|
+
|
|
29
|
+
systemMetrics: config.boolean('SYSTEM_METRICS', true),
|
|
30
|
+
|
|
31
|
+
customMetrics: config.boolean('CUSTOM_METRICS', false),
|
|
32
|
+
|
|
33
|
+
// Metric exporters
|
|
34
|
+
exportToConsole: config.boolean('METRICS_EXPORT_CONSOLE', helpers.isDevelopment()),
|
|
35
|
+
|
|
36
|
+
exportToFile: config.boolean('METRICS_EXPORT_FILE', false),
|
|
37
|
+
|
|
38
|
+
exportToHttp: config.boolean('METRICS_EXPORT_HTTP', false),
|
|
39
|
+
|
|
40
|
+
exportHttpUrl: config.string('METRICS_EXPORT_URL'),
|
|
41
|
+
|
|
42
|
+
// Metric storage
|
|
43
|
+
retentionPeriod: config.number('METRICS_RETENTION_PERIOD', 3600000), // 1 hour in ms
|
|
44
|
+
|
|
45
|
+
maxDataPoints: config.number('METRICS_MAX_DATA_POINTS', 1000)
|
|
46
|
+
} as const
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Profiling Configuration Schema
|
|
50
|
+
*/
|
|
51
|
+
const profilingSchema = {
|
|
52
|
+
enabled: config.boolean('PROFILING_ENABLED', false),
|
|
53
|
+
|
|
54
|
+
sampleRate: {
|
|
55
|
+
type: 'number' as const,
|
|
56
|
+
env: 'PROFILING_SAMPLE_RATE',
|
|
57
|
+
default: helpers.isProduction() ? 0.01 : 0.1,
|
|
58
|
+
validate: (value: number) => {
|
|
59
|
+
if (value < 0 || value > 1) {
|
|
60
|
+
return 'Sample rate must be between 0 and 1'
|
|
61
|
+
}
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
memoryProfiling: config.boolean('MEMORY_PROFILING', false),
|
|
67
|
+
|
|
68
|
+
cpuProfiling: config.boolean('CPU_PROFILING', false),
|
|
69
|
+
|
|
70
|
+
heapSnapshot: config.boolean('HEAP_SNAPSHOT', false),
|
|
71
|
+
|
|
72
|
+
// Profiling output
|
|
73
|
+
outputDir: config.string('PROFILING_OUTPUT_DIR', 'profiling'),
|
|
74
|
+
|
|
75
|
+
maxProfiles: config.number('PROFILING_MAX_PROFILES', 10)
|
|
76
|
+
} as const
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Monitoring Configuration Schema
|
|
80
|
+
*/
|
|
81
|
+
const monitoringSchema = {
|
|
82
|
+
enabled: config.boolean('ENABLE_MONITORING', false),
|
|
83
|
+
|
|
84
|
+
// Exporters
|
|
85
|
+
exporters: config.array('MONITORING_EXPORTERS', []),
|
|
86
|
+
|
|
87
|
+
// Health checks
|
|
88
|
+
enableHealthChecks: config.boolean('ENABLE_HEALTH_CHECKS', true),
|
|
89
|
+
|
|
90
|
+
healthCheckInterval: config.number('HEALTH_CHECK_INTERVAL', 30000), // 30s
|
|
91
|
+
|
|
92
|
+
// Alerting
|
|
93
|
+
enableAlerts: config.boolean('ENABLE_ALERTS', false),
|
|
94
|
+
|
|
95
|
+
alertWebhook: config.string('ALERT_WEBHOOK')
|
|
96
|
+
} as const
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Export monitoring config (nested)
|
|
100
|
+
*/
|
|
101
|
+
export const monitoringConfig = defineNestedConfig({
|
|
102
|
+
monitoring: monitoringSchema,
|
|
103
|
+
metrics: metricsSchema,
|
|
104
|
+
profiling: profilingSchema
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Export types
|
|
108
|
+
export type MonitoringConfig = typeof monitoringConfig.monitoring
|
|
109
|
+
export type MetricsConfig = typeof monitoringConfig.metrics
|
|
110
|
+
export type ProfilingConfig = typeof monitoringConfig.profiling
|
|
111
|
+
export type MonitoringFullConfig = typeof monitoringConfig
|
|
112
|
+
|
|
113
|
+
// Export default
|
|
114
|
+
export default monitoringConfig
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugins Configuration
|
|
3
|
+
* Declarative plugin management configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
+
import { env } from '@/core/utils/env'
|
|
8
|
+
import { FLUXSTACK_VERSION } from '@/core/utils/version'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Plugins configuration schema
|
|
12
|
+
*/
|
|
13
|
+
const pluginsConfigSchema = {
|
|
14
|
+
// Plugin management
|
|
15
|
+
enabled: config.array(
|
|
16
|
+
'FLUXSTACK_PLUGINS_ENABLED',
|
|
17
|
+
['logger', 'swagger', 'vite', 'cors', 'static-files', 'crypto-auth']
|
|
18
|
+
),
|
|
19
|
+
|
|
20
|
+
disabled: config.array('FLUXSTACK_PLUGINS_DISABLED', []),
|
|
21
|
+
|
|
22
|
+
// Auto-discovery
|
|
23
|
+
autoDiscover: config.boolean('PLUGINS_AUTO_DISCOVER', true),
|
|
24
|
+
|
|
25
|
+
pluginsDir: config.string('PLUGINS_DIR', 'plugins'),
|
|
26
|
+
|
|
27
|
+
// Plugin-specific configurations
|
|
28
|
+
// Logger plugin (handled by logger.config.ts)
|
|
29
|
+
loggerEnabled: config.boolean('LOGGER_PLUGIN_ENABLED', true),
|
|
30
|
+
|
|
31
|
+
// Swagger plugin (enable/disable via runtime.config.ts)
|
|
32
|
+
swaggerTitle: config.string('SWAGGER_TITLE', 'FluxStack API'),
|
|
33
|
+
swaggerVersion: config.string('SWAGGER_VERSION', FLUXSTACK_VERSION),
|
|
34
|
+
swaggerDescription: config.string(
|
|
35
|
+
'SWAGGER_DESCRIPTION',
|
|
36
|
+
'API documentation for FluxStack application'
|
|
37
|
+
),
|
|
38
|
+
swaggerPath: config.string('SWAGGER_PATH', '/swagger'),
|
|
39
|
+
|
|
40
|
+
// Static files plugin
|
|
41
|
+
staticFilesEnabled: config.boolean('STATIC_FILES_ENABLED', true),
|
|
42
|
+
staticPublicDir: config.string('STATIC_PUBLIC_DIR', 'public'),
|
|
43
|
+
staticUploadsDir: config.string('STATIC_UPLOADS_DIR', 'uploads'),
|
|
44
|
+
staticCacheMaxAge: config.number('STATIC_CACHE_MAX_AGE', 31536000), // 1 year
|
|
45
|
+
staticEnableUploads: config.boolean('STATIC_ENABLE_UPLOADS', true),
|
|
46
|
+
staticEnablePublic: config.boolean('STATIC_ENABLE_PUBLIC', true),
|
|
47
|
+
|
|
48
|
+
// CORS plugin (configuration via server.config.ts)
|
|
49
|
+
// Vite plugin
|
|
50
|
+
viteEnabled: config.boolean('VITE_PLUGIN_ENABLED', true)
|
|
51
|
+
} as const
|
|
52
|
+
|
|
53
|
+
export const pluginsConfig = defineConfig(pluginsConfigSchema)
|
|
54
|
+
|
|
55
|
+
// Export type
|
|
56
|
+
export type PluginsConfig = typeof pluginsConfig
|
|
57
|
+
|
|
58
|
+
// Export default
|
|
59
|
+
export default pluginsConfig
|
package/config/runtime.config.ts
CHANGED
|
@@ -16,19 +16,6 @@ export const appRuntimeConfig = defineReactiveConfig({
|
|
|
16
16
|
enableMonitoring: config.boolean('ENABLE_MONITORING', false),
|
|
17
17
|
enableDebugMode: config.boolean('DEBUG', false),
|
|
18
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
19
|
// Rate limiting
|
|
33
20
|
rateLimitEnabled: config.boolean('RATE_LIMIT_ENABLED', true),
|
|
34
21
|
|
|
@@ -62,9 +49,6 @@ export const appRuntimeConfig = defineReactiveConfig({
|
|
|
62
49
|
validate: (value: number) => value > 0 || 'Max upload size must be positive'
|
|
63
50
|
},
|
|
64
51
|
|
|
65
|
-
// Allowed origins (can be updated in runtime)
|
|
66
|
-
corsOrigins: config.array('CORS_ORIGINS', ['*']),
|
|
67
|
-
|
|
68
52
|
// Maintenance mode
|
|
69
53
|
maintenanceMode: config.boolean('MAINTENANCE_MODE', false),
|
|
70
54
|
|
|
@@ -80,7 +64,6 @@ export const appRuntimeConfig = defineReactiveConfig({
|
|
|
80
64
|
appRuntimeConfig.watch((newConfig) => {
|
|
81
65
|
console.log('๐ Runtime config reloaded:')
|
|
82
66
|
console.log(' Debug:', newConfig.enableDebugMode)
|
|
83
|
-
console.log(' Log Level:', newConfig.logLevel)
|
|
84
67
|
console.log(' Maintenance:', newConfig.maintenanceMode)
|
|
85
68
|
})
|
|
86
69
|
|
package/config/server.config.ts
CHANGED
|
@@ -1,48 +1,68 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Server Configuration
|
|
3
|
-
*
|
|
3
|
+
* Server-specific settings (port, host, CORS, middleware)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
7
|
-
import { FLUXSTACK_VERSION } from '@/core/utils/version'
|
|
6
|
+
import { defineConfig, defineNestedConfig, config } from '@/core/utils/config-schema'
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* CORS configuration schema
|
|
10
|
+
*/
|
|
11
|
+
const corsSchema = {
|
|
12
|
+
origins: config.array('CORS_ORIGINS', ['http://localhost:3000', 'http://localhost:5173']),
|
|
13
|
+
methods: config.array('CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']),
|
|
14
|
+
headers: config.array('CORS_HEADERS', ['Content-Type', 'Authorization']),
|
|
15
|
+
credentials: config.boolean('CORS_CREDENTIALS', false),
|
|
16
|
+
maxAge: config.number('CORS_MAX_AGE', 86400)
|
|
17
|
+
} as const
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Server configuration schema
|
|
21
|
+
*/
|
|
22
|
+
const serverSchema = {
|
|
10
23
|
// Server basics
|
|
11
|
-
port:
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
port: {
|
|
25
|
+
type: 'number' as const,
|
|
26
|
+
env: 'PORT',
|
|
27
|
+
default: 3000,
|
|
28
|
+
required: true,
|
|
29
|
+
validate: (value: number) => {
|
|
30
|
+
if (value < 1 || value > 65535) {
|
|
31
|
+
return 'Port must be between 1 and 65535'
|
|
32
|
+
}
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
14
36
|
|
|
15
|
-
|
|
16
|
-
corsOrigins: config.array('CORS_ORIGINS', ['http://localhost:3000', 'http://localhost:5173']),
|
|
17
|
-
corsMethods: config.array('CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']),
|
|
18
|
-
corsHeaders: config.array('CORS_HEADERS', ['Content-Type', 'Authorization']),
|
|
19
|
-
corsCredentials: config.boolean('CORS_CREDENTIALS', false),
|
|
20
|
-
corsMaxAge: config.number('CORS_MAX_AGE', 86400),
|
|
37
|
+
host: config.string('HOST', 'localhost', true),
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
apiPrefix: {
|
|
40
|
+
type: 'string' as const,
|
|
41
|
+
env: 'API_PREFIX',
|
|
42
|
+
default: '/api',
|
|
43
|
+
validate: (value: string) => value.startsWith('/') || 'API prefix must start with /'
|
|
44
|
+
},
|
|
27
45
|
|
|
28
46
|
// Backend-only mode
|
|
29
47
|
backendPort: config.number('BACKEND_PORT', 3001),
|
|
30
48
|
|
|
31
|
-
// App info
|
|
32
|
-
appName: config.string('FLUXSTACK_APP_NAME', 'FluxStack'),
|
|
33
|
-
appVersion: config.string('FLUXSTACK_APP_VERSION', FLUXSTACK_VERSION),
|
|
34
|
-
|
|
35
49
|
// Features
|
|
36
|
-
enableSwagger: config.boolean('ENABLE_SWAGGER', true),
|
|
37
|
-
enableMetrics: config.boolean('ENABLE_METRICS', false),
|
|
38
|
-
enableMonitoring: config.boolean('ENABLE_MONITORING', false),
|
|
39
50
|
enableRequestLogging: config.boolean('ENABLE_REQUEST_LOGGING', true),
|
|
40
|
-
|
|
41
|
-
// Vite/Development
|
|
42
|
-
enableViteProxyLogs: config.boolean('ENABLE_VITE_PROXY_LOGS', false)
|
|
51
|
+
showBanner: config.boolean('SHOW_SERVER_BANNER', true)
|
|
43
52
|
} as const
|
|
44
53
|
|
|
45
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Export server config (nested with CORS)
|
|
56
|
+
*/
|
|
57
|
+
export const serverConfig = defineNestedConfig({
|
|
58
|
+
server: serverSchema,
|
|
59
|
+
cors: corsSchema
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// Export types
|
|
63
|
+
export type ServerConfig = typeof serverConfig.server
|
|
64
|
+
export type CorsConfig = typeof serverConfig.cors
|
|
65
|
+
export type ServerFullConfig = typeof serverConfig
|
|
46
66
|
|
|
47
|
-
|
|
67
|
+
// Export default
|
|
48
68
|
export default serverConfig
|
package/core/build/bundler.ts
CHANGED
|
@@ -3,11 +3,13 @@ import { existsSync, mkdirSync } from "fs"
|
|
|
3
3
|
import { join } from "path"
|
|
4
4
|
import type { FluxStackConfig } from "../config"
|
|
5
5
|
import type { BundleResult, BundleOptions } from "../types/build"
|
|
6
|
+
import { buildLogger } from "../utils/build-logger"
|
|
6
7
|
|
|
7
8
|
export interface BundlerConfig {
|
|
8
9
|
target: 'bun' | 'node' | 'docker'
|
|
9
10
|
outDir: string
|
|
10
11
|
sourceMaps: boolean
|
|
12
|
+
minify?: boolean
|
|
11
13
|
external?: string[]
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -19,8 +21,9 @@ export class Bundler {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
async bundleClient(options: BundleOptions = {}): Promise<BundleResult> {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
buildLogger.section('Client Build', 'โก')
|
|
25
|
+
buildLogger.step('Starting Vite build...')
|
|
26
|
+
|
|
24
27
|
const startTime = Date.now()
|
|
25
28
|
|
|
26
29
|
try {
|
|
@@ -41,9 +44,9 @@ export class Bundler {
|
|
|
41
44
|
|
|
42
45
|
const exitCode = await buildProcess.exited
|
|
43
46
|
const duration = Date.now() - startTime
|
|
44
|
-
|
|
47
|
+
|
|
45
48
|
if (exitCode === 0) {
|
|
46
|
-
|
|
49
|
+
buildLogger.success(`Client bundle completed in ${buildLogger.formatDuration(duration)}`)
|
|
47
50
|
return {
|
|
48
51
|
success: true,
|
|
49
52
|
duration,
|
|
@@ -52,7 +55,7 @@ export class Bundler {
|
|
|
52
55
|
}
|
|
53
56
|
} else {
|
|
54
57
|
const stderr = await new Response(buildProcess.stderr).text()
|
|
55
|
-
|
|
58
|
+
buildLogger.error("Client bundle failed")
|
|
56
59
|
return {
|
|
57
60
|
success: false,
|
|
58
61
|
duration,
|
|
@@ -70,23 +73,21 @@ export class Bundler {
|
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
async bundleServer(entryPoint: string, options: BundleOptions = {}): Promise<BundleResult> {
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
buildLogger.section('Server Build', 'โก')
|
|
77
|
+
|
|
75
78
|
const startTime = Date.now()
|
|
76
79
|
let liveComponentsGenerator: any = null
|
|
77
|
-
|
|
80
|
+
|
|
78
81
|
try {
|
|
79
82
|
// ๐ PRE-BUILD: Auto-generate Live Components registration
|
|
80
83
|
const generatorModule = await import('./live-components-generator')
|
|
81
84
|
liveComponentsGenerator = generatorModule.liveComponentsGenerator
|
|
82
85
|
const discoveredComponents = await liveComponentsGenerator.preBuild()
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
|
|
85
87
|
// ๐ PRE-BUILD: Auto-generate FluxStack Plugins registration
|
|
86
88
|
const pluginsGeneratorModule = await import('./flux-plugins-generator')
|
|
87
89
|
const fluxPluginsGenerator = pluginsGeneratorModule.fluxPluginsGenerator
|
|
88
90
|
const discoveredPlugins = await fluxPluginsGenerator.preBuild()
|
|
89
|
-
console.log(`๐ Auto-discovered ${discoveredPlugins.length} FluxStack Plugins for bundle`)
|
|
90
91
|
|
|
91
92
|
// Ensure output directory exists
|
|
92
93
|
if (!existsSync(this.config.outDir)) {
|
|
@@ -130,12 +131,12 @@ export class Bundler {
|
|
|
130
131
|
|
|
131
132
|
const exitCode = await buildProcess.exited
|
|
132
133
|
const duration = Date.now() - startTime
|
|
133
|
-
|
|
134
|
+
|
|
134
135
|
// ๐งน POST-BUILD: Handle auto-generated registration file
|
|
135
136
|
// (liveComponentsGenerator already available from above)
|
|
136
|
-
|
|
137
|
+
|
|
137
138
|
if (exitCode === 0) {
|
|
138
|
-
|
|
139
|
+
buildLogger.success(`Server bundle completed in ${buildLogger.formatDuration(duration)}`)
|
|
139
140
|
|
|
140
141
|
// Keep generated files for production (they're now baked into bundle)
|
|
141
142
|
await liveComponentsGenerator.postBuild(false)
|
|
@@ -152,7 +153,7 @@ export class Bundler {
|
|
|
152
153
|
entryPoint: join(this.config.outDir, "index.js")
|
|
153
154
|
}
|
|
154
155
|
} else {
|
|
155
|
-
|
|
156
|
+
buildLogger.error("Server bundle failed")
|
|
156
157
|
|
|
157
158
|
// Restore original files since build failed
|
|
158
159
|
await liveComponentsGenerator.postBuild(false)
|
|
@@ -183,7 +184,7 @@ export class Bundler {
|
|
|
183
184
|
const fluxPluginsGenerator = pluginsGeneratorModule.fluxPluginsGenerator
|
|
184
185
|
await fluxPluginsGenerator.postBuild(false)
|
|
185
186
|
} catch (cleanupError) {
|
|
186
|
-
|
|
187
|
+
buildLogger.warn(`Failed to cleanup generated files: ${cleanupError}`)
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
return {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { existsSync, readdirSync, writeFileSync, unlinkSync, readFileSync, statSync } from 'fs'
|
|
5
5
|
import { join, extname, basename } from 'path'
|
|
6
|
+
import { buildLogger } from '../utils/build-logger'
|
|
6
7
|
|
|
7
8
|
export interface PluginInfo {
|
|
8
9
|
pluginDir: string
|
|
@@ -36,8 +37,6 @@ export class FluxPluginsGenerator {
|
|
|
36
37
|
if (existsSync(this.pluginsPath)) {
|
|
37
38
|
const externalPlugins = this.discoverPluginsInDirectory(this.pluginsPath, 'external')
|
|
38
39
|
plugins.push(...externalPlugins)
|
|
39
|
-
} else {
|
|
40
|
-
console.log('โ ๏ธ No external plugins directory found (plugins/)')
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
// Note: Built-in plugins are automatically loaded by core system
|
|
@@ -78,13 +77,13 @@ export class FluxPluginsGenerator {
|
|
|
78
77
|
type
|
|
79
78
|
})
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
buildLogger.step(`Discovered ${type} plugin: ${entry} (${entryFile})`)
|
|
82
81
|
} else {
|
|
83
|
-
|
|
82
|
+
buildLogger.warn(`Plugin '${entry}' has no valid entry point`)
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
} catch (error) {
|
|
87
|
-
|
|
86
|
+
// Silently skip directories that can't be scanned
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
return plugins
|
|
@@ -122,7 +121,6 @@ export class FluxPluginsGenerator {
|
|
|
122
121
|
if (existsSync(this.registrationFilePath)) {
|
|
123
122
|
const existingContent = readFileSync(this.registrationFilePath, 'utf-8')
|
|
124
123
|
writeFileSync(this.backupFilePath, existingContent)
|
|
125
|
-
console.log('๐ Backed up existing auto-registry.ts')
|
|
126
124
|
}
|
|
127
125
|
|
|
128
126
|
// All discovered plugins are external (built-in are handled by core)
|
|
@@ -198,7 +196,7 @@ console.log('๐ Auto-discovered ${plugins.length} external plugins' + (pluginN
|
|
|
198
196
|
`
|
|
199
197
|
|
|
200
198
|
writeFileSync(this.registrationFilePath, fileContent)
|
|
201
|
-
|
|
199
|
+
buildLogger.success(`Generated registry for ${plugins.length} plugins`)
|
|
202
200
|
}
|
|
203
201
|
|
|
204
202
|
/**
|
|
@@ -220,12 +218,10 @@ console.log('๐ Auto-discovered ${plugins.length} external plugins' + (pluginN
|
|
|
220
218
|
const backupContent = readFileSync(this.backupFilePath, 'utf-8')
|
|
221
219
|
writeFileSync(this.registrationFilePath, backupContent)
|
|
222
220
|
unlinkSync(this.backupFilePath)
|
|
223
|
-
console.log('๐ Restored original auto-registry.ts')
|
|
224
221
|
} else {
|
|
225
222
|
// If no backup exists, remove the generated file
|
|
226
223
|
if (existsSync(this.registrationFilePath)) {
|
|
227
224
|
unlinkSync(this.registrationFilePath)
|
|
228
|
-
console.log('๐๏ธ Removed auto-generated registry file')
|
|
229
225
|
}
|
|
230
226
|
}
|
|
231
227
|
}
|
|
@@ -246,17 +242,33 @@ console.log('๐ Auto-discovered ${plugins.length} external plugins' + (pluginN
|
|
|
246
242
|
* Pre-build hook: Generate registration file
|
|
247
243
|
*/
|
|
248
244
|
async preBuild(): Promise<PluginInfo[]> {
|
|
249
|
-
|
|
250
|
-
|
|
245
|
+
buildLogger.section('FluxStack Plugins Discovery', '๐')
|
|
246
|
+
|
|
251
247
|
const plugins = this.discoverPlugins()
|
|
252
|
-
|
|
248
|
+
|
|
253
249
|
if (plugins.length === 0) {
|
|
254
|
-
|
|
250
|
+
buildLogger.warn('No FluxStack Plugins found')
|
|
255
251
|
return []
|
|
256
252
|
}
|
|
257
253
|
|
|
254
|
+
// Create table of discovered plugins
|
|
255
|
+
const pluginData = plugins.map(p => ({
|
|
256
|
+
plugin: p.pluginName,
|
|
257
|
+
type: p.type,
|
|
258
|
+
entry: p.entryFile
|
|
259
|
+
}))
|
|
260
|
+
|
|
261
|
+
buildLogger.table(
|
|
262
|
+
[
|
|
263
|
+
{ header: 'Plugin', key: 'plugin', width: 25, align: 'left', color: 'cyan' },
|
|
264
|
+
{ header: 'Type', key: 'type', width: 12, align: 'left', color: 'yellow' },
|
|
265
|
+
{ header: 'Entry Point', key: 'entry', width: 20, align: 'left', color: 'gray' }
|
|
266
|
+
],
|
|
267
|
+
pluginData
|
|
268
|
+
)
|
|
269
|
+
|
|
258
270
|
this.generateRegistrationFile(plugins)
|
|
259
|
-
|
|
271
|
+
|
|
260
272
|
return plugins
|
|
261
273
|
}
|
|
262
274
|
|
|
@@ -264,10 +276,9 @@ console.log('๐ Auto-discovered ${plugins.length} external plugins' + (pluginN
|
|
|
264
276
|
* Post-build hook: Clean up generated file (optional)
|
|
265
277
|
*/
|
|
266
278
|
async postBuild(keepGenerated: boolean = false): Promise<void> {
|
|
267
|
-
|
|
268
|
-
|
|
279
|
+
buildLogger.step('Cleaning up FluxStack Plugins registry...')
|
|
280
|
+
|
|
269
281
|
if (keepGenerated) {
|
|
270
|
-
console.log('๐ Keeping auto-generated plugin registry for production')
|
|
271
282
|
// Remove backup since we're keeping the generated version
|
|
272
283
|
if (existsSync(this.backupFilePath)) {
|
|
273
284
|
unlinkSync(this.backupFilePath)
|
|
@@ -304,7 +315,7 @@ console.log('๐ Auto-discovered ${plugins.length} external plugins' + (pluginN
|
|
|
304
315
|
*/
|
|
305
316
|
updateIfNeeded(): void {
|
|
306
317
|
if (this.needsUpdate()) {
|
|
307
|
-
|
|
318
|
+
buildLogger.info('FluxStack Plugins changed, updating registry...')
|
|
308
319
|
const plugins = this.discoverPlugins()
|
|
309
320
|
this.generateRegistrationFile(plugins)
|
|
310
321
|
}
|