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.
- package/CHANGELOG.md +80 -0
- package/app/client/src/App.tsx +8 -0
- package/app/client/src/live/AuthDemo.tsx +4 -4
- package/core/build/bundler.ts +40 -26
- package/core/build/flux-plugins-generator.ts +325 -325
- package/core/build/index.ts +92 -21
- package/core/cli/command-registry.ts +44 -46
- package/core/cli/commands/build.ts +11 -6
- package/core/cli/commands/create.ts +7 -5
- package/core/cli/commands/dev.ts +6 -5
- package/core/cli/commands/help.ts +3 -2
- package/core/cli/commands/make-plugin.ts +8 -7
- package/core/cli/commands/plugin-add.ts +60 -43
- package/core/cli/commands/plugin-deps.ts +73 -57
- package/core/cli/commands/plugin-list.ts +44 -41
- package/core/cli/commands/plugin-remove.ts +33 -22
- package/core/cli/generators/component.ts +770 -769
- package/core/cli/generators/controller.ts +9 -8
- package/core/cli/generators/index.ts +148 -146
- package/core/cli/generators/interactive.ts +228 -227
- package/core/cli/generators/plugin.ts +11 -10
- package/core/cli/generators/prompts.ts +83 -82
- package/core/cli/generators/route.ts +7 -6
- package/core/cli/generators/service.ts +10 -9
- package/core/cli/generators/template-engine.ts +2 -1
- package/core/cli/generators/types.ts +7 -7
- package/core/cli/generators/utils.ts +191 -191
- package/core/cli/index.ts +9 -8
- package/core/cli/plugin-discovery.ts +2 -2
- package/core/client/hooks/useAuth.ts +48 -48
- package/core/client/standalone.ts +18 -17
- package/core/client/state/createStore.ts +192 -192
- package/core/client/state/index.ts +14 -14
- package/core/config/index.ts +1 -0
- package/core/framework/client.ts +131 -131
- package/core/framework/index.ts +7 -7
- package/core/framework/server.ts +72 -112
- package/core/framework/types.ts +2 -2
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +6 -3
- package/core/plugins/built-in/monitoring/index.ts +110 -68
- package/core/plugins/built-in/static/index.ts +2 -2
- package/core/plugins/built-in/swagger/index.ts +9 -9
- package/core/plugins/built-in/vite/index.ts +3 -3
- package/core/plugins/built-in/vite/vite-dev.ts +3 -3
- package/core/plugins/config.ts +50 -47
- package/core/plugins/discovery.ts +10 -4
- package/core/plugins/executor.ts +2 -2
- package/core/plugins/index.ts +206 -203
- package/core/plugins/manager.ts +21 -20
- package/core/plugins/registry.ts +76 -12
- package/core/plugins/types.ts +14 -14
- package/core/server/framework.ts +3 -189
- package/core/server/live/auto-generated-components.ts +11 -29
- package/core/server/live/index.ts +41 -31
- package/core/server/live/websocket-plugin.ts +11 -1
- package/core/server/middleware/elysia-helpers.ts +16 -15
- package/core/server/middleware/errorHandling.ts +14 -14
- package/core/server/middleware/index.ts +31 -31
- package/core/server/plugins/database.ts +181 -180
- package/core/server/plugins/static-files-plugin.ts +4 -3
- package/core/server/plugins/swagger.ts +11 -8
- package/core/server/rooms/RoomBroadcaster.ts +11 -10
- package/core/server/rooms/RoomSystem.ts +14 -11
- package/core/server/services/BaseService.ts +7 -7
- package/core/server/services/ServiceContainer.ts +5 -5
- package/core/server/services/index.ts +8 -8
- package/core/templates/create-project.ts +28 -27
- package/core/testing/index.ts +9 -9
- package/core/testing/setup.ts +73 -73
- package/core/types/api.ts +168 -168
- package/core/types/config.ts +5 -5
- package/core/types/index.ts +1 -1
- package/core/types/plugin.ts +2 -2
- package/core/types/types.ts +3 -3
- package/core/utils/build-logger.ts +324 -324
- package/core/utils/config-schema.ts +480 -480
- package/core/utils/env.ts +10 -8
- package/core/utils/errors/codes.ts +114 -114
- package/core/utils/errors/handlers.ts +30 -20
- package/core/utils/errors/index.ts +54 -46
- package/core/utils/errors/middleware.ts +113 -113
- package/core/utils/helpers.ts +19 -16
- package/core/utils/logger/colors.ts +114 -114
- package/core/utils/logger/config.ts +2 -2
- package/core/utils/logger/formatter.ts +82 -82
- package/core/utils/logger/group-logger.ts +101 -101
- package/core/utils/logger/index.ts +13 -3
- package/core/utils/logger/startup-banner.ts +2 -2
- package/core/utils/logger/winston-logger.ts +152 -152
- package/core/utils/monitoring/index.ts +211 -211
- package/core/utils/sync-version.ts +67 -66
- package/core/utils/version.ts +1 -1
- package/package.json +104 -100
- package/playwright-report/index.html +85 -0
- package/playwright.config.ts +31 -0
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
- package/plugins/crypto-auth/client/components/index.ts +11 -11
- package/plugins/crypto-auth/client/index.ts +11 -11
- package/plugins/crypto-auth/package.json +65 -65
- package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +6 -5
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +6 -5
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +3 -3
- package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
- package/plugins/crypto-auth/server/middlewares.ts +19 -19
- package/vite.config.ts +13 -0
- package/app/client/.live-stubs/LiveAdminPanel.js +0 -5
- package/app/client/.live-stubs/LiveCounter.js +0 -9
- package/app/client/.live-stubs/LiveForm.js +0 -11
- package/app/client/.live-stubs/LiveLocalCounter.js +0 -8
- package/app/client/.live-stubs/LivePingPong.js +0 -10
- package/app/client/.live-stubs/LiveRoomChat.js +0 -11
- package/app/client/.live-stubs/LiveSharedCounter.js +0 -10
- package/app/client/.live-stubs/LiveUpload.js +0 -15
- package/app/server/live/register-components.ts +0 -19
- package/core/build/live-components-generator.ts +0 -321
- package/core/live/ComponentRegistry.ts +0 -403
- package/core/live/types.ts +0 -241
- 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,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,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()
|