create-fluxstack 1.8.1 → 1.9.1
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 +653 -272
- 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/bundler.ts +199 -55
- package/core/build/flux-plugins-generator.ts +5 -5
- package/core/build/index.ts +4 -0
- 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 +9 -9
- 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 +258 -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/types/build.ts +21 -0
- package/core/utils/logger/startup-banner.ts +7 -33
- package/core/utils/version.ts +1 -1
- package/create-fluxstack.ts +73 -30
- package/package.json +3 -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/tsconfig.json +2 -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
|
@@ -2,245 +2,78 @@
|
|
|
2
2
|
import { treaty } from '@elysiajs/eden'
|
|
3
3
|
import type { App } from '../../../server/app'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Get base URL dynamically
|
|
7
|
+
*/
|
|
8
|
+
export const getBaseUrl = () => {
|
|
7
9
|
if (typeof window === 'undefined') return 'http://localhost:3000'
|
|
8
|
-
|
|
9
|
-
//
|
|
10
|
+
|
|
11
|
+
// Production: use current origin
|
|
10
12
|
if (window.location.hostname !== 'localhost') {
|
|
11
13
|
return window.location.origin
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
// In development, use backend server (port 3000 for integrated mode)
|
|
15
|
-
return 'http://localhost:3000'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Create Eden Treaty client with proper typing
|
|
19
|
-
const client = treaty<App>(getBaseUrl())
|
|
20
|
-
|
|
21
|
-
// Export the client's API directly to get proper type inference
|
|
22
|
-
export const api = client.api
|
|
23
15
|
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
ClientAPIError,
|
|
27
|
-
NetworkError,
|
|
28
|
-
TimeoutError,
|
|
29
|
-
withRetry,
|
|
30
|
-
withFallback,
|
|
31
|
-
CircuitBreaker,
|
|
32
|
-
getDefaultUserMessage,
|
|
33
|
-
type RetryOptions,
|
|
34
|
-
type FallbackOptions
|
|
35
|
-
} from './errors'
|
|
36
|
-
|
|
37
|
-
// Legacy interface for backward compatibility
|
|
38
|
-
export interface APIError {
|
|
39
|
-
message: string
|
|
40
|
-
status: number
|
|
41
|
-
code?: string
|
|
42
|
-
details?: any
|
|
16
|
+
// Development: use backend server
|
|
17
|
+
return 'http://localhost:3000'
|
|
43
18
|
}
|
|
44
19
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
constructor(error: APIError) {
|
|
52
|
-
super(error.message)
|
|
53
|
-
this.name = 'APIException'
|
|
54
|
-
this.status = error.status
|
|
55
|
-
this.code = error.code
|
|
56
|
-
this.details = error.details
|
|
57
|
-
}
|
|
20
|
+
/**
|
|
21
|
+
* Get auth token from localStorage (optional)
|
|
22
|
+
*/
|
|
23
|
+
const getAuthToken = (): string | null => {
|
|
24
|
+
if (typeof window === 'undefined') return null
|
|
25
|
+
return localStorage.getItem('accessToken')
|
|
58
26
|
}
|
|
59
27
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
export
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Add timeout to the API call
|
|
77
|
-
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
reject(new TimeoutError(timeout))
|
|
80
|
-
}, timeout)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
const result = await Promise.race([apiPromise, timeoutPromise])
|
|
85
|
-
const { data, error } = result
|
|
86
|
-
|
|
87
|
-
if (error) {
|
|
88
|
-
const correlationId = error.value?.correlationId
|
|
89
|
-
|
|
90
|
-
throw new ClientAPIError(
|
|
91
|
-
error.value?.message || 'API Error',
|
|
92
|
-
error.value?.code || 'API_ERROR',
|
|
93
|
-
error.status,
|
|
94
|
-
error.value?.details || error.value,
|
|
95
|
-
correlationId,
|
|
96
|
-
error.value?.userMessage
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return data
|
|
101
|
-
} catch (error) {
|
|
102
|
-
// Handle different types of errors
|
|
103
|
-
if (error instanceof ClientAPIError || error instanceof TimeoutError) {
|
|
104
|
-
throw error
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (error instanceof Error) {
|
|
108
|
-
// Check if it's a network error
|
|
109
|
-
if (error.message.includes('fetch') || error.message.includes('network')) {
|
|
110
|
-
throw new NetworkError(error.message)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
throw new ClientAPIError(
|
|
114
|
-
error.message,
|
|
115
|
-
'NETWORK_ERROR',
|
|
116
|
-
0,
|
|
117
|
-
undefined,
|
|
118
|
-
undefined,
|
|
119
|
-
'Unable to connect to the server. Please check your connection.'
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
throw new ClientAPIError(
|
|
124
|
-
'Unknown error occurred',
|
|
125
|
-
'UNKNOWN_ERROR',
|
|
126
|
-
500,
|
|
127
|
-
error
|
|
128
|
-
)
|
|
28
|
+
/**
|
|
29
|
+
* Create Eden Treaty client with authentication and logging
|
|
30
|
+
* Based on official ElysiaJS Chan example
|
|
31
|
+
*/
|
|
32
|
+
export const api = treaty<App>(getBaseUrl(), {
|
|
33
|
+
// Dynamic headers for every request
|
|
34
|
+
headers(_path, _options) {
|
|
35
|
+
const token = getAuthToken()
|
|
36
|
+
return token ? { Authorization: `Bearer ${token}` } : undefined
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Custom fetcher with logging and error handling
|
|
40
|
+
// Use 'as any' to bypass Bun's strict fetch type (includes preconnect property)
|
|
41
|
+
fetcher: (async (url, init) => {
|
|
42
|
+
if (import.meta.env.DEV) {
|
|
43
|
+
console.log(`🌐 ${init?.method ?? 'GET'} ${url}`)
|
|
129
44
|
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Wrap with circuit breaker if enabled
|
|
133
|
-
const callWithCircuitBreaker = useCircuitBreaker
|
|
134
|
-
? () => apiCircuitBreaker.execute(executeCall)
|
|
135
|
-
: executeCall
|
|
136
|
-
|
|
137
|
-
// Apply retry logic if specified
|
|
138
|
-
const callWithRetry = retry
|
|
139
|
-
? () => withRetry(callWithCircuitBreaker, retry)
|
|
140
|
-
: callWithCircuitBreaker
|
|
141
|
-
|
|
142
|
-
// Apply fallback if specified
|
|
143
|
-
if (fallback) {
|
|
144
|
-
return withFallback(callWithRetry, fallback)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return callWithRetry()
|
|
148
|
-
}
|
|
149
45
|
|
|
150
|
-
|
|
151
|
-
export async function simpleApiCall(apiPromise: Promise<any>) {
|
|
152
|
-
return apiCall(apiPromise)
|
|
153
|
-
}
|
|
46
|
+
const res = await fetch(url, init)
|
|
154
47
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
retry: {
|
|
159
|
-
maxRetries: 5,
|
|
160
|
-
baseDelay: 2000,
|
|
161
|
-
maxDelay: 30000
|
|
162
|
-
},
|
|
163
|
-
timeout: 60000,
|
|
164
|
-
useCircuitBreaker: true
|
|
165
|
-
})
|
|
166
|
-
}
|
|
48
|
+
if (import.meta.env.DEV) {
|
|
49
|
+
console.log(`📡 ${url} → ${res.status}`)
|
|
50
|
+
}
|
|
167
51
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
maxRetries: 2,
|
|
175
|
-
baseDelay: 1000
|
|
176
|
-
},
|
|
177
|
-
fallback: {
|
|
178
|
-
fallbackValue,
|
|
179
|
-
showFallbackMessage: false
|
|
180
|
-
},
|
|
181
|
-
timeout: 15000,
|
|
182
|
-
useCircuitBreaker: false
|
|
183
|
-
})
|
|
184
|
-
}
|
|
52
|
+
// Auto-logout on 401
|
|
53
|
+
if (res.status === 401) {
|
|
54
|
+
console.warn('🔒 Token expired')
|
|
55
|
+
localStorage.removeItem('accessToken')
|
|
56
|
+
// window.location.href = '/login' // Uncomment if you have auth
|
|
57
|
+
}
|
|
185
58
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
maxRetries: 3,
|
|
190
|
-
baseDelay: 1000,
|
|
191
|
-
retryableStatusCodes: [408, 429, 500, 502, 503, 504]
|
|
192
|
-
},
|
|
193
|
-
timeout: 30000,
|
|
194
|
-
useCircuitBreaker: true
|
|
195
|
-
})
|
|
196
|
-
}
|
|
59
|
+
return res
|
|
60
|
+
}) as typeof fetch
|
|
61
|
+
}).api // ← expose the generated API object
|
|
197
62
|
|
|
198
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Get user-friendly error message
|
|
65
|
+
*/
|
|
199
66
|
export function getErrorMessage(error: unknown): string {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (error instanceof APIException) {
|
|
205
|
-
return getDefaultUserMessage(error.code || 'UNKNOWN_ERROR', error.status)
|
|
67
|
+
// Eden Treaty error format
|
|
68
|
+
if (error && typeof error === 'object' && 'value' in error) {
|
|
69
|
+
const edenError = error as { value?: { message?: string; userMessage?: string } }
|
|
70
|
+
return edenError.value?.userMessage || edenError.value?.message || 'An error occurred'
|
|
206
71
|
}
|
|
207
|
-
|
|
72
|
+
|
|
73
|
+
// Standard Error
|
|
208
74
|
if (error instanceof Error) {
|
|
209
75
|
return error.message
|
|
210
76
|
}
|
|
211
|
-
|
|
212
|
-
return 'An unexpected error occurred'
|
|
213
|
-
}
|
|
214
77
|
|
|
215
|
-
|
|
216
|
-
export function isRetryableError(error: unknown): boolean {
|
|
217
|
-
if (error instanceof ClientAPIError) {
|
|
218
|
-
return error.isRetryable
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (error instanceof APIException) {
|
|
222
|
-
const retryableStatusCodes = [408, 429, 500, 502, 503, 504]
|
|
223
|
-
return retryableStatusCodes.includes(error.status)
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return false
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export function shouldShowErrorToUser(error: unknown): boolean {
|
|
230
|
-
if (error instanceof ClientAPIError) {
|
|
231
|
-
// Don't show technical errors to users
|
|
232
|
-
const technicalCodes = ['DATABASE_ERROR', 'EXTERNAL_SERVICE_ERROR', 'INTERNAL_SERVER_ERROR']
|
|
233
|
-
return !technicalCodes.includes(error.code)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return true
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Circuit breaker utilities
|
|
240
|
-
export function getCircuitBreakerState(): string {
|
|
241
|
-
return apiCircuitBreaker.getState()
|
|
78
|
+
return 'An unexpected error occurred'
|
|
242
79
|
}
|
|
243
|
-
|
|
244
|
-
export function resetCircuitBreaker(): void {
|
|
245
|
-
apiCircuitBreaker.reset()
|
|
246
|
-
}
|
package/app/client/src/main.tsx
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { StrictMode } from 'react'
|
|
2
2
|
import { createRoot } from 'react-dom/client'
|
|
3
|
-
import { BrowserRouter } from 'react-router-dom'
|
|
4
3
|
import './index.css'
|
|
5
4
|
import App from './App.tsx'
|
|
6
5
|
|
|
7
6
|
createRoot(document.getElementById('root')!).render(
|
|
8
|
-
<
|
|
7
|
+
<StrictMode>
|
|
9
8
|
<App />
|
|
10
|
-
</
|
|
9
|
+
</StrictMode>,
|
|
11
10
|
)
|
|
@@ -1,37 +1,56 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CreateUserRequest } from '@/app/shared/types'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
// User type
|
|
4
|
+
export interface User {
|
|
5
|
+
id: number
|
|
6
|
+
name: string
|
|
7
|
+
email: string
|
|
8
|
+
createdAt: Date
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// In-memory storage for users (for testing purposes)
|
|
12
|
+
let users: User[] = []
|
|
13
|
+
let nextId = 1
|
|
7
14
|
|
|
8
15
|
export class UsersController {
|
|
16
|
+
/**
|
|
17
|
+
* Get all users
|
|
18
|
+
*/
|
|
9
19
|
static async getUsers() {
|
|
10
|
-
return {
|
|
20
|
+
return {
|
|
21
|
+
users
|
|
22
|
+
}
|
|
11
23
|
}
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
25
|
+
/**
|
|
26
|
+
* Get user by ID
|
|
27
|
+
*/
|
|
28
|
+
static async getUserById(id: number) {
|
|
29
|
+
const user = users.find(u => u.id === id)
|
|
30
|
+
if (!user) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
return { user }
|
|
19
34
|
}
|
|
20
35
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Create a new user
|
|
38
|
+
*/
|
|
39
|
+
static async createUser(data: CreateUserRequest) {
|
|
40
|
+
// Check for duplicate email
|
|
41
|
+
const existingUser = users.find(u => u.email === data.email)
|
|
24
42
|
if (existingUser) {
|
|
25
43
|
return {
|
|
26
44
|
success: false,
|
|
27
|
-
message:
|
|
45
|
+
message: 'Email já está em uso'
|
|
28
46
|
}
|
|
29
47
|
}
|
|
30
48
|
|
|
49
|
+
// Create new user
|
|
31
50
|
const newUser: User = {
|
|
32
|
-
id:
|
|
33
|
-
name:
|
|
34
|
-
email:
|
|
51
|
+
id: nextId++,
|
|
52
|
+
name: data.name,
|
|
53
|
+
email: data.email,
|
|
35
54
|
createdAt: new Date()
|
|
36
55
|
}
|
|
37
56
|
|
|
@@ -43,27 +62,34 @@ export class UsersController {
|
|
|
43
62
|
}
|
|
44
63
|
}
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
static async deleteUser(id: number): Promise<UserResponse> {
|
|
65
|
+
/**
|
|
66
|
+
* Delete user by ID
|
|
67
|
+
*/
|
|
68
|
+
static async deleteUser(id: number) {
|
|
52
69
|
const userIndex = users.findIndex(u => u.id === id)
|
|
53
|
-
|
|
70
|
+
|
|
54
71
|
if (userIndex === -1) {
|
|
55
72
|
return {
|
|
56
73
|
success: false,
|
|
57
|
-
message:
|
|
74
|
+
message: 'Usuário não encontrado'
|
|
58
75
|
}
|
|
59
76
|
}
|
|
60
77
|
|
|
61
|
-
const deletedUser = users
|
|
62
|
-
|
|
78
|
+
const deletedUser = users[userIndex]
|
|
79
|
+
users.splice(userIndex, 1)
|
|
80
|
+
|
|
63
81
|
return {
|
|
64
82
|
success: true,
|
|
65
83
|
user: deletedUser,
|
|
66
|
-
message:
|
|
84
|
+
message: 'Usuário deletado com sucesso'
|
|
67
85
|
}
|
|
68
86
|
}
|
|
69
|
-
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Reset users array for testing purposes
|
|
90
|
+
*/
|
|
91
|
+
static resetForTesting() {
|
|
92
|
+
users = []
|
|
93
|
+
nextId = 1
|
|
94
|
+
}
|
|
95
|
+
}
|
package/app/server/index.ts
CHANGED
|
@@ -26,8 +26,11 @@ import cryptoAuthPlugin from "@/plugins/crypto-auth"
|
|
|
26
26
|
// ===== Application Routes =====
|
|
27
27
|
import { appInstance } from "./app"
|
|
28
28
|
|
|
29
|
-
//
|
|
30
|
-
//
|
|
29
|
+
// ===== Live Components Registration =====
|
|
30
|
+
// Import auto-generated component registrations from core/ (for production build)
|
|
31
|
+
// The generator creates this file in core/ to prevent accidental user modifications
|
|
32
|
+
// This ensures components are registered before the plugin tries to use them
|
|
33
|
+
import "@/core/server/live/auto-generated-components"
|
|
31
34
|
|
|
32
35
|
// ===== Startup Logging =====
|
|
33
36
|
DEBUG('🔧 Loading declarative configuration...')
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
//
|
|
2
|
-
// This file
|
|
3
|
-
//
|
|
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
|
|
4
17
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// Removed startup log to keep output clean - auto-generation handles everything
|
|
18
|
+
// This file intentionally left empty - do not import
|
|
19
|
+
export {}
|
|
@@ -3,18 +3,62 @@
|
|
|
3
3
|
* Displays current configuration for debugging purposes
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Elysia } from 'elysia'
|
|
6
|
+
import { Elysia, t } from 'elysia'
|
|
7
7
|
import { appConfig } from '@/config/app.config'
|
|
8
8
|
import { serverConfig } from '@/config/server.config'
|
|
9
9
|
import { loggerConfig } from '@/config/logger.config'
|
|
10
10
|
import { appRuntimeConfig } from '@/config/runtime.config'
|
|
11
11
|
import { helpers } from '@/core/utils/env'
|
|
12
12
|
|
|
13
|
+
// Response schema for environment test
|
|
14
|
+
const EnvTestResponseSchema = t.Object({
|
|
15
|
+
message: t.String(),
|
|
16
|
+
timestamp: t.String(),
|
|
17
|
+
serverConfig: t.Object({
|
|
18
|
+
port: t.Number(),
|
|
19
|
+
host: t.String(),
|
|
20
|
+
apiPrefix: t.String(),
|
|
21
|
+
appName: t.String(),
|
|
22
|
+
appVersion: t.String(),
|
|
23
|
+
cors: t.Object({
|
|
24
|
+
origins: t.Array(t.String()),
|
|
25
|
+
methods: t.Array(t.String()),
|
|
26
|
+
credentials: t.Boolean()
|
|
27
|
+
}),
|
|
28
|
+
client: t.Object({
|
|
29
|
+
port: t.Number(),
|
|
30
|
+
target: t.String(),
|
|
31
|
+
sourceMaps: t.Boolean()
|
|
32
|
+
}),
|
|
33
|
+
features: t.Object({
|
|
34
|
+
enableSwagger: t.Boolean(),
|
|
35
|
+
enableMetrics: t.Boolean(),
|
|
36
|
+
enableMonitoring: t.Boolean()
|
|
37
|
+
})
|
|
38
|
+
}),
|
|
39
|
+
environment: t.Object({
|
|
40
|
+
NODE_ENV: t.String(),
|
|
41
|
+
DEBUG: t.Boolean(),
|
|
42
|
+
LOG_LEVEL: t.String()
|
|
43
|
+
}),
|
|
44
|
+
urls: t.Object({
|
|
45
|
+
server: t.String(),
|
|
46
|
+
client: t.String(),
|
|
47
|
+
swagger: t.String()
|
|
48
|
+
}),
|
|
49
|
+
system: t.Object({
|
|
50
|
+
version: t.String(),
|
|
51
|
+
features: t.Array(t.String())
|
|
52
|
+
})
|
|
53
|
+
}, {
|
|
54
|
+
description: 'Environment and configuration information for debugging'
|
|
55
|
+
})
|
|
56
|
+
|
|
13
57
|
/**
|
|
14
58
|
* Environment test endpoint
|
|
15
59
|
* Shows declarative config system information
|
|
16
60
|
*/
|
|
17
|
-
export const envTestRoute = new Elysia({ prefix: '/api' })
|
|
61
|
+
export const envTestRoute = new Elysia({ prefix: '/api', tags: ['Development'] })
|
|
18
62
|
.get('/env-test', () => {
|
|
19
63
|
return {
|
|
20
64
|
message: '⚡ Declarative Config System!',
|
|
@@ -56,4 +100,11 @@ export const envTestRoute = new Elysia({ prefix: '/api' })
|
|
|
56
100
|
features: ['type-safe', 'validated', 'declarative', 'runtime-reload']
|
|
57
101
|
}
|
|
58
102
|
}
|
|
103
|
+
}, {
|
|
104
|
+
detail: {
|
|
105
|
+
summary: 'Environment Configuration Test',
|
|
106
|
+
description: 'Returns current environment configuration, server settings, and runtime features for debugging and validation',
|
|
107
|
+
tags: ['Development', 'Configuration', 'Debug']
|
|
108
|
+
},
|
|
109
|
+
response: EnvTestResponseSchema
|
|
59
110
|
})
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { Elysia, t } from "elysia"
|
|
2
2
|
import { usersRoutes } from "./users.routes"
|
|
3
|
-
import { uploadRoutes } from "./upload"
|
|
4
|
-
import { configRoutes } from "./config"
|
|
5
|
-
import { cryptoAuthDemoRoutes } from "./crypto-auth-demo.routes"
|
|
6
|
-
import { exemploPostsRoutes } from "./exemplo-posts.routes"
|
|
7
3
|
|
|
8
4
|
export const apiRoutes = new Elysia({ prefix: "/api" })
|
|
9
5
|
.get("/", () => ({ message: "🔥 Hot Reload funcionando! FluxStack API v1.4.0 ⚡" }), {
|
|
@@ -36,8 +32,5 @@ export const apiRoutes = new Elysia({ prefix: "/api" })
|
|
|
36
32
|
description: 'Returns the current health status of the API server'
|
|
37
33
|
}
|
|
38
34
|
})
|
|
35
|
+
// Register users routes
|
|
39
36
|
.use(usersRoutes)
|
|
40
|
-
.use(uploadRoutes)
|
|
41
|
-
.use(configRoutes)
|
|
42
|
-
.use(cryptoAuthDemoRoutes)
|
|
43
|
-
.use(exemploPostsRoutes) // ✅ Exemplo de rotas com crypto-auth
|