create-fluxstack 1.16.0 → 1.17.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/app/client/src/App.tsx +8 -0
  3. package/app/client/src/live/AuthDemo.tsx +4 -4
  4. package/core/build/bundler.ts +40 -26
  5. package/core/build/flux-plugins-generator.ts +325 -325
  6. package/core/build/index.ts +92 -21
  7. package/core/cli/command-registry.ts +44 -46
  8. package/core/cli/commands/build.ts +11 -6
  9. package/core/cli/commands/create.ts +7 -5
  10. package/core/cli/commands/dev.ts +6 -5
  11. package/core/cli/commands/help.ts +3 -2
  12. package/core/cli/commands/make-plugin.ts +8 -7
  13. package/core/cli/commands/plugin-add.ts +60 -43
  14. package/core/cli/commands/plugin-deps.ts +73 -57
  15. package/core/cli/commands/plugin-list.ts +44 -41
  16. package/core/cli/commands/plugin-remove.ts +33 -22
  17. package/core/cli/generators/component.ts +770 -769
  18. package/core/cli/generators/controller.ts +9 -8
  19. package/core/cli/generators/index.ts +148 -146
  20. package/core/cli/generators/interactive.ts +228 -227
  21. package/core/cli/generators/plugin.ts +11 -10
  22. package/core/cli/generators/prompts.ts +83 -82
  23. package/core/cli/generators/route.ts +7 -6
  24. package/core/cli/generators/service.ts +10 -9
  25. package/core/cli/generators/template-engine.ts +2 -1
  26. package/core/cli/generators/types.ts +7 -7
  27. package/core/cli/generators/utils.ts +191 -191
  28. package/core/cli/index.ts +9 -8
  29. package/core/cli/plugin-discovery.ts +2 -2
  30. package/core/client/hooks/useAuth.ts +48 -48
  31. package/core/client/standalone.ts +18 -17
  32. package/core/client/state/createStore.ts +192 -192
  33. package/core/client/state/index.ts +14 -14
  34. package/core/config/index.ts +1 -0
  35. package/core/framework/client.ts +131 -131
  36. package/core/framework/index.ts +7 -7
  37. package/core/framework/server.ts +72 -112
  38. package/core/framework/types.ts +2 -2
  39. package/core/plugins/built-in/live-components/commands/create-live-component.ts +6 -3
  40. package/core/plugins/built-in/monitoring/index.ts +110 -68
  41. package/core/plugins/built-in/static/index.ts +2 -2
  42. package/core/plugins/built-in/swagger/index.ts +9 -9
  43. package/core/plugins/built-in/vite/index.ts +3 -3
  44. package/core/plugins/built-in/vite/vite-dev.ts +3 -3
  45. package/core/plugins/config.ts +50 -47
  46. package/core/plugins/discovery.ts +10 -4
  47. package/core/plugins/executor.ts +2 -2
  48. package/core/plugins/index.ts +206 -203
  49. package/core/plugins/manager.ts +21 -20
  50. package/core/plugins/registry.ts +76 -12
  51. package/core/plugins/types.ts +14 -14
  52. package/core/server/framework.ts +3 -189
  53. package/core/server/live/auto-generated-components.ts +11 -29
  54. package/core/server/live/index.ts +41 -31
  55. package/core/server/live/websocket-plugin.ts +11 -1
  56. package/core/server/middleware/elysia-helpers.ts +16 -15
  57. package/core/server/middleware/errorHandling.ts +14 -14
  58. package/core/server/middleware/index.ts +31 -31
  59. package/core/server/plugins/database.ts +181 -180
  60. package/core/server/plugins/static-files-plugin.ts +4 -3
  61. package/core/server/plugins/swagger.ts +11 -8
  62. package/core/server/rooms/RoomBroadcaster.ts +11 -10
  63. package/core/server/rooms/RoomSystem.ts +14 -11
  64. package/core/server/services/BaseService.ts +7 -7
  65. package/core/server/services/ServiceContainer.ts +5 -5
  66. package/core/server/services/index.ts +8 -8
  67. package/core/templates/create-project.ts +28 -27
  68. package/core/testing/index.ts +9 -9
  69. package/core/testing/setup.ts +73 -73
  70. package/core/types/api.ts +168 -168
  71. package/core/types/config.ts +5 -5
  72. package/core/types/index.ts +1 -1
  73. package/core/types/plugin.ts +2 -2
  74. package/core/types/types.ts +3 -3
  75. package/core/utils/build-logger.ts +324 -324
  76. package/core/utils/config-schema.ts +480 -480
  77. package/core/utils/env.ts +10 -8
  78. package/core/utils/errors/codes.ts +114 -114
  79. package/core/utils/errors/handlers.ts +30 -20
  80. package/core/utils/errors/index.ts +54 -46
  81. package/core/utils/errors/middleware.ts +113 -113
  82. package/core/utils/helpers.ts +19 -16
  83. package/core/utils/logger/colors.ts +114 -114
  84. package/core/utils/logger/config.ts +2 -2
  85. package/core/utils/logger/formatter.ts +82 -82
  86. package/core/utils/logger/group-logger.ts +101 -101
  87. package/core/utils/logger/index.ts +13 -3
  88. package/core/utils/logger/startup-banner.ts +2 -2
  89. package/core/utils/logger/winston-logger.ts +152 -152
  90. package/core/utils/monitoring/index.ts +211 -211
  91. package/core/utils/sync-version.ts +67 -66
  92. package/core/utils/version.ts +1 -1
  93. package/package.json +104 -100
  94. package/playwright-report/index.html +85 -0
  95. package/playwright.config.ts +31 -0
  96. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  97. package/plugins/crypto-auth/client/components/index.ts +11 -11
  98. package/plugins/crypto-auth/client/index.ts +11 -11
  99. package/plugins/crypto-auth/package.json +65 -65
  100. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  101. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +6 -5
  102. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +6 -5
  103. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +3 -3
  104. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  105. package/plugins/crypto-auth/server/middlewares.ts +19 -19
  106. package/vite.config.ts +13 -0
  107. package/app/client/.live-stubs/LiveAdminPanel.js +0 -5
  108. package/app/client/.live-stubs/LiveCounter.js +0 -9
  109. package/app/client/.live-stubs/LiveForm.js +0 -11
  110. package/app/client/.live-stubs/LiveLocalCounter.js +0 -8
  111. package/app/client/.live-stubs/LivePingPong.js +0 -10
  112. package/app/client/.live-stubs/LiveRoomChat.js +0 -11
  113. package/app/client/.live-stubs/LiveSharedCounter.js +0 -10
  114. package/app/client/.live-stubs/LiveUpload.js +0 -15
  115. package/app/server/live/register-components.ts +0 -19
  116. package/core/build/live-components-generator.ts +0 -321
  117. package/core/live/ComponentRegistry.ts +0 -403
  118. package/core/live/types.ts +0 -241
  119. package/workspace.json +0 -6
