create-fluxstack 1.0.22 โ†’ 1.1.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.
@@ -1,28 +1,8 @@
1
- // ๐Ÿ”ฅ Register all live components
2
- // NOTE: Components are now auto-discovered from this directory!
3
- // Manual registration is optional for custom initial states
1
+ // ๐Ÿงช Manual Registration REMOVED for Auto-Generation Testing
2
+ // This file is intentionally left empty to test the auto-generation system
3
+ // The build system should automatically generate all imports and registrations
4
4
 
5
- import { CounterComponent } from "./CounterComponent"
5
+ // NOTE: If you see this in production, auto-generation worked!
6
+ // All Live Components should be discovered and registered automatically during build
6
7
 
7
- // Manual registration is now optional - components are auto-discovered
8
- // Uncomment below for custom initial states:
9
-
10
- /*
11
- import { componentRegistry } from "@/core/server/live/ComponentRegistry"
12
-
13
- componentRegistry.registerComponent({
14
- name: 'CounterComponent',
15
- component: CounterComponent,
16
- initialState: {
17
- count: 0,
18
- title: 'Live Counter',
19
- step: 1,
20
- history: [0],
21
- lastUpdated: new Date()
22
- }
23
- })
24
- */
25
-
26
- console.log('๐Ÿ“ Live components registered successfully!')
27
-
28
- export { CounterComponent }
8
+ console.log('๐Ÿงช Manual registration file loaded - auto-generation should handle components')
@@ -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
- if (this.config.minify) {
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()
@@ -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
  })
@@ -229,6 +226,7 @@ MONITORING_ENABLED=true
229
226
  console.log("โœ… Docker files created in dist/")
230
227
  }
231
228
 
229
+
232
230
  async build(): Promise<BuildResult> {
233
231
  console.log("โšก FluxStack Framework - Building...")
234
232