create-fluxstack 1.7.5 → 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/.dockerignore +82 -0
- package/.env.example +19 -0
- package/Dockerfile +70 -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/app.ts +20 -5
- package/app/server/backend-only.ts +15 -12
- package/app/server/controllers/users.controller.ts +57 -31
- package/app/server/index.ts +86 -96
- package/app/server/live/register-components.ts +18 -7
- package/app/server/routes/env-test.ts +110 -0
- package/app/server/routes/index.ts +1 -8
- package/app/server/routes/users.routes.ts +192 -91
- package/config/app.config.ts +2 -54
- package/config/client.config.ts +95 -0
- package/config/fluxstack.config.ts +2 -2
- package/config/index.ts +57 -22
- package/config/monitoring.config.ts +114 -0
- package/config/plugins.config.ts +80 -0
- package/config/runtime.config.ts +0 -17
- package/config/server.config.ts +50 -30
- package/core/build/bundler.ts +17 -16
- package/core/build/flux-plugins-generator.ts +34 -23
- package/core/build/index.ts +32 -31
- package/core/build/live-components-generator.ts +44 -30
- package/core/build/optimizer.ts +37 -17
- 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 -189
- 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 +5 -1
- package/core/config/runtime-config.ts +12 -10
- package/core/config/schema.ts +33 -2
- package/core/framework/server.ts +30 -14
- package/core/framework/types.ts +2 -2
- package/core/index.ts +31 -23
- 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 +75 -277
- package/core/plugins/built-in/swagger/index.ts +301 -231
- package/core/plugins/built-in/vite/index.ts +342 -377
- 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 +25 -21
- package/core/plugins/types.ts +147 -5
- package/core/server/backend-entry.ts +51 -0
- 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/types/plugin.ts +6 -0
- package/core/utils/build-logger.ts +324 -0
- package/core/utils/config-schema.ts +2 -6
- package/core/utils/helpers.ts +14 -9
- package/core/utils/logger/startup-banner.ts +7 -33
- package/core/utils/regenerate-files.ts +69 -0
- package/core/utils/version.ts +6 -6
- package/create-fluxstack.ts +68 -25
- package/fluxstack.config.ts +138 -252
- package/package.json +3 -18
- 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 +17 -26
- 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
- package/config/build.config.ts +0 -24
|
@@ -1,378 +1,343 @@
|
|
|
1
|
-
import type { FluxStack, PluginContext, RequestContext } from "
|
|
2
|
-
import { createServer, type ViteDevServer } from 'vite'
|
|
3
|
-
import { FLUXSTACK_VERSION } from "
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
requestContext.
|
|
197
|
-
requestContext.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
} catch (error) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
for (const port of portsToTry) {
|
|
345
|
-
try {
|
|
346
|
-
const isRunning = await checkViteRunning(host, port, 1000)
|
|
347
|
-
if (isRunning) {
|
|
348
|
-
return port
|
|
349
|
-
}
|
|
350
|
-
} catch (error) {
|
|
351
|
-
// Continue trying other ports
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
return null
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// Check if Vite is running
|
|
359
|
-
async function checkViteRunning(host: string, port: number, timeout: number = 1000): Promise<boolean> {
|
|
360
|
-
try {
|
|
361
|
-
const controller = new AbortController()
|
|
362
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout)
|
|
363
|
-
|
|
364
|
-
const response = await fetch(`http://${host}:${port}`, {
|
|
365
|
-
signal: controller.signal,
|
|
366
|
-
method: 'HEAD' // Use HEAD to minimize data transfer
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
clearTimeout(timeoutId)
|
|
370
|
-
return response.status >= 200 && response.status < 500
|
|
371
|
-
} catch (error) {
|
|
372
|
-
return false
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Note: Proxy logic is now handled directly in the onBeforeRoute hook above
|
|
377
|
-
|
|
1
|
+
import type { FluxStack, PluginContext, RequestContext } from "@/core/plugins/types"
|
|
2
|
+
import { createServer, type ViteDevServer } from 'vite'
|
|
3
|
+
import { FLUXSTACK_VERSION } from "@/core/utils/version"
|
|
4
|
+
import { clientConfig } from '@/config/client.config'
|
|
5
|
+
|
|
6
|
+
type Plugin = FluxStack.Plugin
|
|
7
|
+
|
|
8
|
+
let viteServer: ViteDevServer | null = null
|
|
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
|
+
|
|
37
|
+
export const vitePlugin: Plugin = {
|
|
38
|
+
name: "vite",
|
|
39
|
+
version: FLUXSTACK_VERSION,
|
|
40
|
+
description: "Enhanced Vite integration plugin for FluxStack with improved error handling and monitoring",
|
|
41
|
+
author: "FluxStack Team",
|
|
42
|
+
priority: 800, // Should run early to setup proxying
|
|
43
|
+
category: "development",
|
|
44
|
+
tags: ["vite", "development", "hot-reload"],
|
|
45
|
+
dependencies: [],
|
|
46
|
+
|
|
47
|
+
setup: async (context: PluginContext) => {
|
|
48
|
+
if (!DEFAULTS.enabled) {
|
|
49
|
+
context.logger.debug('Vite plugin disabled or no client configuration found')
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const vitePort = DEFAULTS.port || clientConfig.vite.port || 5173
|
|
54
|
+
const viteHost = DEFAULTS.host || "localhost"
|
|
55
|
+
|
|
56
|
+
// Import group logger utilities
|
|
57
|
+
const { startGroup, endGroup, logInGroup } = await import('@/core/utils/logger/group-logger')
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
// Start Vite dev server programmatically (silently)
|
|
61
|
+
viteServer = await createServer({
|
|
62
|
+
configFile: './vite.config.ts',
|
|
63
|
+
// Don't override root - let vite.config.ts handle it
|
|
64
|
+
server: {
|
|
65
|
+
port: vitePort,
|
|
66
|
+
host: viteHost,
|
|
67
|
+
strictPort: true
|
|
68
|
+
},
|
|
69
|
+
logLevel: 'silent' // Suppress all Vite logs
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
await viteServer.listen()
|
|
73
|
+
|
|
74
|
+
context.logger.debug(`Vite server started on ${viteHost}:${vitePort} (internal proxy)`)
|
|
75
|
+
context.logger.debug('Hot reload coordination active')
|
|
76
|
+
|
|
77
|
+
// Store Vite config in context for later use
|
|
78
|
+
; (context as any).viteConfig = {
|
|
79
|
+
port: vitePort,
|
|
80
|
+
host: viteHost,
|
|
81
|
+
server: viteServer
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Setup cleanup on process exit
|
|
85
|
+
const cleanup = async () => {
|
|
86
|
+
if (viteServer) {
|
|
87
|
+
context.logger.debug('🛑 Stopping Vite server...')
|
|
88
|
+
await viteServer.close()
|
|
89
|
+
viteServer = null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
process.on('SIGINT', cleanup)
|
|
94
|
+
process.on('SIGTERM', cleanup)
|
|
95
|
+
process.on('exit', cleanup)
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
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...')
|
|
117
|
+
|
|
118
|
+
// Fallback to monitoring if programmatic start fails
|
|
119
|
+
; (context as any).viteConfig = {
|
|
120
|
+
port: vitePort,
|
|
121
|
+
host: viteHost
|
|
122
|
+
}
|
|
123
|
+
monitorVite(context, viteHost, vitePort)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
onServerStart: async (context: PluginContext) => {
|
|
129
|
+
const viteConfig = (context as any).viteConfig
|
|
130
|
+
|
|
131
|
+
if (DEFAULTS.enabled && viteConfig) {
|
|
132
|
+
context.logger.debug(`Vite integration active - monitoring ${viteConfig.host}:${viteConfig.port}`)
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
onBeforeRoute: async (requestContext: RequestContext) => {
|
|
137
|
+
// Skip API routes and swagger - let them be handled by backend
|
|
138
|
+
if (requestContext.path.startsWith("/api") || requestContext.path.startsWith("/swagger")) {
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// For Vite internal routes, proxy directly to Vite server
|
|
143
|
+
if (requestContext.path.startsWith("/@") || // All Vite internal routes (/@vite/, /@fs/, /@react-refresh, etc.)
|
|
144
|
+
requestContext.path.startsWith("/__vite") || // Vite HMR and dev routes
|
|
145
|
+
requestContext.path.startsWith("/node_modules") || // Direct node_modules access
|
|
146
|
+
requestContext.path.includes("/.vite/") || // Vite cache and deps
|
|
147
|
+
requestContext.path.endsWith(".js.map") || // Source maps
|
|
148
|
+
requestContext.path.endsWith(".css.map")) { // CSS source maps
|
|
149
|
+
|
|
150
|
+
// Use fixed configuration for Vite proxy
|
|
151
|
+
const viteHost = "localhost"
|
|
152
|
+
const vitePort = 5173
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const url = parseRequestURL(requestContext.request)
|
|
156
|
+
const viteUrl = `http://${viteHost}:${vitePort}${requestContext.path}${url.search}`
|
|
157
|
+
|
|
158
|
+
// Forward request to Vite
|
|
159
|
+
const response = await fetch(viteUrl, {
|
|
160
|
+
method: requestContext.method,
|
|
161
|
+
headers: requestContext.headers,
|
|
162
|
+
body: requestContext.method !== 'GET' && requestContext.method !== 'HEAD' ? requestContext.request.body : undefined
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Return the Vite response
|
|
166
|
+
const body = await response.arrayBuffer()
|
|
167
|
+
|
|
168
|
+
requestContext.handled = true
|
|
169
|
+
requestContext.response = new Response(body, {
|
|
170
|
+
status: response.status,
|
|
171
|
+
statusText: response.statusText,
|
|
172
|
+
headers: response.headers
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
} catch (viteError) {
|
|
176
|
+
// If Vite fails, let the request continue to normal routing (will become 404)
|
|
177
|
+
// Only log if explicitly enabled for debugging
|
|
178
|
+
const { clientConfig } = await import('@/config/client.config')
|
|
179
|
+
if (clientConfig.vite.enableLogging) {
|
|
180
|
+
console.warn(`Vite proxy error: ${viteError}`)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Use fixed configuration for simplicity - Vite should be running on port 5173
|
|
187
|
+
const viteHost = "localhost"
|
|
188
|
+
const vitePort = 5173
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const url = parseRequestURL(requestContext.request)
|
|
192
|
+
const viteUrl = `http://${viteHost}:${vitePort}${requestContext.path}${url.search}`
|
|
193
|
+
|
|
194
|
+
// Forward request to Vite
|
|
195
|
+
const response = await fetch(viteUrl, {
|
|
196
|
+
method: requestContext.method,
|
|
197
|
+
headers: requestContext.headers,
|
|
198
|
+
body: requestContext.method !== 'GET' && requestContext.method !== 'HEAD' ? requestContext.request.body : undefined
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// If Vite responds successfully, handle the request
|
|
202
|
+
if (response.ok || response.status < 500) {
|
|
203
|
+
// Return a proper Response object with all headers and status
|
|
204
|
+
const body = await response.arrayBuffer()
|
|
205
|
+
|
|
206
|
+
requestContext.handled = true
|
|
207
|
+
requestContext.response = new Response(body, {
|
|
208
|
+
status: response.status,
|
|
209
|
+
statusText: response.statusText,
|
|
210
|
+
headers: response.headers
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
} catch (viteError) {
|
|
215
|
+
// If Vite fails, let the request continue to normal routing (will become 404)
|
|
216
|
+
// Only log if explicitly enabled for debugging
|
|
217
|
+
const { clientConfig } = await import('@/config/client.config')
|
|
218
|
+
if (clientConfig.vite.enableLogging) {
|
|
219
|
+
console.warn(`Vite proxy error: ${viteError}`)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Monitor Vite server status with automatic port detection
|
|
226
|
+
async function monitorVite(
|
|
227
|
+
context: PluginContext,
|
|
228
|
+
host: string,
|
|
229
|
+
initialPort: number
|
|
230
|
+
) {
|
|
231
|
+
let retries = 0
|
|
232
|
+
let isConnected = false
|
|
233
|
+
let actualPort = initialPort
|
|
234
|
+
let portDetected = false
|
|
235
|
+
|
|
236
|
+
const checkVite = async () => {
|
|
237
|
+
try {
|
|
238
|
+
// If we haven't found the correct port yet, try to detect it
|
|
239
|
+
if (!portDetected) {
|
|
240
|
+
const detectedPort = await detectVitePort(host, initialPort)
|
|
241
|
+
if (detectedPort !== null) {
|
|
242
|
+
actualPort = detectedPort
|
|
243
|
+
portDetected = true
|
|
244
|
+
// Update the context with the detected port
|
|
245
|
+
if ((context as any).viteConfig) {
|
|
246
|
+
; (context as any).viteConfig.port = actualPort
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const isRunning = await checkViteRunning(host, actualPort, DEFAULTS.timeout)
|
|
252
|
+
|
|
253
|
+
if (isRunning && !isConnected) {
|
|
254
|
+
isConnected = true
|
|
255
|
+
retries = 0
|
|
256
|
+
if (actualPort !== initialPort) {
|
|
257
|
+
context.logger.debug(`✓ Vite server detected on ${host}:${actualPort} (auto-detected from port ${initialPort})`)
|
|
258
|
+
} else {
|
|
259
|
+
context.logger.debug(`✓ Vite server detected on ${host}:${actualPort}`)
|
|
260
|
+
}
|
|
261
|
+
context.logger.debug("Hot reload coordination active")
|
|
262
|
+
} else if (!isRunning && isConnected) {
|
|
263
|
+
isConnected = false
|
|
264
|
+
context.logger.warn(`✗ Vite server disconnected from ${host}:${actualPort}`)
|
|
265
|
+
// Reset port detection when disconnected
|
|
266
|
+
portDetected = false
|
|
267
|
+
actualPort = initialPort
|
|
268
|
+
} else if (!isRunning) {
|
|
269
|
+
retries++
|
|
270
|
+
if (retries <= DEFAULTS.maxRetries) {
|
|
271
|
+
if (portDetected) {
|
|
272
|
+
context.logger.debug(`Waiting for Vite server on ${host}:${actualPort}... (${retries}/${DEFAULTS.maxRetries})`)
|
|
273
|
+
} else {
|
|
274
|
+
context.logger.debug(`Detecting Vite server port... (${retries}/${DEFAULTS.maxRetries})`)
|
|
275
|
+
}
|
|
276
|
+
} else if (retries === DEFAULTS.maxRetries + 1) {
|
|
277
|
+
context.logger.warn(`Vite server not found after ${DEFAULTS.maxRetries} attempts. Development features may be limited.`)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (isConnected) {
|
|
282
|
+
context.logger.error('Error checking Vite server status', { error })
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Continue monitoring
|
|
287
|
+
setTimeout(checkVite, DEFAULTS.checkInterval)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Start monitoring after a brief delay
|
|
291
|
+
setTimeout(checkVite, 1000)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Auto-detect Vite port by trying common ports
|
|
295
|
+
async function detectVitePort(host: string, startPort: number): Promise<number | null> {
|
|
296
|
+
// Try the initial port first, then common alternatives
|
|
297
|
+
const portsToTry = [
|
|
298
|
+
startPort,
|
|
299
|
+
startPort + 1,
|
|
300
|
+
startPort + 2,
|
|
301
|
+
startPort + 3,
|
|
302
|
+
5174, // Common Vite alternative
|
|
303
|
+
5175,
|
|
304
|
+
5176,
|
|
305
|
+
3000, // Sometimes Vite might use this
|
|
306
|
+
4173 // Another common alternative
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
for (const port of portsToTry) {
|
|
310
|
+
try {
|
|
311
|
+
const isRunning = await checkViteRunning(host, port, 1000)
|
|
312
|
+
if (isRunning) {
|
|
313
|
+
return port
|
|
314
|
+
}
|
|
315
|
+
} catch (error) {
|
|
316
|
+
// Continue trying other ports
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return null
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Check if Vite is running
|
|
324
|
+
async function checkViteRunning(host: string, port: number, timeout: number = 1000): Promise<boolean> {
|
|
325
|
+
try {
|
|
326
|
+
const controller = new AbortController()
|
|
327
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout)
|
|
328
|
+
|
|
329
|
+
const response = await fetch(`http://${host}:${port}`, {
|
|
330
|
+
signal: controller.signal,
|
|
331
|
+
method: 'HEAD' // Use HEAD to minimize data transfer
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
clearTimeout(timeoutId)
|
|
335
|
+
return response.status >= 200 && response.status < 500
|
|
336
|
+
} catch (error) {
|
|
337
|
+
return false
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Note: Proxy logic is now handled directly in the onBeforeRoute hook above
|
|
342
|
+
|
|
378
343
|
export default vitePlugin
|