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,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/bundler.ts
CHANGED
|
@@ -9,7 +9,6 @@ export interface BundlerConfig {
|
|
|
9
9
|
outDir: string
|
|
10
10
|
sourceMaps: boolean
|
|
11
11
|
external?: string[]
|
|
12
|
-
minify?: boolean
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
export class Bundler {
|
|
@@ -32,6 +31,7 @@ export class Bundler {
|
|
|
32
31
|
stderr: "pipe",
|
|
33
32
|
env: {
|
|
34
33
|
...process.env,
|
|
34
|
+
NODE_ENV: 'production', // Force production environment for builds
|
|
35
35
|
VITE_BUILD_OUTDIR: this.config.outDir,
|
|
36
36
|
VITE_BUILD_MINIFY: (this.config.minify || false).toString(),
|
|
37
37
|
VITE_BUILD_SOURCEMAPS: this.config.sourceMaps.toString(),
|
|
@@ -73,8 +73,21 @@ export class Bundler {
|
|
|
73
73
|
console.log("โก Bundling server...")
|
|
74
74
|
|
|
75
75
|
const startTime = Date.now()
|
|
76
|
+
let liveComponentsGenerator: any = null
|
|
76
77
|
|
|
77
78
|
try {
|
|
79
|
+
// ๐ PRE-BUILD: Auto-generate Live Components registration
|
|
80
|
+
const generatorModule = await import('./live-components-generator')
|
|
81
|
+
liveComponentsGenerator = generatorModule.liveComponentsGenerator
|
|
82
|
+
const discoveredComponents = await liveComponentsGenerator.preBuild()
|
|
83
|
+
console.log(`๐ Auto-discovered ${discoveredComponents.length} Live Components for bundle`)
|
|
84
|
+
|
|
85
|
+
// ๐ PRE-BUILD: Auto-generate FluxStack Plugins registration
|
|
86
|
+
const pluginsGeneratorModule = await import('./flux-plugins-generator')
|
|
87
|
+
const fluxPluginsGenerator = pluginsGeneratorModule.fluxPluginsGenerator
|
|
88
|
+
const discoveredPlugins = await fluxPluginsGenerator.preBuild()
|
|
89
|
+
console.log(`๐ Auto-discovered ${discoveredPlugins.length} FluxStack Plugins for bundle`)
|
|
90
|
+
|
|
78
91
|
// Ensure output directory exists
|
|
79
92
|
if (!existsSync(this.config.outDir)) {
|
|
80
93
|
mkdirSync(this.config.outDir, { recursive: true })
|
|
@@ -102,9 +115,7 @@ export class Bundler {
|
|
|
102
115
|
buildArgs.push("--sourcemap")
|
|
103
116
|
}
|
|
104
117
|
|
|
105
|
-
|
|
106
|
-
buildArgs.push("--minify")
|
|
107
|
-
}
|
|
118
|
+
// Bun bundling only - no minification for better compatibility
|
|
108
119
|
|
|
109
120
|
const buildProcess = spawn({
|
|
110
121
|
cmd: buildArgs,
|
|
@@ -112,6 +123,7 @@ export class Bundler {
|
|
|
112
123
|
stderr: "pipe",
|
|
113
124
|
env: {
|
|
114
125
|
...process.env,
|
|
126
|
+
NODE_ENV: 'production', // Force production environment for builds
|
|
115
127
|
...options.env
|
|
116
128
|
}
|
|
117
129
|
})
|
|
@@ -119,8 +131,20 @@ export class Bundler {
|
|
|
119
131
|
const exitCode = await buildProcess.exited
|
|
120
132
|
const duration = Date.now() - startTime
|
|
121
133
|
|
|
134
|
+
// ๐งน POST-BUILD: Handle auto-generated registration file
|
|
135
|
+
// (liveComponentsGenerator already available from above)
|
|
136
|
+
|
|
122
137
|
if (exitCode === 0) {
|
|
123
138
|
console.log("โ
Server bundle completed")
|
|
139
|
+
|
|
140
|
+
// Keep generated files for production (they're now baked into bundle)
|
|
141
|
+
await liveComponentsGenerator.postBuild(false)
|
|
142
|
+
|
|
143
|
+
// Cleanup plugins registry
|
|
144
|
+
const pluginsGeneratorModule = await import('./flux-plugins-generator')
|
|
145
|
+
const fluxPluginsGenerator = pluginsGeneratorModule.fluxPluginsGenerator
|
|
146
|
+
await fluxPluginsGenerator.postBuild(false)
|
|
147
|
+
|
|
124
148
|
return {
|
|
125
149
|
success: true,
|
|
126
150
|
duration,
|
|
@@ -128,8 +152,17 @@ export class Bundler {
|
|
|
128
152
|
entryPoint: join(this.config.outDir, "index.js")
|
|
129
153
|
}
|
|
130
154
|
} else {
|
|
131
|
-
const stderr = await new Response(buildProcess.stderr).text()
|
|
132
155
|
console.error("โ Server bundle failed")
|
|
156
|
+
|
|
157
|
+
// Restore original files since build failed
|
|
158
|
+
await liveComponentsGenerator.postBuild(false)
|
|
159
|
+
|
|
160
|
+
// Restore plugins registry
|
|
161
|
+
const pluginsGeneratorModule = await import('./flux-plugins-generator')
|
|
162
|
+
const fluxPluginsGenerator = pluginsGeneratorModule.fluxPluginsGenerator
|
|
163
|
+
await fluxPluginsGenerator.postBuild(false)
|
|
164
|
+
|
|
165
|
+
const stderr = await new Response(buildProcess.stderr).text()
|
|
133
166
|
return {
|
|
134
167
|
success: false,
|
|
135
168
|
duration,
|
|
@@ -138,6 +171,21 @@ export class Bundler {
|
|
|
138
171
|
}
|
|
139
172
|
} catch (error) {
|
|
140
173
|
const duration = Date.now() - startTime
|
|
174
|
+
|
|
175
|
+
// ๐งน CLEANUP: Restore original files on error
|
|
176
|
+
try {
|
|
177
|
+
if (liveComponentsGenerator) {
|
|
178
|
+
await liveComponentsGenerator.postBuild(false)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Cleanup plugins registry
|
|
182
|
+
const pluginsGeneratorModule = await import('./flux-plugins-generator')
|
|
183
|
+
const fluxPluginsGenerator = pluginsGeneratorModule.fluxPluginsGenerator
|
|
184
|
+
await fluxPluginsGenerator.postBuild(false)
|
|
185
|
+
} catch (cleanupError) {
|
|
186
|
+
console.warn('โ ๏ธ Failed to cleanup generated files:', cleanupError)
|
|
187
|
+
}
|
|
188
|
+
|
|
141
189
|
return {
|
|
142
190
|
success: false,
|
|
143
191
|
duration,
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
// ๐ FluxStack Plugins - Auto Registration Generator
|
|
2
|
+
// Automatically generates plugin registration during build time
|
|
3
|
+
|
|
4
|
+
import { existsSync, readdirSync, writeFileSync, unlinkSync, readFileSync, statSync } from 'fs'
|
|
5
|
+
import { join, extname, basename } from 'path'
|
|
6
|
+
|
|
7
|
+
export interface PluginInfo {
|
|
8
|
+
pluginDir: string
|
|
9
|
+
pluginName: string
|
|
10
|
+
entryFile: string
|
|
11
|
+
relativePath: string
|
|
12
|
+
type: 'external' | 'built-in'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class FluxPluginsGenerator {
|
|
16
|
+
private pluginsPath: string
|
|
17
|
+
private builtInPluginsPath: string
|
|
18
|
+
private registrationFilePath: string
|
|
19
|
+
private backupFilePath: string
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
this.pluginsPath = join(process.cwd(), 'plugins')
|
|
23
|
+
this.builtInPluginsPath = join(process.cwd(), 'core', 'plugins', 'built-in')
|
|
24
|
+
this.registrationFilePath = join(process.cwd(), 'core', 'plugins', 'auto-registry.ts')
|
|
25
|
+
this.backupFilePath = join(process.cwd(), 'core', 'plugins', 'auto-registry.backup.ts')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Scan plugin directories and discover external plugins only
|
|
30
|
+
* Built-in plugins are handled by the core system
|
|
31
|
+
*/
|
|
32
|
+
discoverPlugins(): PluginInfo[] {
|
|
33
|
+
const plugins: PluginInfo[] = []
|
|
34
|
+
|
|
35
|
+
// Discover external plugins only
|
|
36
|
+
if (existsSync(this.pluginsPath)) {
|
|
37
|
+
const externalPlugins = this.discoverPluginsInDirectory(this.pluginsPath, 'external')
|
|
38
|
+
plugins.push(...externalPlugins)
|
|
39
|
+
} else {
|
|
40
|
+
console.log('โ ๏ธ No external plugins directory found (plugins/)')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Note: Built-in plugins are automatically loaded by core system
|
|
44
|
+
// No need to include them in auto-generation
|
|
45
|
+
|
|
46
|
+
return plugins
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Discover plugins in a specific directory
|
|
51
|
+
*/
|
|
52
|
+
private discoverPluginsInDirectory(directory: string, type: 'external' | 'built-in'): PluginInfo[] {
|
|
53
|
+
const plugins: PluginInfo[] = []
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const entries = readdirSync(directory)
|
|
57
|
+
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const pluginDir = join(directory, entry)
|
|
60
|
+
|
|
61
|
+
// Skip files, only process directories
|
|
62
|
+
if (!statSync(pluginDir).isDirectory()) {
|
|
63
|
+
continue
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Look for plugin entry point
|
|
67
|
+
const entryFile = this.findPluginEntryFile(pluginDir)
|
|
68
|
+
if (entryFile) {
|
|
69
|
+
const relativePath = type === 'external'
|
|
70
|
+
? `../../plugins/${entry}`
|
|
71
|
+
: `./built-in/${entry}`
|
|
72
|
+
|
|
73
|
+
plugins.push({
|
|
74
|
+
pluginDir,
|
|
75
|
+
pluginName: entry,
|
|
76
|
+
entryFile,
|
|
77
|
+
relativePath,
|
|
78
|
+
type
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
console.log(`๐ Discovered ${type} plugin: ${entry} (${entryFile})`)
|
|
82
|
+
} else {
|
|
83
|
+
console.warn(`โ ๏ธ Plugin '${entry}' has no valid entry point`)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.warn(`โ ๏ธ Failed to scan ${type} plugins directory '${directory}':`, error)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return plugins
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Find the main plugin entry file
|
|
95
|
+
*/
|
|
96
|
+
private findPluginEntryFile(pluginDir: string): string | null {
|
|
97
|
+
const possibleFiles = [
|
|
98
|
+
'index.ts',
|
|
99
|
+
'index.js',
|
|
100
|
+
'plugin.ts',
|
|
101
|
+
'plugin.js',
|
|
102
|
+
'src/index.ts',
|
|
103
|
+
'src/index.js',
|
|
104
|
+
'dist/index.js'
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
for (const file of possibleFiles) {
|
|
108
|
+
const filePath = join(pluginDir, file)
|
|
109
|
+
if (existsSync(filePath)) {
|
|
110
|
+
return basename(file)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Generate the registration file with all discovered plugins
|
|
119
|
+
*/
|
|
120
|
+
generateRegistrationFile(plugins: PluginInfo[]): void {
|
|
121
|
+
// Backup existing file if it exists
|
|
122
|
+
if (existsSync(this.registrationFilePath)) {
|
|
123
|
+
const existingContent = readFileSync(this.registrationFilePath, 'utf-8')
|
|
124
|
+
writeFileSync(this.backupFilePath, existingContent)
|
|
125
|
+
console.log('๐ Backed up existing auto-registry.ts')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// All discovered plugins are external (built-in are handled by core)
|
|
129
|
+
const externalPlugins = plugins
|
|
130
|
+
|
|
131
|
+
// Generate imports
|
|
132
|
+
const imports = plugins
|
|
133
|
+
.map(plugin => {
|
|
134
|
+
const importName = this.getImportName(plugin.pluginName)
|
|
135
|
+
const importPath = plugin.entryFile === 'index.ts' || plugin.entryFile === 'index.js'
|
|
136
|
+
? plugin.relativePath
|
|
137
|
+
: `${plugin.relativePath}/${plugin.entryFile.replace(/\.(ts|js)$/, '')}`
|
|
138
|
+
return `import ${importName} from "${importPath}"`
|
|
139
|
+
})
|
|
140
|
+
.join('\n')
|
|
141
|
+
|
|
142
|
+
// Generate plugin array
|
|
143
|
+
const pluginsList = plugins
|
|
144
|
+
.map(plugin => {
|
|
145
|
+
const importName = this.getImportName(plugin.pluginName)
|
|
146
|
+
return ` ${importName}`
|
|
147
|
+
})
|
|
148
|
+
.join(',\n')
|
|
149
|
+
|
|
150
|
+
// Generate file content
|
|
151
|
+
const fileContent = `// ๐ฅ Auto-generated FluxStack External Plugins Registry
|
|
152
|
+
// This file is automatically generated during build time - DO NOT EDIT MANUALLY
|
|
153
|
+
// Built-in plugins are handled by the core system automatically
|
|
154
|
+
// Generated at: ${new Date().toISOString()}
|
|
155
|
+
|
|
156
|
+
import type { Plugin } from './types'
|
|
157
|
+
|
|
158
|
+
${imports}
|
|
159
|
+
|
|
160
|
+
// Auto-discovered external plugins array
|
|
161
|
+
export const discoveredPlugins: Plugin[] = [
|
|
162
|
+
${pluginsList}
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
// All discovered plugins are external (built-in handled by core)
|
|
166
|
+
export const externalPlugins = discoveredPlugins
|
|
167
|
+
|
|
168
|
+
// Plugin registration function
|
|
169
|
+
export async function registerDiscoveredPlugins(registry: any): Promise<void> {
|
|
170
|
+
if (discoveredPlugins.length === 0) {
|
|
171
|
+
console.log('๐ฆ No external plugins to register')
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log(\`๐ฆ Registering \${discoveredPlugins.length} auto-discovered external plugins...\`)
|
|
176
|
+
|
|
177
|
+
let registered = 0
|
|
178
|
+
let failed = 0
|
|
179
|
+
|
|
180
|
+
for (const plugin of discoveredPlugins) {
|
|
181
|
+
try {
|
|
182
|
+
await registry.register(plugin)
|
|
183
|
+
registered++
|
|
184
|
+
console.log(\`โ
Registered external plugin: \${plugin.name}\`)
|
|
185
|
+
} catch (error) {
|
|
186
|
+
failed++
|
|
187
|
+
console.error(\`โ Failed to register external plugin \${plugin.name}:\`, error)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
console.log(\`๐ External plugin registration complete: \${registered} registered, \${failed} failed\`)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Export plugin names for easy access
|
|
195
|
+
export const pluginNames = discoveredPlugins.map(p => p.name)
|
|
196
|
+
|
|
197
|
+
console.log('๐ Auto-discovered ${plugins.length} external plugins' + (pluginNames.length > 0 ? ': ' + pluginNames.join(', ') : ''))
|
|
198
|
+
`
|
|
199
|
+
|
|
200
|
+
writeFileSync(this.registrationFilePath, fileContent)
|
|
201
|
+
console.log(`โ
Generated plugin registry with ${plugins.length} plugins`)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Generate a valid import name from plugin name
|
|
206
|
+
*/
|
|
207
|
+
private getImportName(pluginName: string): string {
|
|
208
|
+
// Convert kebab-case to PascalCase for import names
|
|
209
|
+
return pluginName
|
|
210
|
+
.split('-')
|
|
211
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
212
|
+
.join('') + 'Plugin'
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Restore the original registration file from backup
|
|
217
|
+
*/
|
|
218
|
+
restoreOriginalFile(): void {
|
|
219
|
+
if (existsSync(this.backupFilePath)) {
|
|
220
|
+
const backupContent = readFileSync(this.backupFilePath, 'utf-8')
|
|
221
|
+
writeFileSync(this.registrationFilePath, backupContent)
|
|
222
|
+
unlinkSync(this.backupFilePath)
|
|
223
|
+
console.log('๐ Restored original auto-registry.ts')
|
|
224
|
+
} else {
|
|
225
|
+
// If no backup exists, remove the generated file
|
|
226
|
+
if (existsSync(this.registrationFilePath)) {
|
|
227
|
+
unlinkSync(this.registrationFilePath)
|
|
228
|
+
console.log('๐๏ธ Removed auto-generated registry file')
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Check if the current registration file is auto-generated
|
|
235
|
+
*/
|
|
236
|
+
isAutoGenerated(): boolean {
|
|
237
|
+
if (!existsSync(this.registrationFilePath)) {
|
|
238
|
+
return false
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const content = readFileSync(this.registrationFilePath, 'utf-8')
|
|
242
|
+
return content.includes('// ๐ฅ Auto-generated FluxStack Plugins Registry')
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Pre-build hook: Generate registration file
|
|
247
|
+
*/
|
|
248
|
+
async preBuild(): Promise<PluginInfo[]> {
|
|
249
|
+
console.log('๐ [PRE-BUILD] Generating FluxStack Plugins registry...')
|
|
250
|
+
|
|
251
|
+
const plugins = this.discoverPlugins()
|
|
252
|
+
|
|
253
|
+
if (plugins.length === 0) {
|
|
254
|
+
console.log('โ ๏ธ No FluxStack Plugins found to register')
|
|
255
|
+
return []
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.generateRegistrationFile(plugins)
|
|
259
|
+
|
|
260
|
+
return plugins
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Post-build hook: Clean up generated file (optional)
|
|
265
|
+
*/
|
|
266
|
+
async postBuild(keepGenerated: boolean = false): Promise<void> {
|
|
267
|
+
console.log('๐งน [POST-BUILD] Cleaning up FluxStack Plugins registry...')
|
|
268
|
+
|
|
269
|
+
if (keepGenerated) {
|
|
270
|
+
console.log('๐ Keeping auto-generated plugin registry for production')
|
|
271
|
+
// Remove backup since we're keeping the generated version
|
|
272
|
+
if (existsSync(this.backupFilePath)) {
|
|
273
|
+
unlinkSync(this.backupFilePath)
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
this.restoreOriginalFile()
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Development mode: Check if registration needs update
|
|
282
|
+
*/
|
|
283
|
+
needsUpdate(): boolean {
|
|
284
|
+
if (!this.isAutoGenerated()) {
|
|
285
|
+
return false // No auto-generated file, don't touch manual setup
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const plugins = this.discoverPlugins()
|
|
289
|
+
const currentContent = readFileSync(this.registrationFilePath, 'utf-8')
|
|
290
|
+
|
|
291
|
+
// Check if all discovered plugins are in the current file
|
|
292
|
+
for (const plugin of plugins) {
|
|
293
|
+
const importName = this.getImportName(plugin.pluginName)
|
|
294
|
+
if (!currentContent.includes(importName)) {
|
|
295
|
+
return true
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return false
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Development mode: Update registration if needed
|
|
304
|
+
*/
|
|
305
|
+
updateIfNeeded(): void {
|
|
306
|
+
if (this.needsUpdate()) {
|
|
307
|
+
console.log('๐ FluxStack Plugins changed, updating registry...')
|
|
308
|
+
const plugins = this.discoverPlugins()
|
|
309
|
+
this.generateRegistrationFile(plugins)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Export singleton instance
|
|
315
|
+
export const fluxPluginsGenerator = new FluxPluginsGenerator()
|
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"
|
|
@@ -18,13 +18,11 @@ export class FluxStackBuilder {
|
|
|
18
18
|
target: config.build.target,
|
|
19
19
|
outDir: config.build.outDir,
|
|
20
20
|
sourceMaps: config.build.sourceMaps,
|
|
21
|
-
minify: config.build.minify,
|
|
22
21
|
external: config.build.external
|
|
23
22
|
})
|
|
24
23
|
|
|
25
24
|
// Initialize optimizer with configuration
|
|
26
25
|
this.optimizer = new Optimizer({
|
|
27
|
-
minify: config.build.minify,
|
|
28
26
|
treeshake: config.build.treeshake,
|
|
29
27
|
compress: config.build.compress || false,
|
|
30
28
|
removeUnusedCSS: config.build.removeUnusedCSS || false,
|
|
@@ -37,7 +35,6 @@ export class FluxStackBuilder {
|
|
|
37
35
|
return await this.bundler.bundleClient({
|
|
38
36
|
env: {
|
|
39
37
|
VITE_BUILD_OUTDIR: this.config.client.build.outDir,
|
|
40
|
-
VITE_BUILD_MINIFY: this.config.client.build.minify.toString(),
|
|
41
38
|
VITE_BUILD_SOURCEMAPS: this.config.client.build.sourceMaps.toString()
|
|
42
39
|
}
|
|
43
40
|
})
|
|
@@ -180,9 +177,15 @@ coverage
|
|
|
180
177
|
console.log(` - target path: ${distEnvPath}`)
|
|
181
178
|
|
|
182
179
|
if (existsSync(envPath)) {
|
|
183
|
-
console.log(`๐ Copying .env file...`)
|
|
184
|
-
|
|
185
|
-
|
|
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)")
|
|
186
189
|
} else if (existsSync(envExamplePath)) {
|
|
187
190
|
console.log(`๐ Copying .env.example file...`)
|
|
188
191
|
copyFileSync(envExamplePath, distEnvPath)
|
|
@@ -229,6 +232,7 @@ MONITORING_ENABLED=true
|
|
|
229
232
|
console.log("โ
Docker files created in dist/")
|
|
230
233
|
}
|
|
231
234
|
|
|
235
|
+
|
|
232
236
|
async build(): Promise<BuildResult> {
|
|
233
237
|
console.log("โก FluxStack Framework - Building...")
|
|
234
238
|
|