create-fluxstack 1.7.5 → 1.8.3
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/.env.example +19 -0
- package/Dockerfile +70 -0
- package/README.md +6 -3
- package/app/client/SIMPLIFICATION.md +140 -0
- package/app/client/frontend-only.ts +1 -1
- package/app/client/src/App.tsx +148 -283
- package/app/client/src/index.css +5 -20
- package/app/client/src/lib/eden-api.ts +53 -220
- package/app/client/src/main.tsx +2 -3
- package/app/server/app.ts +20 -5
- package/app/server/backend-only.ts +15 -12
- package/app/server/controllers/users.controller.ts +57 -31
- package/app/server/index.ts +86 -96
- package/app/server/live/register-components.ts +18 -7
- package/app/server/routes/env-test.ts +110 -0
- package/app/server/routes/index.ts +1 -8
- package/app/server/routes/users.routes.ts +192 -91
- package/config/app.config.ts +2 -54
- package/config/client.config.ts +95 -0
- package/config/fluxstack.config.ts +2 -2
- package/config/index.ts +57 -22
- package/config/monitoring.config.ts +114 -0
- package/config/plugins.config.ts +80 -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 +34 -23
- package/core/build/index.ts +32 -31
- package/core/build/live-components-generator.ts +44 -30
- package/core/build/optimizer.ts +37 -17
- package/core/cli/command-registry.ts +4 -14
- package/core/cli/commands/plugin-deps.ts +8 -8
- package/core/cli/generators/component.ts +3 -3
- package/core/cli/generators/controller.ts +4 -4
- package/core/cli/generators/index.ts +8 -8
- package/core/cli/generators/interactive.ts +4 -4
- package/core/cli/generators/plugin.ts +3 -3
- package/core/cli/generators/prompts.ts +1 -1
- package/core/cli/generators/route.ts +27 -11
- package/core/cli/generators/service.ts +5 -5
- package/core/cli/generators/template-engine.ts +1 -1
- package/core/cli/generators/types.ts +1 -1
- package/core/cli/index.ts +158 -189
- package/core/cli/plugin-discovery.ts +3 -3
- package/core/client/hooks/index.ts +2 -2
- package/core/client/hooks/state-validator.ts +1 -1
- package/core/client/hooks/useAuth.ts +1 -1
- package/core/client/hooks/useChunkedUpload.ts +1 -1
- package/core/client/hooks/useHybridLiveComponent.ts +1 -1
- package/core/client/hooks/useWebSocket.ts +1 -1
- package/core/config/env.ts +5 -1
- package/core/config/runtime-config.ts +12 -10
- package/core/config/schema.ts +33 -2
- package/core/framework/server.ts +30 -14
- package/core/framework/types.ts +2 -2
- package/core/index.ts +31 -23
- package/core/live/ComponentRegistry.ts +1 -1
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
- package/core/plugins/built-in/live-components/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +65 -161
- package/core/plugins/built-in/static/index.ts +75 -277
- package/core/plugins/built-in/swagger/index.ts +301 -231
- package/core/plugins/built-in/vite/index.ts +342 -377
- package/core/plugins/config.ts +2 -2
- package/core/plugins/dependency-manager.ts +2 -2
- package/core/plugins/discovery.ts +1 -1
- package/core/plugins/executor.ts +2 -2
- package/core/plugins/manager.ts +19 -4
- package/core/plugins/module-resolver.ts +1 -1
- package/core/plugins/registry.ts +25 -21
- package/core/plugins/types.ts +147 -5
- package/core/server/backend-entry.ts +51 -0
- package/core/server/framework.ts +2 -2
- package/core/server/live/ComponentRegistry.ts +9 -26
- package/core/server/live/FileUploadManager.ts +1 -1
- package/core/server/live/auto-generated-components.ts +26 -0
- package/core/server/live/websocket-plugin.ts +211 -19
- package/core/server/middleware/errorHandling.ts +1 -1
- package/core/server/middleware/index.ts +4 -4
- package/core/server/plugins/database.ts +1 -2
- package/core/server/plugins/static-files-plugin.ts +259 -231
- package/core/server/plugins/swagger.ts +1 -1
- package/core/server/services/BaseService.ts +1 -1
- package/core/server/services/ServiceContainer.ts +1 -1
- package/core/server/services/index.ts +4 -4
- package/core/server/standalone.ts +16 -1
- package/core/testing/index.ts +1 -1
- package/core/testing/setup.ts +1 -1
- 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/logger/startup-banner.ts +7 -33
- package/core/utils/regenerate-files.ts +69 -0
- package/core/utils/version.ts +6 -6
- package/create-fluxstack.ts +68 -25
- package/fluxstack.config.ts +138 -252
- package/package.json +3 -18
- package/plugins/crypto-auth/index.ts +52 -47
- package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
- package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
- package/vitest.config.ts +17 -26
- package/app/client/src/App.css +0 -883
- package/app/client/src/components/ErrorBoundary.tsx +0 -107
- package/app/client/src/components/ErrorDisplay.css +0 -365
- package/app/client/src/components/ErrorDisplay.tsx +0 -258
- package/app/client/src/components/FluxStackConfig.tsx +0 -1321
- package/app/client/src/components/HybridLiveCounter.tsx +0 -140
- package/app/client/src/components/LiveClock.tsx +0 -286
- package/app/client/src/components/MainLayout.tsx +0 -388
- package/app/client/src/components/SidebarNavigation.tsx +0 -391
- package/app/client/src/components/StateDemo.tsx +0 -178
- package/app/client/src/components/SystemMonitor.tsx +0 -1044
- package/app/client/src/components/UserProfile.tsx +0 -809
- package/app/client/src/hooks/useAuth.ts +0 -39
- package/app/client/src/hooks/useNotifications.ts +0 -56
- package/app/client/src/lib/errors.ts +0 -340
- package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
- package/app/client/src/lib/index.ts +0 -45
- package/app/client/src/pages/ApiDocs.tsx +0 -182
- package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
- package/app/client/src/pages/Demo.tsx +0 -174
- package/app/client/src/pages/HybridLive.tsx +0 -263
- package/app/client/src/pages/Overview.tsx +0 -155
- package/app/client/src/store/README.md +0 -43
- package/app/client/src/store/index.ts +0 -16
- package/app/client/src/store/slices/uiSlice.ts +0 -151
- package/app/client/src/store/slices/userSlice.ts +0 -161
- package/app/client/src/test/README.md +0 -257
- package/app/client/src/test/setup.ts +0 -70
- package/app/client/src/test/types.ts +0 -12
- package/app/server/live/CounterComponent.ts +0 -191
- package/app/server/live/FluxStackConfig.ts +0 -534
- package/app/server/live/SidebarNavigation.ts +0 -157
- package/app/server/live/SystemMonitor.ts +0 -595
- package/app/server/live/SystemMonitorIntegration.ts +0 -151
- package/app/server/live/UserProfileComponent.ts +0 -141
- package/app/server/middleware/auth.ts +0 -136
- package/app/server/middleware/errorHandling.ts +0 -252
- package/app/server/middleware/index.ts +0 -10
- package/app/server/middleware/rateLimit.ts +0 -193
- package/app/server/middleware/requestLogging.ts +0 -215
- package/app/server/middleware/validation.ts +0 -270
- package/app/server/routes/config.ts +0 -145
- package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
- package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
- package/app/server/routes/exemplo-posts.routes.ts +0 -161
- package/app/server/routes/upload.ts +0 -92
- package/app/server/services/NotificationService.ts +0 -302
- package/app/server/services/UserService.ts +0 -222
- package/app/server/services/index.ts +0 -46
- package/app/server/types/index.ts +0 -1
- package/config/build.config.ts +0 -24
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
|
|
@@ -96,12 +95,12 @@ export class FluxPluginsGenerator {
|
|
|
96
95
|
private findPluginEntryFile(pluginDir: string): string | null {
|
|
97
96
|
const possibleFiles = [
|
|
98
97
|
'index.ts',
|
|
99
|
-
'index
|
|
98
|
+
'index',
|
|
100
99
|
'plugin.ts',
|
|
101
|
-
'plugin
|
|
100
|
+
'plugin',
|
|
102
101
|
'src/index.ts',
|
|
103
|
-
'src/index
|
|
104
|
-
'dist/index
|
|
102
|
+
'src/index',
|
|
103
|
+
'dist/index'
|
|
105
104
|
]
|
|
106
105
|
|
|
107
106
|
for (const file of possibleFiles) {
|
|
@@ -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)
|
|
@@ -132,7 +130,7 @@ export class FluxPluginsGenerator {
|
|
|
132
130
|
const imports = plugins
|
|
133
131
|
.map(plugin => {
|
|
134
132
|
const importName = this.getImportName(plugin.pluginName)
|
|
135
|
-
const importPath = plugin.entryFile === 'index.ts' || plugin.entryFile === 'index
|
|
133
|
+
const importPath = plugin.entryFile === 'index.ts' || plugin.entryFile === 'index'
|
|
136
134
|
? plugin.relativePath
|
|
137
135
|
: `${plugin.relativePath}/${plugin.entryFile.replace(/\.(ts|js)$/, '')}`
|
|
138
136
|
return `import ${importName} from "${importPath}"`
|
|
@@ -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
|
}
|
package/core/build/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { BuildResult, BuildManifest } from "../types/build"
|
|
|
5
5
|
import { Bundler } from "./bundler"
|
|
6
6
|
import { Optimizer } from "./optimizer"
|
|
7
7
|
import { FLUXSTACK_VERSION } from "../utils/version"
|
|
8
|
+
import { buildLogger } from "../utils/build-logger"
|
|
8
9
|
|
|
9
10
|
export class FluxStackBuilder {
|
|
10
11
|
private config: FluxStackConfig
|
|
@@ -19,6 +20,7 @@ export class FluxStackBuilder {
|
|
|
19
20
|
target: config.build.target,
|
|
20
21
|
outDir: config.build.outDir,
|
|
21
22
|
sourceMaps: config.build.sourceMaps,
|
|
23
|
+
minify: config.build.minify,
|
|
22
24
|
external: config.build.external
|
|
23
25
|
})
|
|
24
26
|
|
|
@@ -46,18 +48,18 @@ export class FluxStackBuilder {
|
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
async createDockerFiles() {
|
|
49
|
-
|
|
51
|
+
buildLogger.section('Docker Configuration', '🐳')
|
|
50
52
|
|
|
51
53
|
const distDir = this.config.build.outDir
|
|
52
|
-
|
|
54
|
+
buildLogger.step(`Output directory: ${distDir}`)
|
|
53
55
|
|
|
54
56
|
// Ensure dist directory exists
|
|
55
57
|
if (!existsSync(distDir)) {
|
|
56
|
-
|
|
58
|
+
buildLogger.step(`Creating directory: ${distDir}`)
|
|
57
59
|
mkdirSync(distDir, { recursive: true })
|
|
58
|
-
|
|
60
|
+
buildLogger.success('Directory created successfully')
|
|
59
61
|
} else {
|
|
60
|
-
|
|
62
|
+
buildLogger.success('Directory already exists')
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// Dockerfile optimizado para produção
|
|
@@ -156,14 +158,14 @@ coverage
|
|
|
156
158
|
|
|
157
159
|
// Escrever arquivos no dist
|
|
158
160
|
try {
|
|
159
|
-
|
|
161
|
+
buildLogger.step('Writing Dockerfile...')
|
|
160
162
|
writeFileSync(join(distDir, "Dockerfile"), dockerfile)
|
|
161
|
-
|
|
163
|
+
buildLogger.step('Writing docker-compose.yml...')
|
|
162
164
|
writeFileSync(join(distDir, "docker-compose.yml"), dockerCompose)
|
|
163
|
-
|
|
165
|
+
buildLogger.step('Writing .dockerignore...')
|
|
164
166
|
writeFileSync(join(distDir, ".dockerignore"), dockerignore)
|
|
165
167
|
} catch (error) {
|
|
166
|
-
|
|
168
|
+
buildLogger.error(`Error writing Docker files: ${error}`)
|
|
167
169
|
throw error
|
|
168
170
|
}
|
|
169
171
|
|
|
@@ -172,13 +174,9 @@ coverage
|
|
|
172
174
|
const envExamplePath = join(process.cwd(), '.env.example')
|
|
173
175
|
const distEnvPath = join(distDir, ".env")
|
|
174
176
|
|
|
175
|
-
|
|
176
|
-
console.log(` - .env path: ${envPath}`)
|
|
177
|
-
console.log(` - .env.example path: ${envExamplePath}`)
|
|
178
|
-
console.log(` - target path: ${distEnvPath}`)
|
|
177
|
+
buildLogger.step('Configuring environment files...')
|
|
179
178
|
|
|
180
179
|
if (existsSync(envPath)) {
|
|
181
|
-
console.log(`📄 Copying .env file and setting production mode...`)
|
|
182
180
|
// Read .env content
|
|
183
181
|
let envContent = readFileSync(envPath, 'utf-8')
|
|
184
182
|
// Replace development with production
|
|
@@ -186,13 +184,11 @@ coverage
|
|
|
186
184
|
envContent = envContent.replace(/VITE_NODE_ENV=development/g, 'VITE_NODE_ENV=production')
|
|
187
185
|
// Write to dist
|
|
188
186
|
writeFileSync(distEnvPath, envContent)
|
|
189
|
-
|
|
187
|
+
buildLogger.success("Environment file copied (NODE_ENV=production)")
|
|
190
188
|
} else if (existsSync(envExamplePath)) {
|
|
191
|
-
console.log(`📄 Copying .env.example file...`)
|
|
192
189
|
copyFileSync(envExamplePath, distEnvPath)
|
|
193
|
-
|
|
190
|
+
buildLogger.success("Example environment file copied")
|
|
194
191
|
} else {
|
|
195
|
-
console.log(`📄 Creating default .env file...`)
|
|
196
192
|
// Criar um .env básico para produção
|
|
197
193
|
const defaultEnv = `NODE_ENV=production
|
|
198
194
|
PORT=3000
|
|
@@ -202,22 +198,20 @@ LOG_LEVEL=info
|
|
|
202
198
|
MONITORING_ENABLED=true
|
|
203
199
|
`
|
|
204
200
|
writeFileSync(distEnvPath, defaultEnv)
|
|
205
|
-
|
|
201
|
+
buildLogger.success("Default environment file created")
|
|
206
202
|
}
|
|
207
203
|
|
|
208
204
|
// Copy package.json for Docker build
|
|
209
205
|
const packageJsonPath = join(process.cwd(), 'package.json')
|
|
210
206
|
const distPackageJsonPath = join(distDir, 'package.json')
|
|
211
207
|
|
|
212
|
-
|
|
213
|
-
console.log(` - source: ${packageJsonPath}`)
|
|
214
|
-
console.log(` - target: ${distPackageJsonPath}`)
|
|
208
|
+
buildLogger.step('Copying package.json...')
|
|
215
209
|
|
|
216
210
|
if (existsSync(packageJsonPath)) {
|
|
217
211
|
copyFileSync(packageJsonPath, distPackageJsonPath)
|
|
218
|
-
|
|
212
|
+
buildLogger.success("Package.json copied successfully")
|
|
219
213
|
} else {
|
|
220
|
-
|
|
214
|
+
buildLogger.warn("package.json not found, creating minimal version...")
|
|
221
215
|
const minimalPackageJson = {
|
|
222
216
|
name: "fluxstack-app",
|
|
223
217
|
version: "1.0.0",
|
|
@@ -230,12 +224,13 @@ MONITORING_ENABLED=true
|
|
|
230
224
|
writeFileSync(distPackageJsonPath, JSON.stringify(minimalPackageJson, null, 2))
|
|
231
225
|
}
|
|
232
226
|
|
|
233
|
-
|
|
227
|
+
buildLogger.success("Docker configuration completed")
|
|
234
228
|
}
|
|
235
229
|
|
|
236
230
|
|
|
237
231
|
async build(): Promise<BuildResult> {
|
|
238
|
-
|
|
232
|
+
buildLogger.header('⚡ FluxStack Build')
|
|
233
|
+
buildLogger.startTimer()
|
|
239
234
|
|
|
240
235
|
const startTime = Date.now()
|
|
241
236
|
|
|
@@ -292,9 +287,15 @@ MONITORING_ENABLED=true
|
|
|
292
287
|
|
|
293
288
|
const duration = Date.now() - startTime
|
|
294
289
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
290
|
+
// Print build summary
|
|
291
|
+
buildLogger.summary('Build Completed Successfully', [
|
|
292
|
+
{ label: 'Build Time', value: buildLogger.formatDuration(duration), highlight: true },
|
|
293
|
+
{ label: 'Output Directory', value: this.config.build.outDir },
|
|
294
|
+
{ label: 'Client Assets', value: clientResult.assets?.length || 0 },
|
|
295
|
+
{ label: 'Total Size', value: buildLogger.formatSize(optimizationResult?.optimizedSize || 0) },
|
|
296
|
+
{ label: 'Compression', value: optimizationResult?.compressionRatio ? `${optimizationResult.compressionRatio.toFixed(2)}%` : 'N/A' },
|
|
297
|
+
{ label: 'Docker Ready', value: '✓', highlight: true }
|
|
298
|
+
])
|
|
298
299
|
|
|
299
300
|
return {
|
|
300
301
|
success: true,
|
|
@@ -316,7 +317,7 @@ MONITORING_ENABLED=true
|
|
|
316
317
|
const duration = Date.now() - startTime
|
|
317
318
|
const errorMessage = error instanceof Error ? error.message : "Unknown build error"
|
|
318
319
|
|
|
319
|
-
|
|
320
|
+
buildLogger.error(`Build failed: ${errorMessage}`)
|
|
320
321
|
|
|
321
322
|
return {
|
|
322
323
|
success: false,
|
|
@@ -364,7 +365,7 @@ MONITORING_ENABLED=true
|
|
|
364
365
|
|
|
365
366
|
private async clean(): Promise<void> {
|
|
366
367
|
// Clean output directory - implementation would go here
|
|
367
|
-
|
|
368
|
+
buildLogger.step("Cleaning output directory...")
|
|
368
369
|
}
|
|
369
370
|
|
|
370
371
|
private async generateManifest(
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { existsSync, readdirSync, writeFileSync, unlinkSync, readFileSync } from 'fs'
|
|
5
5
|
import { join, extname, basename } from 'path'
|
|
6
|
+
import { buildLogger } from '../utils/build-logger'
|
|
6
7
|
|
|
7
8
|
export interface ComponentInfo {
|
|
8
9
|
fileName: string
|
|
@@ -17,9 +18,12 @@ export class LiveComponentsGenerator {
|
|
|
17
18
|
private backupFilePath: string
|
|
18
19
|
|
|
19
20
|
constructor() {
|
|
21
|
+
// Scan components from app/ directory (user code)
|
|
20
22
|
this.componentsPath = join(process.cwd(), 'app', 'server', 'live')
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
|
|
24
|
+
// Generate registration file in core/ directory (framework code - protected from user modifications)
|
|
25
|
+
this.registrationFilePath = join(process.cwd(), 'core', 'server', 'live', 'auto-generated-components.ts')
|
|
26
|
+
this.backupFilePath = join(process.cwd(), 'core', 'server', 'live', 'auto-generated-components.backup.ts')
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
@@ -27,7 +31,6 @@ export class LiveComponentsGenerator {
|
|
|
27
31
|
*/
|
|
28
32
|
discoverComponents(): ComponentInfo[] {
|
|
29
33
|
if (!existsSync(this.componentsPath)) {
|
|
30
|
-
console.log('⚠️ Live components directory not found:', this.componentsPath)
|
|
31
34
|
return []
|
|
32
35
|
}
|
|
33
36
|
|
|
@@ -64,15 +67,16 @@ export class LiveComponentsGenerator {
|
|
|
64
67
|
fileName,
|
|
65
68
|
className,
|
|
66
69
|
componentName,
|
|
67
|
-
|
|
70
|
+
// Path relative to core/server/live/ where the generated file will be
|
|
71
|
+
filePath: `@/app/server/live/${fileName}`
|
|
68
72
|
})
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
|
|
74
|
+
buildLogger.step(`Discovered component: ${className} → ${componentName}`)
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
} catch (error) {
|
|
75
|
-
|
|
79
|
+
// Silently skip files that can't be analyzed
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
|
|
@@ -87,7 +91,6 @@ export class LiveComponentsGenerator {
|
|
|
87
91
|
if (existsSync(this.registrationFilePath)) {
|
|
88
92
|
const existingContent = readFileSync(this.registrationFilePath, 'utf-8')
|
|
89
93
|
writeFileSync(this.backupFilePath, existingContent)
|
|
90
|
-
console.log('📄 Backed up existing register-components.ts')
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
// Generate imports
|
|
@@ -130,7 +133,7 @@ ${components.map(comp => ` ${comp.className}`).join(',\n')}
|
|
|
130
133
|
`
|
|
131
134
|
|
|
132
135
|
writeFileSync(this.registrationFilePath, fileContent)
|
|
133
|
-
|
|
136
|
+
buildLogger.success(`Generated registration for ${components.length} components`)
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
/**
|
|
@@ -141,9 +144,6 @@ ${components.map(comp => ` ${comp.className}`).join(',\n')}
|
|
|
141
144
|
const backupContent = readFileSync(this.backupFilePath, 'utf-8')
|
|
142
145
|
writeFileSync(this.registrationFilePath, backupContent)
|
|
143
146
|
unlinkSync(this.backupFilePath)
|
|
144
|
-
console.log('🔄 Restored original register-components.ts')
|
|
145
|
-
} else {
|
|
146
|
-
console.log('⚠️ No backup file found, keeping generated registration file')
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -163,34 +163,48 @@ ${components.map(comp => ` ${comp.className}`).join(',\n')}
|
|
|
163
163
|
* Pre-build hook: Generate registration file
|
|
164
164
|
*/
|
|
165
165
|
async preBuild(): Promise<ComponentInfo[]> {
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
buildLogger.section('Live Components Discovery', '🚀')
|
|
167
|
+
|
|
168
168
|
const components = this.discoverComponents()
|
|
169
|
-
|
|
169
|
+
|
|
170
170
|
if (components.length === 0) {
|
|
171
|
-
|
|
171
|
+
buildLogger.warn('No Live Components found')
|
|
172
172
|
return []
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
// Create table of discovered components
|
|
176
|
+
const componentData = components.map(c => ({
|
|
177
|
+
component: c.componentName,
|
|
178
|
+
className: c.className,
|
|
179
|
+
file: c.fileName + '.ts'
|
|
180
|
+
}))
|
|
181
|
+
|
|
182
|
+
buildLogger.table(
|
|
183
|
+
[
|
|
184
|
+
{ header: 'Component', key: 'component', width: 20, align: 'left', color: 'cyan' },
|
|
185
|
+
{ header: 'Class Name', key: 'className', width: 25, align: 'left' },
|
|
186
|
+
{ header: 'File', key: 'file', width: 20, align: 'left', color: 'gray' }
|
|
187
|
+
],
|
|
188
|
+
componentData
|
|
189
|
+
)
|
|
190
|
+
|
|
175
191
|
this.generateRegistrationFile(components)
|
|
176
|
-
|
|
192
|
+
|
|
177
193
|
return components
|
|
178
194
|
}
|
|
179
195
|
|
|
180
196
|
/**
|
|
181
|
-
* Post-build hook: Clean up
|
|
197
|
+
* Post-build hook: Clean up backup file
|
|
198
|
+
* Note: Since the generated file is now in core/, we always keep it (it's bundled into production)
|
|
182
199
|
*/
|
|
183
|
-
async postBuild(keepGenerated: boolean =
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
} else {
|
|
193
|
-
this.restoreOriginalFile()
|
|
200
|
+
async postBuild(keepGenerated: boolean = true): Promise<void> {
|
|
201
|
+
buildLogger.step('Cleaning up Live Components registration...')
|
|
202
|
+
|
|
203
|
+
// Always keep the generated file in core/ (it gets bundled)
|
|
204
|
+
// Just remove the backup
|
|
205
|
+
if (existsSync(this.backupFilePath)) {
|
|
206
|
+
unlinkSync(this.backupFilePath)
|
|
207
|
+
buildLogger.step('Removed backup file')
|
|
194
208
|
}
|
|
195
209
|
}
|
|
196
210
|
|
|
@@ -220,7 +234,7 @@ ${components.map(comp => ` ${comp.className}`).join(',\n')}
|
|
|
220
234
|
*/
|
|
221
235
|
updateIfNeeded(): void {
|
|
222
236
|
if (this.needsUpdate()) {
|
|
223
|
-
|
|
237
|
+
buildLogger.info('Live Components changed, updating registration...')
|
|
224
238
|
const components = this.discoverComponents()
|
|
225
239
|
this.generateRegistrationFile(components)
|
|
226
240
|
}
|