package/vite.config.ts CHANGED
@@ -69,6 +69,19 @@ export default defineConfig({
69
69
  host: clientConfig.vite.host,
70
70
  port: clientConfig.vite.port,
71
71
  clientPort: clientConfig.vite.port
72
+ },
73
+
74
+ proxy: {
75
+ '/api/': {
76
+ target: 'http://localhost:3000',
77
+ changeOrigin: true,
78
+ // WebSocket goes directly to port 3000 (configured in App.tsx)
79
+ // to avoid Vite proxy overhead and HMR contention
80
+ },
81
+ '/swagger': {
82
+ target: 'http://localhost:3000',
83
+ changeOrigin: true,
84
+ },
72
85
  }
73
86
  },
74
87
 
@@ -1,5 +0,0 @@
1
- export class LiveAdminPanel {
2
- static componentName = 'LiveAdminPanel'
3
- static defaultState = {}
4
- static publicActions = ['getAuthInfo', 'init', 'listUsers', 'addUser', 'deleteUser', 'clearAudit']
5
- }
@@ -1,9 +0,0 @@
1
- export class LiveCounter {
2
- static componentName = 'LiveCounter'
3
- static defaultState = {
4
- count: 0,
5
- lastUpdatedBy: null,
6
- connectedUsers: 0
7
- }
8
- static publicActions = ['increment', 'decrement', 'reset']
9
- }
@@ -1,11 +0,0 @@
1
- export class LiveForm {
2
- static componentName = 'LiveForm'
3
- static defaultState = {
4
- name: '',
5
- email: '',
6
- message: '',
7
- submitted: false,
8
- submittedAt: null
9
- }
10
- static publicActions = ['submit', 'reset', 'validate', 'setValue']
11
- }
@@ -1,8 +0,0 @@
1
- export class LiveLocalCounter {
2
- static componentName = 'LiveLocalCounter'
3
- static defaultState = {
4
- count: 0,
5
- clicks: 0
6
- }
7
- static publicActions = ['increment', 'decrement', 'reset']
8
- }
@@ -1,10 +0,0 @@
1
- export class LivePingPong {
2
- static componentName = 'LivePingPong'
3
- static defaultState = {
4
- username: '',
5
- onlineCount: 0,
6
- totalPings: 0,
7
- lastPingBy: null,
8
- }
9
- static publicActions = ['ping']
10
- }
@@ -1,11 +0,0 @@
1
- export class LiveRoomChat {
2
- static componentName = 'LiveRoomChat'
3
- static defaultState = {
4
- username: '',
5
- activeRoom: null,
6
- rooms: [],
7
- messages: {},
8
- customRooms: []
9
- }
10
- static publicActions = ['createRoom', 'joinRoom', 'leaveRoom', 'switchRoom', 'sendMessage', 'setUsername']
11
- }
@@ -1,10 +0,0 @@
1
- export class LiveSharedCounter {
2
- static componentName = 'LiveSharedCounter'
3
- static defaultState = {
4
- username: '',
5
- count: 0,
6
- lastUpdatedBy: null,
7
- onlineCount: 0
8
- }
9
- static publicActions = ['increment', 'decrement', 'reset']
10
- }
@@ -1,15 +0,0 @@
1
- export class LiveUpload {
2
- static componentName = 'LiveUpload'
3
- static defaultState = {
4
- status: 'idle',
5
- progress: 0,
6
- fileName: '',
7
- fileSize: 0,
8
- fileType: '',
9
- fileUrl: '',
10
- bytesUploaded: 0,
11
- totalBytes: 0,
12
- error: null
13
- }
14
- static publicActions = ['startUpload', 'updateProgress', 'completeUpload', 'failUpload', 'reset']
15
- }
@@ -1,19 +0,0 @@
1
- // ⚠️ DEPRECATION NOTICE
2
- // This file has been moved to: core/server/live/auto-generated-components.ts
3
- //
4
- // The auto-generated component registration is now located in the core/ directory
5
- // to prevent accidental user modifications and keep framework code separate from
6
- // application code.
7
- //
8
- // If you're looking for component registration logic:
9
- // - Generated file: core/server/live/auto-generated-components.ts (auto-generated during build)
10
- // - Generator: core/build/live-components-generator.ts
11
- // - Import location: app/server/index.ts
12
- //
13
- // To add new Live Components:
14
- // 1. Create your component class in this directory (app/server/live/)
15
- // 2. Extend LiveComponent class
16
- // 3. Run 'bun run build' to regenerate the registration file
17
-
18
- // This file intentionally left empty - do not import
19
- export {}
@@ -1,321 +0,0 @@
1
- // 🚀 FluxStack Live Components - Auto Registration Generator
2
- // Automatically generates component registration during build time
3
-
4
- import { existsSync, readdirSync, writeFileSync, unlinkSync, readFileSync } from 'fs'
5
- import { join, extname, basename } from 'path'
6
- import { buildLogger } from '../utils/build-logger'
7
-
8
- export interface ComponentInfo {
9
- fileName: string
10
- className: string
11
- componentName: string
12
- filePath: string
13
- }
14
-
15
- export class LiveComponentsGenerator {
16
- private componentsPath: string
17
- private registrationFilePath: string
18
- private backupFilePath: string
19
- private entryPointPath: string
20
- private entryPointBackupPath: string
21
- private readonly importLine = 'import "@core/server/live/auto-generated-components"'
22
-
23
- constructor() {
24
- // Scan components from app/ directory (user code)
25
- this.componentsPath = join(process.cwd(), 'app', 'server', 'live')
26
-
27
- // Generate registration file in core/ directory (framework code - protected from user modifications)
28
- this.registrationFilePath = join(process.cwd(), 'core', 'server', 'live', 'auto-generated-components.ts')
29
- this.backupFilePath = join(process.cwd(), 'core', 'server', 'live', 'auto-generated-components.backup.ts')
30
-
31
- // Entry point for import injection
32
- this.entryPointPath = join(process.cwd(), 'app', 'server', 'index.ts')
33
- this.entryPointBackupPath = join(process.cwd(), 'app', 'server', 'index.ts.backup')
34
- }
35
-
36
- /**
37
- * Scan the live components directory and discover all components
38
- */
39
- discoverComponents(): ComponentInfo[] {
40
- if (!existsSync(this.componentsPath)) {
41
- return []
42
- }
43
-
44
- const components: ComponentInfo[] = []
45
- const files = readdirSync(this.componentsPath)
46
-
47
- for (const file of files) {
48
- // Skip non-TypeScript files, backup files, and the registration file itself
49
- if (!file.endsWith('.ts') ||
50
- file === 'register-components.ts' ||
51
- file.includes('.backup.') ||
52
- file.includes('.bak')) {
53
- continue
54
- }
55
-
56
- const filePath = join(this.componentsPath, file)
57
- const fileName = basename(file, extname(file))
58
-
59
- try {
60
- // Read file content to extract class name
61
- const content = readFileSync(filePath, 'utf-8')
62
-
63
- // Look for class exports that extend LiveComponent
64
- const classMatches = content.match(/export\s+class\s+(\w+)\s+extends\s+LiveComponent/g)
65
-
66
- if (classMatches && classMatches.length > 0) {
67
- for (const match of classMatches) {
68
- const classNameMatch = match.match(/class\s+(\w+)/)
69
- if (classNameMatch) {
70
- const className = classNameMatch[1]
71
- const componentName = className.replace(/Component$/, '')
72
-
73
- components.push({
74
- fileName,
75
- className,
76
- componentName,
77
- // Path relative to core/server/live/ where the generated file will be
78
- filePath: `@app/server/live/${fileName}`
79
- })
80
-
81
- buildLogger.step(`Discovered component: ${className} → ${componentName}`)
82
- }
83
- }
84
- }
85
- } catch (error) {
86
- // Silently skip files that can't be analyzed
87
- }
88
- }
89
-
90
- return components
91
- }
92
-
93
- /**
94
- * Generate the registration file with all discovered components
95
- */
96
- generateRegistrationFile(components: ComponentInfo[]): void {
97
- // Backup existing file if it exists
98
- if (existsSync(this.registrationFilePath)) {
99
- const existingContent = readFileSync(this.registrationFilePath, 'utf-8')
100
- writeFileSync(this.backupFilePath, existingContent)
101
- }
102
-
103
- // Generate imports
104
- const imports = components
105
- .map(comp => `import { ${comp.className} } from "${comp.filePath}"`)
106
- .join('\n')
107
-
108
- // Generate registrations
109
- const registrations = components
110
- .map(comp => ` componentRegistry.registerComponentClass('${comp.componentName}', ${comp.className})`)
111
- .join('\n')
112
-
113
- // Generate file content
114
- const fileContent = `// 🔥 Auto-generated Live Components Registration
115
- // This file is automatically generated during build time - DO NOT EDIT MANUALLY
116
- // Generated at: ${new Date().toISOString()}
117
-
118
- ${imports}
119
- import { componentRegistry } from "@core/server/live"
120
-
121
- // Register all components statically for production bundle
122
- function registerAllComponents() {
123
- try {
124
- // Auto-generated component registrations
125
- ${registrations}
126
-
127
- console.log('📝 Live components registered successfully! (${components.length} components)')
128
- } catch (error) {
129
- console.warn('⚠️ Error registering components:', error)
130
- }
131
- }
132
-
133
- // Auto-register components
134
- registerAllComponents()
135
-
136
- // Export all components to ensure they're included in the bundle
137
- export {
138
- ${components.map(comp => ` ${comp.className}`).join(',\n')}
139
- }
140
- `
141
-
142
- writeFileSync(this.registrationFilePath, fileContent)
143
- buildLogger.success(`Generated registration for ${components.length} components`)
144
- }
145
-
146
- /**
147
- * Restore the original registration file from backup
148
- */
149
- restoreOriginalFile(): void {
150
- if (existsSync(this.backupFilePath)) {
151
- const backupContent = readFileSync(this.backupFilePath, 'utf-8')
152
- writeFileSync(this.registrationFilePath, backupContent)
153
- unlinkSync(this.backupFilePath)
154
- }
155
- }
156
-
157
- /**
158
- * Inject the auto-generated components import into the entry point
159
- */
160
- injectImportIntoEntryPoint(): void {
161
- if (!existsSync(this.entryPointPath)) {
162
- buildLogger.warn('Entry point not found, skipping import injection')
163
- return
164
- }
165
-
166
- const content = readFileSync(this.entryPointPath, 'utf-8')
167
-
168
- // Check if import already exists
169
- if (content.includes(this.importLine)) {
170
- return // Already injected
171
- }
172
-
173
- // Backup original file
174
- writeFileSync(this.entryPointBackupPath, content)
175
-
176
- // Find the best place to inject (after other imports)
177
- const lines = content.split('\n')
178
- let lastImportIndex = -1
179
-
180
- for (let i = 0; i < lines.length; i++) {
181
- const line = lines[i].trim()
182
- if (line.startsWith('import ') || line.startsWith('import{')) {
183
- lastImportIndex = i
184
- }
185
- }
186
-
187
- // Inject after the last import
188
- if (lastImportIndex >= 0) {
189
- lines.splice(lastImportIndex + 1, 0, this.importLine)
190
- } else {
191
- // No imports found, add at the beginning
192
- lines.unshift(this.importLine)
193
- }
194
-
195
- writeFileSync(this.entryPointPath, lines.join('\n'))
196
- buildLogger.step('Injected auto-generated components import into entry point')
197
- }
198
-
199
- /**
200
- * Remove the injected import and restore original entry point
201
- */
202
- removeInjectedImport(): void {
203
- if (existsSync(this.entryPointBackupPath)) {
204
- const backupContent = readFileSync(this.entryPointBackupPath, 'utf-8')
205
- writeFileSync(this.entryPointPath, backupContent)
206
- unlinkSync(this.entryPointBackupPath)
207
- buildLogger.step('Restored original entry point')
208
- }
209
- }
210
-
211
- /**
212
- * Check if the current registration file is auto-generated
213
- */
214
- isAutoGenerated(): boolean {
215
- if (!existsSync(this.registrationFilePath)) {
216
- return false
217
- }
218
-
219
- const content = readFileSync(this.registrationFilePath, 'utf-8')
220
- return content.includes('// 🔥 Auto-generated Live Components Registration')
221
- }
222
-
223
- /**
224
- * Pre-build hook: Generate registration file
225
- */
226
- async preBuild(): Promise<ComponentInfo[]> {
227
- buildLogger.section('Live Components Discovery', '🚀')
228
-
229
- const components = this.discoverComponents()
230
-
231
- if (components.length === 0) {
232
- buildLogger.warn('No Live Components found')
233
- return []
234
- }
235
-
236
- // Create table of discovered components
237
- const componentData = components.map(c => ({
238
- component: c.componentName,
239
- className: c.className,
240
- file: c.fileName + '.ts'
241
- }))
242
-
243
- buildLogger.table(
244
- [
245
- { header: 'Component', key: 'component', width: 20, align: 'left', color: 'cyan' },
246
- { header: 'Class Name', key: 'className', width: 25, align: 'left' },
247
- { header: 'File', key: 'file', width: 20, align: 'left', color: 'gray' }
248
- ],
249
- componentData
250
- )
251
-
252
- this.generateRegistrationFile(components)
253
-
254
- // Inject import into entry point for build
255
- this.injectImportIntoEntryPoint()
256
-
257
- return components
258
- }
259
-
260
- /**
261
- * Post-build hook: Clean up backup file and restore entry point
262
- * Note: Since the generated file is now in core/, we always keep it (it's bundled into production)
263
- */
264
- async postBuild(keepGenerated: boolean = true): Promise<void> {
265
- buildLogger.step('Cleaning up Live Components registration...')
266
-
267
- // Always keep the generated file in core/ (it gets bundled)
268
- // Just remove the backup
269
- if (existsSync(this.backupFilePath)) {
270
- unlinkSync(this.backupFilePath)
271
- buildLogger.step('Removed backup file')
272
- }
273
-
274
- // Restore original entry point (remove injected import)
275
- this.removeInjectedImport()
276
- }
277
-
278
- /**
279
- * Development mode: Check if registration needs update
280
- */
281
- needsUpdate(): boolean {
282
- if (!this.isAutoGenerated()) {
283
- return false // Manual file, don't touch
284
- }
285
-
286
- const components = this.discoverComponents()
287
- const currentContent = readFileSync(this.registrationFilePath, 'utf-8')
288
-
289
- // Check if all discovered components are in the current file
290
- for (const comp of components) {
291
- if (!currentContent.includes(`'${comp.componentName}', ${comp.className}`)) {
292
- return true
293
- }
294
- }
295
-
296
- // Check if the file references components that no longer exist (deleted files)
297
- const registeredMatches = currentContent.matchAll(/registerComponentClass\('(\w+)',\s*(\w+)\)/g)
298
- const discoveredNames = new Set(components.map(c => c.componentName))
299
- for (const match of registeredMatches) {
300
- if (!discoveredNames.has(match[1])) {
301
- return true
302
- }
303
- }
304
-
305
- return false
306
- }
307
-
308
- /**
309
- * Development mode: Update registration if needed
310
- */
311
- updateIfNeeded(): void {
312
- if (this.needsUpdate()) {
313
- buildLogger.info('Live Components changed, updating registration...')
314
- const components = this.discoverComponents()
315
- this.generateRegistrationFile(components)
316
- }
317
- }
318
- }
319
-
320
- // Export singleton instance
321
- export const liveComponentsGenerator = new LiveComponentsGenerator()