create-fluxstack 1.8.1 → 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/.env.example +19 -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/controllers/users.controller.ts +57 -31
- package/app/server/index.ts +5 -2
- package/app/server/live/register-components.ts +18 -7
- package/app/server/routes/env-test.ts +53 -2
- package/app/server/routes/index.ts +1 -8
- package/app/server/routes/users.routes.ts +192 -91
- package/config/fluxstack.config.ts +2 -2
- package/config/plugins.config.ts +22 -1
- package/core/build/flux-plugins-generator.ts +5 -5
- package/core/build/live-components-generator.ts +15 -12
- 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 -193
- 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 +1 -1
- package/core/config/runtime-config.ts +5 -5
- package/core/config/schema.ts +9 -0
- package/core/framework/server.ts +30 -15
- package/core/framework/types.ts +2 -2
- 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 +18 -47
- package/core/plugins/built-in/swagger/index.ts +301 -231
- package/core/plugins/built-in/vite/index.ts +74 -109
- 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 +3 -3
- package/core/plugins/types.ts +147 -5
- 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/utils/logger/startup-banner.ts +7 -33
- package/core/utils/version.ts +6 -6
- package/create-fluxstack.ts +68 -25
- package/package.json +2 -2
- 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 +11 -2
- 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
|
@@ -1,11 +1,39 @@
|
|
|
1
|
-
import type { FluxStack, PluginContext, RequestContext } from "
|
|
1
|
+
import type { FluxStack, PluginContext, RequestContext } from "@/core/plugins/types"
|
|
2
2
|
import { createServer, type ViteDevServer } from 'vite'
|
|
3
|
-
import { FLUXSTACK_VERSION } from "
|
|
3
|
+
import { FLUXSTACK_VERSION } from "@/core/utils/version"
|
|
4
|
+
import { clientConfig } from '@/config/client.config'
|
|
4
5
|
|
|
5
6
|
type Plugin = FluxStack.Plugin
|
|
6
7
|
|
|
7
8
|
let viteServer: ViteDevServer | null = null
|
|
8
9
|
|
|
10
|
+
// Default configuration values (uses clientConfig from /config)
|
|
11
|
+
const DEFAULTS = {
|
|
12
|
+
enabled: true,
|
|
13
|
+
port: clientConfig.vite.port,
|
|
14
|
+
host: "localhost",
|
|
15
|
+
checkInterval: 2000,
|
|
16
|
+
maxRetries: 10,
|
|
17
|
+
timeout: 5000,
|
|
18
|
+
proxyPaths: [] as string[],
|
|
19
|
+
excludePaths: [] as string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Helper to safely parse request.url which might be relative or absolute
|
|
24
|
+
*/
|
|
25
|
+
function parseRequestURL(request: Request): URL {
|
|
26
|
+
try {
|
|
27
|
+
// Try parsing as absolute URL first
|
|
28
|
+
return new URL(request.url)
|
|
29
|
+
} catch {
|
|
30
|
+
// If relative, use host from headers or default to localhost
|
|
31
|
+
const host = request.headers.get('host') || 'localhost'
|
|
32
|
+
const protocol = request.headers.get('x-forwarded-proto') || 'http'
|
|
33
|
+
return new URL(request.url, `${protocol}://${host}`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
9
37
|
export const vitePlugin: Plugin = {
|
|
10
38
|
name: "vite",
|
|
11
39
|
version: FLUXSTACK_VERSION,
|
|
@@ -14,89 +42,22 @@ export const vitePlugin: Plugin = {
|
|
|
14
42
|
priority: 800, // Should run early to setup proxying
|
|
15
43
|
category: "development",
|
|
16
44
|
tags: ["vite", "development", "hot-reload"],
|
|
17
|
-
dependencies: [],
|
|
18
|
-
|
|
19
|
-
configSchema: {
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: {
|
|
22
|
-
enabled: {
|
|
23
|
-
type: "boolean",
|
|
24
|
-
description: "Enable Vite integration"
|
|
25
|
-
},
|
|
26
|
-
port: {
|
|
27
|
-
type: "number",
|
|
28
|
-
minimum: 1,
|
|
29
|
-
maximum: 65535,
|
|
30
|
-
description: "Vite development server port"
|
|
31
|
-
},
|
|
32
|
-
host: {
|
|
33
|
-
type: "string",
|
|
34
|
-
description: "Vite development server host"
|
|
35
|
-
},
|
|
36
|
-
checkInterval: {
|
|
37
|
-
type: "number",
|
|
38
|
-
minimum: 100,
|
|
39
|
-
description: "Interval to check if Vite is running (ms)"
|
|
40
|
-
},
|
|
41
|
-
maxRetries: {
|
|
42
|
-
type: "number",
|
|
43
|
-
minimum: 1,
|
|
44
|
-
description: "Maximum retries to connect to Vite"
|
|
45
|
-
},
|
|
46
|
-
timeout: {
|
|
47
|
-
type: "number",
|
|
48
|
-
minimum: 100,
|
|
49
|
-
description: "Timeout for Vite requests (ms)"
|
|
50
|
-
},
|
|
51
|
-
proxyPaths: {
|
|
52
|
-
type: "array",
|
|
53
|
-
items: { type: "string" },
|
|
54
|
-
description: "Paths to proxy to Vite (defaults to all non-API paths)"
|
|
55
|
-
},
|
|
56
|
-
excludePaths: {
|
|
57
|
-
type: "array",
|
|
58
|
-
items: { type: "string" },
|
|
59
|
-
description: "Paths to exclude from Vite proxying"
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
additionalProperties: false
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
defaultConfig: {
|
|
66
|
-
enabled: true,
|
|
67
|
-
port: 5173,
|
|
68
|
-
host: "localhost",
|
|
69
|
-
checkInterval: 2000,
|
|
70
|
-
maxRetries: 10,
|
|
71
|
-
timeout: 5000,
|
|
72
|
-
proxyPaths: [],
|
|
73
|
-
excludePaths: []
|
|
74
|
-
},
|
|
45
|
+
dependencies: [],
|
|
75
46
|
|
|
76
47
|
setup: async (context: PluginContext) => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (!config.enabled || !context.config.client) {
|
|
48
|
+
if (!DEFAULTS.enabled) {
|
|
80
49
|
context.logger.debug('Vite plugin disabled or no client configuration found')
|
|
81
50
|
return
|
|
82
51
|
}
|
|
83
52
|
|
|
84
|
-
const vitePort =
|
|
85
|
-
const viteHost =
|
|
53
|
+
const vitePort = DEFAULTS.port || clientConfig.vite.port || 5173
|
|
54
|
+
const viteHost = DEFAULTS.host || "localhost"
|
|
86
55
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
startGroup({
|
|
91
|
-
title: 'Vite Development Server',
|
|
92
|
-
icon: '🎨',
|
|
93
|
-
color: 'magenta',
|
|
94
|
-
collapsed: true
|
|
95
|
-
})
|
|
56
|
+
// Import group logger utilities
|
|
57
|
+
const { startGroup, endGroup, logInGroup } = await import('@/core/utils/logger/group-logger')
|
|
96
58
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// Start Vite dev server programmatically
|
|
59
|
+
try {
|
|
60
|
+
// Start Vite dev server programmatically (silently)
|
|
100
61
|
viteServer = await createServer({
|
|
101
62
|
configFile: './vite.config.ts',
|
|
102
63
|
// Don't override root - let vite.config.ts handle it
|
|
@@ -105,23 +66,18 @@ export const vitePlugin: Plugin = {
|
|
|
105
66
|
host: viteHost,
|
|
106
67
|
strictPort: true
|
|
107
68
|
},
|
|
108
|
-
logLevel: '
|
|
69
|
+
logLevel: 'silent' // Suppress all Vite logs
|
|
109
70
|
})
|
|
110
71
|
|
|
111
72
|
await viteServer.listen()
|
|
112
73
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
logInGroup('Hot reload coordination active', '🔄')
|
|
116
|
-
|
|
117
|
-
endGroup()
|
|
118
|
-
console.log('') // Separator line
|
|
74
|
+
context.logger.debug(`Vite server started on ${viteHost}:${vitePort} (internal proxy)`)
|
|
75
|
+
context.logger.debug('Hot reload coordination active')
|
|
119
76
|
|
|
120
77
|
// Store Vite config in context for later use
|
|
121
78
|
; (context as any).viteConfig = {
|
|
122
79
|
port: vitePort,
|
|
123
80
|
host: viteHost,
|
|
124
|
-
...config,
|
|
125
81
|
server: viteServer
|
|
126
82
|
}
|
|
127
83
|
|
|
@@ -139,24 +95,40 @@ export const vitePlugin: Plugin = {
|
|
|
139
95
|
process.on('exit', cleanup)
|
|
140
96
|
|
|
141
97
|
} catch (error) {
|
|
142
|
-
|
|
143
|
-
|
|
98
|
+
// Check if error is related to port already in use
|
|
99
|
+
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
100
|
+
const isPortInUse = errorMessage.includes('EADDRINUSE') ||
|
|
101
|
+
errorMessage.includes('address already in use') ||
|
|
102
|
+
errorMessage.includes('Port') && errorMessage.includes('is in use')
|
|
103
|
+
|
|
104
|
+
if (isPortInUse) {
|
|
105
|
+
endGroup()
|
|
106
|
+
console.log('') // Separator line
|
|
107
|
+
context.logger.error(`❌ Failed to start Vite: Port ${vitePort} is already in use`)
|
|
108
|
+
context.logger.info(`💡 Try one of these solutions:`)
|
|
109
|
+
context.logger.info(` 1. Stop the process using port ${vitePort}`)
|
|
110
|
+
context.logger.info(` 2. Change VITE_PORT in your .env file`)
|
|
111
|
+
context.logger.info(` 3. Kill the process: ${process.platform === 'win32' ? `netstat -ano | findstr :${vitePort}` : `lsof -ti:${vitePort} | xargs kill -9`}`)
|
|
112
|
+
process.exit(1)
|
|
113
|
+
} else {
|
|
114
|
+
context.logger.error('❌ Failed to start Vite server:', errorMessage)
|
|
115
|
+
context.logger.debug('Full error:', error)
|
|
116
|
+
context.logger.debug('⚠️ Falling back to monitoring mode...')
|
|
144
117
|
|
|
145
118
|
// Fallback to monitoring if programmatic start fails
|
|
146
119
|
; (context as any).viteConfig = {
|
|
147
120
|
port: vitePort,
|
|
148
|
-
host: viteHost
|
|
149
|
-
...config
|
|
121
|
+
host: viteHost
|
|
150
122
|
}
|
|
151
|
-
|
|
123
|
+
monitorVite(context, viteHost, vitePort)
|
|
124
|
+
}
|
|
152
125
|
}
|
|
153
126
|
},
|
|
154
127
|
|
|
155
128
|
onServerStart: async (context: PluginContext) => {
|
|
156
|
-
const config = getPluginConfig(context)
|
|
157
129
|
const viteConfig = (context as any).viteConfig
|
|
158
130
|
|
|
159
|
-
if (
|
|
131
|
+
if (DEFAULTS.enabled && viteConfig) {
|
|
160
132
|
context.logger.debug(`Vite integration active - monitoring ${viteConfig.host}:${viteConfig.port}`)
|
|
161
133
|
}
|
|
162
134
|
},
|
|
@@ -180,7 +152,7 @@ export const vitePlugin: Plugin = {
|
|
|
180
152
|
const vitePort = 5173
|
|
181
153
|
|
|
182
154
|
try {
|
|
183
|
-
const url =
|
|
155
|
+
const url = parseRequestURL(requestContext.request)
|
|
184
156
|
const viteUrl = `http://${viteHost}:${vitePort}${requestContext.path}${url.search}`
|
|
185
157
|
|
|
186
158
|
// Forward request to Vite
|
|
@@ -216,7 +188,7 @@ export const vitePlugin: Plugin = {
|
|
|
216
188
|
const vitePort = 5173
|
|
217
189
|
|
|
218
190
|
try {
|
|
219
|
-
const url =
|
|
191
|
+
const url = parseRequestURL(requestContext.request)
|
|
220
192
|
const viteUrl = `http://${viteHost}:${vitePort}${requestContext.path}${url.search}`
|
|
221
193
|
|
|
222
194
|
// Forward request to Vite
|
|
@@ -250,18 +222,11 @@ export const vitePlugin: Plugin = {
|
|
|
250
222
|
}
|
|
251
223
|
}
|
|
252
224
|
|
|
253
|
-
// Helper function to get plugin config
|
|
254
|
-
function getPluginConfig(context: PluginContext) {
|
|
255
|
-
const pluginConfig = context.config.plugins.config?.vite || {}
|
|
256
|
-
return { ...vitePlugin.defaultConfig, ...pluginConfig }
|
|
257
|
-
}
|
|
258
|
-
|
|
259
225
|
// Monitor Vite server status with automatic port detection
|
|
260
226
|
async function monitorVite(
|
|
261
227
|
context: PluginContext,
|
|
262
228
|
host: string,
|
|
263
|
-
initialPort: number
|
|
264
|
-
config: any
|
|
229
|
+
initialPort: number
|
|
265
230
|
) {
|
|
266
231
|
let retries = 0
|
|
267
232
|
let isConnected = false
|
|
@@ -283,7 +248,7 @@ async function monitorVite(
|
|
|
283
248
|
}
|
|
284
249
|
}
|
|
285
250
|
|
|
286
|
-
const isRunning = await checkViteRunning(host, actualPort,
|
|
251
|
+
const isRunning = await checkViteRunning(host, actualPort, DEFAULTS.timeout)
|
|
287
252
|
|
|
288
253
|
if (isRunning && !isConnected) {
|
|
289
254
|
isConnected = true
|
|
@@ -302,14 +267,14 @@ async function monitorVite(
|
|
|
302
267
|
actualPort = initialPort
|
|
303
268
|
} else if (!isRunning) {
|
|
304
269
|
retries++
|
|
305
|
-
if (retries <=
|
|
270
|
+
if (retries <= DEFAULTS.maxRetries) {
|
|
306
271
|
if (portDetected) {
|
|
307
|
-
context.logger.debug(`Waiting for Vite server on ${host}:${actualPort}... (${retries}/${
|
|
272
|
+
context.logger.debug(`Waiting for Vite server on ${host}:${actualPort}... (${retries}/${DEFAULTS.maxRetries})`)
|
|
308
273
|
} else {
|
|
309
|
-
context.logger.debug(`Detecting Vite server port... (${retries}/${
|
|
274
|
+
context.logger.debug(`Detecting Vite server port... (${retries}/${DEFAULTS.maxRetries})`)
|
|
310
275
|
}
|
|
311
|
-
} else if (retries ===
|
|
312
|
-
context.logger.warn(`Vite server not found after ${
|
|
276
|
+
} else if (retries === DEFAULTS.maxRetries + 1) {
|
|
277
|
+
context.logger.warn(`Vite server not found after ${DEFAULTS.maxRetries} attempts. Development features may be limited.`)
|
|
313
278
|
}
|
|
314
279
|
}
|
|
315
280
|
} catch (error) {
|
|
@@ -319,7 +284,7 @@ async function monitorVite(
|
|
|
319
284
|
}
|
|
320
285
|
|
|
321
286
|
// Continue monitoring
|
|
322
|
-
setTimeout(checkVite,
|
|
287
|
+
setTimeout(checkVite, DEFAULTS.checkInterval)
|
|
323
288
|
}
|
|
324
289
|
|
|
325
290
|
// Start monitoring after a brief delay
|
package/core/plugins/config.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { FluxStack, PluginConfigSchema, PluginValidationResult } from "./types"
|
|
7
|
-
import type { FluxStackConfig } from "
|
|
8
|
-
import type { Logger } from "
|
|
7
|
+
import type { FluxStackConfig } from "@/core/config/schema"
|
|
8
|
+
import type { Logger } from "@/core/utils/logger/index"
|
|
9
9
|
|
|
10
10
|
type Plugin = FluxStack.Plugin
|
|
11
11
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
7
7
|
import { join, resolve } from 'path'
|
|
8
8
|
import { execSync } from 'child_process'
|
|
9
|
-
import type { Logger } from '
|
|
9
|
+
import type { Logger } from '@/core/utils/logger'
|
|
10
10
|
|
|
11
11
|
export interface PluginDependency {
|
|
12
12
|
name: string
|
|
@@ -176,7 +176,7 @@ export class PluginDependencyManager {
|
|
|
176
176
|
/**
|
|
177
177
|
* Instalar dependências no diretório local do plugin
|
|
178
178
|
*/
|
|
179
|
-
|
|
179
|
+
async installPluginDependenciesLocally(pluginPath: string, dependencies: PluginDependency[]): Promise<void> {
|
|
180
180
|
if (dependencies.length === 0) return
|
|
181
181
|
|
|
182
182
|
const regularDeps = dependencies.filter(d => d.type === 'dependency')
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { FluxStack, PluginManifest, PluginLoadResult, PluginDiscoveryOptions } from "./types"
|
|
7
|
-
import type { Logger } from "
|
|
7
|
+
import type { Logger } from "@/core/utils/logger/index"
|
|
8
8
|
import { readdir, readFile } from "fs/promises"
|
|
9
9
|
import { join, resolve } from "path"
|
|
10
10
|
import { existsSync } from "fs"
|
package/core/plugins/executor.ts
CHANGED
|
@@ -10,8 +10,8 @@ import type {
|
|
|
10
10
|
PluginPriority,
|
|
11
11
|
HookExecutionOptions
|
|
12
12
|
} from "./types"
|
|
13
|
-
import type { Logger } from "
|
|
14
|
-
import { FluxStackError } from "
|
|
13
|
+
import type { Logger } from "@/core/utils/logger/index"
|
|
14
|
+
import { FluxStackError } from "@/core/utils/errors"
|
|
15
15
|
|
|
16
16
|
export interface PluginExecutionPlan {
|
|
17
17
|
hook: PluginHook
|
package/core/plugins/manager.ts
CHANGED
|
@@ -18,13 +18,28 @@ import type {
|
|
|
18
18
|
} from "./types"
|
|
19
19
|
|
|
20
20
|
type Plugin = FluxStack.Plugin
|
|
21
|
-
import type { FluxStackConfig } from "
|
|
22
|
-
import type { Logger } from "
|
|
21
|
+
import type { FluxStackConfig } from "@/core/config/schema"
|
|
22
|
+
import type { Logger } from "@/core/utils/logger"
|
|
23
23
|
import { PluginRegistry } from "./registry"
|
|
24
24
|
import { createPluginUtils } from "./config"
|
|
25
|
-
import { FluxStackError } from "
|
|
25
|
+
import { FluxStackError } from "@/core/utils/errors"
|
|
26
26
|
import { EventEmitter } from "events"
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Helper to safely parse request.url which might be relative or absolute
|
|
30
|
+
*/
|
|
31
|
+
function parseRequestURL(request: Request): URL {
|
|
32
|
+
try {
|
|
33
|
+
// Try parsing as absolute URL first
|
|
34
|
+
return new URL(request.url)
|
|
35
|
+
} catch {
|
|
36
|
+
// If relative, use host from headers or default to localhost
|
|
37
|
+
const host = request.headers.get('host') || 'localhost'
|
|
38
|
+
const protocol = request.headers.get('x-forwarded-proto') || 'http'
|
|
39
|
+
return new URL(request.url, `${protocol}://${host}`)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
export interface PluginManagerConfig {
|
|
29
44
|
config: FluxStackConfig
|
|
30
45
|
logger: Logger
|
|
@@ -558,7 +573,7 @@ export class PluginManager extends EventEmitter {
|
|
|
558
573
|
* Create request context from HTTP request
|
|
559
574
|
*/
|
|
560
575
|
export function createRequestContext(request: Request, additionalData: any = {}): RequestContext {
|
|
561
|
-
const url =
|
|
576
|
+
const url = parseRequestURL(request)
|
|
562
577
|
|
|
563
578
|
return {
|
|
564
579
|
request,
|
package/core/plugins/registry.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { FluxStack, PluginManifest, PluginLoadResult, PluginDiscoveryOptions } from "./types"
|
|
2
2
|
|
|
3
3
|
type FluxStackPlugin = FluxStack.Plugin
|
|
4
|
-
import type { FluxStackConfig } from "
|
|
5
|
-
import type { Logger } from "
|
|
6
|
-
import { FluxStackError } from "
|
|
4
|
+
import type { FluxStackConfig } from "@/core/config/schema"
|
|
5
|
+
import type { Logger } from "@/core/utils/logger"
|
|
6
|
+
import { FluxStackError } from "@/core/utils/errors"
|
|
7
7
|
import { PluginDependencyManager } from "./dependency-manager"
|
|
8
8
|
import { readdir, readFile } from "fs/promises"
|
|
9
9
|
import { join, resolve } from "path"
|
package/core/plugins/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FluxStackConfig } from "
|
|
2
|
-
import type { Logger } from "
|
|
1
|
+
import type { FluxStackConfig } from "@/core/config/schema"
|
|
2
|
+
import type { Logger } from "@/core/utils/logger/index"
|
|
3
3
|
|
|
4
4
|
export type PluginHook =
|
|
5
5
|
| 'setup'
|
|
@@ -96,11 +96,31 @@ export namespace FluxStack {
|
|
|
96
96
|
onError?: (context: ErrorContext) => void | Promise<void>
|
|
97
97
|
onBuild?: (context: BuildContext) => void | Promise<void>
|
|
98
98
|
onBuildComplete?: (context: BuildContext) => void | Promise<void>
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
// Configuration
|
|
101
|
+
/**
|
|
102
|
+
* @deprecated Use declarative config system instead (plugins/[name]/config/)
|
|
103
|
+
* Create a config/ folder with defineConfig() for type-safe configuration.
|
|
104
|
+
* This property is kept for backward compatibility with built-in plugins.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // ✅ New way (recommended):
|
|
108
|
+
* // plugins/my-plugin/config/index.ts
|
|
109
|
+
* import { defineConfig, config } from '@/core/utils/config-schema'
|
|
110
|
+
* export const myConfig = defineConfig({ ... })
|
|
111
|
+
*
|
|
112
|
+
* // ❌ Old way (deprecated):
|
|
113
|
+
* configSchema: { type: 'object', properties: { ... } }
|
|
114
|
+
*/
|
|
101
115
|
configSchema?: PluginConfigSchema
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @deprecated Use declarative config system with defineConfig()
|
|
119
|
+
* This property will be removed in a future major version.
|
|
120
|
+
* Use the config/ folder structure for automatic type inference.
|
|
121
|
+
*/
|
|
102
122
|
defaultConfig?: any
|
|
103
|
-
|
|
123
|
+
|
|
104
124
|
// CLI commands
|
|
105
125
|
commands?: CliCommand[]
|
|
106
126
|
}
|
|
@@ -251,4 +271,126 @@ export interface CliContext {
|
|
|
251
271
|
name: string
|
|
252
272
|
version: string
|
|
253
273
|
}
|
|
254
|
-
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Live Components Types
|
|
277
|
+
export interface LiveComponent<TState = any> {
|
|
278
|
+
id: string
|
|
279
|
+
name: string
|
|
280
|
+
state: TState
|
|
281
|
+
mounted: boolean
|
|
282
|
+
socket?: any
|
|
283
|
+
userId?: string
|
|
284
|
+
destroy?: () => void
|
|
285
|
+
executeAction?: (action: string, payload?: any) => Promise<any>
|
|
286
|
+
setState?: (newState: Partial<TState>) => void
|
|
287
|
+
getSerializableState?: () => TState
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export interface LiveMessage {
|
|
291
|
+
type: string
|
|
292
|
+
componentId: string
|
|
293
|
+
data?: any
|
|
294
|
+
payload?: any
|
|
295
|
+
action?: string
|
|
296
|
+
property?: string
|
|
297
|
+
userId?: string
|
|
298
|
+
expectResponse?: boolean
|
|
299
|
+
timestamp?: number
|
|
300
|
+
requestId?: string
|
|
301
|
+
room?: string
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export interface BroadcastMessage {
|
|
305
|
+
type: string
|
|
306
|
+
data?: any
|
|
307
|
+
channel?: string
|
|
308
|
+
room?: string
|
|
309
|
+
payload?: any
|
|
310
|
+
excludeUser?: string
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export interface ComponentDefinition<TState = any> {
|
|
314
|
+
name: string
|
|
315
|
+
initialState: TState
|
|
316
|
+
handlers?: Record<string, Function>
|
|
317
|
+
component?: any
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export interface WebSocketData {
|
|
321
|
+
componentId?: string
|
|
322
|
+
userId?: string
|
|
323
|
+
sessionId?: string
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// File Upload Types
|
|
327
|
+
export interface ActiveUpload {
|
|
328
|
+
uploadId: string
|
|
329
|
+
componentId?: string
|
|
330
|
+
filename: string
|
|
331
|
+
fileType?: string
|
|
332
|
+
fileSize?: number
|
|
333
|
+
totalChunks: number
|
|
334
|
+
receivedChunks: Map<number, any>
|
|
335
|
+
startTime: number
|
|
336
|
+
lastChunkTime?: number
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface FileUploadStartMessage {
|
|
340
|
+
type: 'upload:start' | 'FILE_UPLOAD_START'
|
|
341
|
+
uploadId: string
|
|
342
|
+
filename: string
|
|
343
|
+
totalChunks: number
|
|
344
|
+
fileSize: number
|
|
345
|
+
componentId?: string
|
|
346
|
+
fileType?: string
|
|
347
|
+
chunkSize?: number
|
|
348
|
+
requestId?: string
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export interface FileUploadChunkMessage {
|
|
352
|
+
type: 'upload:chunk' | 'FILE_UPLOAD_CHUNK'
|
|
353
|
+
uploadId: string
|
|
354
|
+
chunkIndex: number
|
|
355
|
+
data: string | ArrayBuffer
|
|
356
|
+
totalChunks?: number
|
|
357
|
+
componentId?: string
|
|
358
|
+
requestId?: string
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export interface FileUploadCompleteMessage {
|
|
362
|
+
type: 'upload:complete' | 'FILE_UPLOAD_COMPLETE'
|
|
363
|
+
uploadId: string
|
|
364
|
+
requestId?: string
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export interface FileUploadProgressResponse {
|
|
368
|
+
type: 'upload:progress' | 'FILE_UPLOAD_PROGRESS'
|
|
369
|
+
uploadId: string
|
|
370
|
+
receivedChunks?: number
|
|
371
|
+
totalChunks?: number
|
|
372
|
+
percentage?: number
|
|
373
|
+
componentId?: string
|
|
374
|
+
chunkIndex?: number
|
|
375
|
+
bytesUploaded?: number
|
|
376
|
+
totalBytes?: number
|
|
377
|
+
progress?: number
|
|
378
|
+
timestamp?: number
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export interface FileUploadCompleteResponse {
|
|
382
|
+
type: 'upload:complete' | 'FILE_UPLOAD_COMPLETE'
|
|
383
|
+
uploadId: string
|
|
384
|
+
url?: string
|
|
385
|
+
filename?: string
|
|
386
|
+
size?: number
|
|
387
|
+
componentId?: string
|
|
388
|
+
success?: boolean
|
|
389
|
+
error?: string
|
|
390
|
+
message?: string
|
|
391
|
+
fileUrl?: string
|
|
392
|
+
timestamp?: number
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Plugin Type Export
|
|
396
|
+
export type Plugin = FluxStack.Plugin
|
package/core/server/framework.ts
CHANGED
|
@@ -65,7 +65,7 @@ export class FluxStackFramework {
|
|
|
65
65
|
// Create plugin context
|
|
66
66
|
this.pluginContext = {
|
|
67
67
|
config: fullConfig,
|
|
68
|
-
logger: logger as
|
|
68
|
+
logger: logger as any,
|
|
69
69
|
app: this.app,
|
|
70
70
|
utils: pluginUtils
|
|
71
71
|
}
|
|
@@ -73,7 +73,7 @@ export class FluxStackFramework {
|
|
|
73
73
|
// Initialize plugin manager
|
|
74
74
|
this.pluginManager = new PluginManager({
|
|
75
75
|
config: fullConfig,
|
|
76
|
-
logger: logger as
|
|
76
|
+
logger: logger as any,
|
|
77
77
|
app: this.app
|
|
78
78
|
})
|
|
79
79
|
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
BroadcastMessage,
|
|
7
7
|
ComponentDefinition,
|
|
8
8
|
WebSocketData
|
|
9
|
-
} from '
|
|
9
|
+
} from '@/core/plugins/types'
|
|
10
10
|
import { stateSignature, type SignedState } from './StateSignature'
|
|
11
11
|
import { performanceMonitor } from './LiveComponentPerformanceMonitor'
|
|
12
12
|
|
|
@@ -151,7 +151,7 @@ export class ComponentRegistry {
|
|
|
151
151
|
try {
|
|
152
152
|
const fs = await import('fs')
|
|
153
153
|
const path = await import('path')
|
|
154
|
-
const { startGroup, endGroup, logInGroup, groupSummary } = await import('
|
|
154
|
+
const { startGroup, endGroup, logInGroup, groupSummary } = await import('@/core/utils/logger/group-logger')
|
|
155
155
|
|
|
156
156
|
if (!fs.existsSync(componentsPath)) {
|
|
157
157
|
console.log(`⚠️ Components path not found: ${componentsPath}`)
|
|
@@ -159,15 +159,9 @@ export class ComponentRegistry {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
const files = fs.readdirSync(componentsPath)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
startGroup({
|
|
165
|
-
title: 'Live Components Auto-Discovery',
|
|
166
|
-
icon: '🔍',
|
|
167
|
-
color: 'blue',
|
|
168
|
-
collapsed: true
|
|
169
|
-
})
|
|
162
|
+
const components: string[] = []
|
|
170
163
|
|
|
164
|
+
// Discovery with component names collection
|
|
171
165
|
for (const file of files) {
|
|
172
166
|
if (file.endsWith('.ts') || file.endsWith('.js')) {
|
|
173
167
|
try {
|
|
@@ -183,30 +177,19 @@ export class ComponentRegistry {
|
|
|
183
177
|
|
|
184
178
|
const componentName = exportName.replace(/Component$/, '')
|
|
185
179
|
this.registerComponentClass(componentName, exportedItem)
|
|
186
|
-
|
|
187
|
-
discoveredCount++
|
|
180
|
+
components.push(componentName)
|
|
188
181
|
}
|
|
189
182
|
})
|
|
190
|
-
|
|
191
|
-
// Check for integration hooks (like SystemMonitorIntegration)
|
|
192
|
-
if (module.default && typeof module.default === 'object' && module.default.setupIntegration) {
|
|
193
|
-
logInGroup('Integration hooks found', '🔗')
|
|
194
|
-
}
|
|
195
183
|
} catch (error) {
|
|
196
|
-
|
|
184
|
+
// Silent - only log in debug mode
|
|
197
185
|
}
|
|
198
186
|
}
|
|
199
187
|
}
|
|
200
188
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
} else {
|
|
205
|
-
logInGroup('No components found', '⚠️')
|
|
189
|
+
// Display components in a compact single line format
|
|
190
|
+
if (components.length > 0) {
|
|
191
|
+
console.log(`\nLive Components (${components.length}): ${components.join(', ')}\n`)
|
|
206
192
|
}
|
|
207
|
-
|
|
208
|
-
endGroup()
|
|
209
|
-
console.log('') // Separator line
|
|
210
193
|
} catch (error) {
|
|
211
194
|
console.error('❌ Auto-discovery failed:', error)
|
|
212
195
|
}
|