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.
Files changed (154) hide show
  1. package/.dockerignore +82 -0
  2. package/.env.example +19 -0
  3. package/Dockerfile +70 -0
  4. package/README.md +6 -3
  5. package/app/client/SIMPLIFICATION.md +140 -0
  6. package/app/client/frontend-only.ts +1 -1
  7. package/app/client/src/App.tsx +148 -283
  8. package/app/client/src/index.css +5 -20
  9. package/app/client/src/lib/eden-api.ts +53 -220
  10. package/app/client/src/main.tsx +2 -3
  11. package/app/server/app.ts +20 -5
  12. package/app/server/backend-only.ts +15 -12
  13. package/app/server/controllers/users.controller.ts +57 -31
  14. package/app/server/index.ts +86 -96
  15. package/app/server/live/register-components.ts +18 -7
  16. package/app/server/routes/env-test.ts +110 -0
  17. package/app/server/routes/index.ts +1 -8
  18. package/app/server/routes/users.routes.ts +192 -91
  19. package/config/app.config.ts +2 -54
  20. package/config/client.config.ts +95 -0
  21. package/config/fluxstack.config.ts +2 -2
  22. package/config/index.ts +57 -22
  23. package/config/monitoring.config.ts +114 -0
  24. package/config/plugins.config.ts +80 -0
  25. package/config/runtime.config.ts +0 -17
  26. package/config/server.config.ts +50 -30
  27. package/core/build/bundler.ts +17 -16
  28. package/core/build/flux-plugins-generator.ts +34 -23
  29. package/core/build/index.ts +32 -31
  30. package/core/build/live-components-generator.ts +44 -30
  31. package/core/build/optimizer.ts +37 -17
  32. package/core/cli/command-registry.ts +4 -14
  33. package/core/cli/commands/plugin-deps.ts +8 -8
  34. package/core/cli/generators/component.ts +3 -3
  35. package/core/cli/generators/controller.ts +4 -4
  36. package/core/cli/generators/index.ts +8 -8
  37. package/core/cli/generators/interactive.ts +4 -4
  38. package/core/cli/generators/plugin.ts +3 -3
  39. package/core/cli/generators/prompts.ts +1 -1
  40. package/core/cli/generators/route.ts +27 -11
  41. package/core/cli/generators/service.ts +5 -5
  42. package/core/cli/generators/template-engine.ts +1 -1
  43. package/core/cli/generators/types.ts +1 -1
  44. package/core/cli/index.ts +158 -189
  45. package/core/cli/plugin-discovery.ts +3 -3
  46. package/core/client/hooks/index.ts +2 -2
  47. package/core/client/hooks/state-validator.ts +1 -1
  48. package/core/client/hooks/useAuth.ts +1 -1
  49. package/core/client/hooks/useChunkedUpload.ts +1 -1
  50. package/core/client/hooks/useHybridLiveComponent.ts +1 -1
  51. package/core/client/hooks/useWebSocket.ts +1 -1
  52. package/core/config/env.ts +5 -1
  53. package/core/config/runtime-config.ts +12 -10
  54. package/core/config/schema.ts +33 -2
  55. package/core/framework/server.ts +30 -14
  56. package/core/framework/types.ts +2 -2
  57. package/core/index.ts +31 -23
  58. package/core/live/ComponentRegistry.ts +1 -1
  59. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
  60. package/core/plugins/built-in/live-components/index.ts +1 -1
  61. package/core/plugins/built-in/monitoring/index.ts +65 -161
  62. package/core/plugins/built-in/static/index.ts +75 -277
  63. package/core/plugins/built-in/swagger/index.ts +301 -231
  64. package/core/plugins/built-in/vite/index.ts +342 -377
  65. package/core/plugins/config.ts +2 -2
  66. package/core/plugins/dependency-manager.ts +2 -2
  67. package/core/plugins/discovery.ts +1 -1
  68. package/core/plugins/executor.ts +2 -2
  69. package/core/plugins/manager.ts +19 -4
  70. package/core/plugins/module-resolver.ts +1 -1
  71. package/core/plugins/registry.ts +25 -21
  72. package/core/plugins/types.ts +147 -5
  73. package/core/server/backend-entry.ts +51 -0
  74. package/core/server/framework.ts +2 -2
  75. package/core/server/live/ComponentRegistry.ts +9 -26
  76. package/core/server/live/FileUploadManager.ts +1 -1
  77. package/core/server/live/auto-generated-components.ts +26 -0
  78. package/core/server/live/websocket-plugin.ts +211 -19
  79. package/core/server/middleware/errorHandling.ts +1 -1
  80. package/core/server/middleware/index.ts +4 -4
  81. package/core/server/plugins/database.ts +1 -2
  82. package/core/server/plugins/static-files-plugin.ts +259 -231
  83. package/core/server/plugins/swagger.ts +1 -1
  84. package/core/server/services/BaseService.ts +1 -1
  85. package/core/server/services/ServiceContainer.ts +1 -1
  86. package/core/server/services/index.ts +4 -4
  87. package/core/server/standalone.ts +16 -1
  88. package/core/testing/index.ts +1 -1
  89. package/core/testing/setup.ts +1 -1
  90. package/core/types/plugin.ts +6 -0
  91. package/core/utils/build-logger.ts +324 -0
  92. package/core/utils/config-schema.ts +2 -6
  93. package/core/utils/helpers.ts +14 -9
  94. package/core/utils/logger/startup-banner.ts +7 -33
  95. package/core/utils/regenerate-files.ts +69 -0
  96. package/core/utils/version.ts +6 -6
  97. package/create-fluxstack.ts +68 -25
  98. package/fluxstack.config.ts +138 -252
  99. package/package.json +3 -18
  100. package/plugins/crypto-auth/index.ts +52 -47
  101. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  102. package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
  103. package/vitest.config.ts +17 -26
  104. package/app/client/src/App.css +0 -883
  105. package/app/client/src/components/ErrorBoundary.tsx +0 -107
  106. package/app/client/src/components/ErrorDisplay.css +0 -365
  107. package/app/client/src/components/ErrorDisplay.tsx +0 -258
  108. package/app/client/src/components/FluxStackConfig.tsx +0 -1321
  109. package/app/client/src/components/HybridLiveCounter.tsx +0 -140
  110. package/app/client/src/components/LiveClock.tsx +0 -286
  111. package/app/client/src/components/MainLayout.tsx +0 -388
  112. package/app/client/src/components/SidebarNavigation.tsx +0 -391
  113. package/app/client/src/components/StateDemo.tsx +0 -178
  114. package/app/client/src/components/SystemMonitor.tsx +0 -1044
  115. package/app/client/src/components/UserProfile.tsx +0 -809
  116. package/app/client/src/hooks/useAuth.ts +0 -39
  117. package/app/client/src/hooks/useNotifications.ts +0 -56
  118. package/app/client/src/lib/errors.ts +0 -340
  119. package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
  120. package/app/client/src/lib/index.ts +0 -45
  121. package/app/client/src/pages/ApiDocs.tsx +0 -182
  122. package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
  123. package/app/client/src/pages/Demo.tsx +0 -174
  124. package/app/client/src/pages/HybridLive.tsx +0 -263
  125. package/app/client/src/pages/Overview.tsx +0 -155
  126. package/app/client/src/store/README.md +0 -43
  127. package/app/client/src/store/index.ts +0 -16
  128. package/app/client/src/store/slices/uiSlice.ts +0 -151
  129. package/app/client/src/store/slices/userSlice.ts +0 -161
  130. package/app/client/src/test/README.md +0 -257
  131. package/app/client/src/test/setup.ts +0 -70
  132. package/app/client/src/test/types.ts +0 -12
  133. package/app/server/live/CounterComponent.ts +0 -191
  134. package/app/server/live/FluxStackConfig.ts +0 -534
  135. package/app/server/live/SidebarNavigation.ts +0 -157
  136. package/app/server/live/SystemMonitor.ts +0 -595
  137. package/app/server/live/SystemMonitorIntegration.ts +0 -151
  138. package/app/server/live/UserProfileComponent.ts +0 -141
  139. package/app/server/middleware/auth.ts +0 -136
  140. package/app/server/middleware/errorHandling.ts +0 -252
  141. package/app/server/middleware/index.ts +0 -10
  142. package/app/server/middleware/rateLimit.ts +0 -193
  143. package/app/server/middleware/requestLogging.ts +0 -215
  144. package/app/server/middleware/validation.ts +0 -270
  145. package/app/server/routes/config.ts +0 -145
  146. package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
  147. package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
  148. package/app/server/routes/exemplo-posts.routes.ts +0 -161
  149. package/app/server/routes/upload.ts +0 -92
  150. package/app/server/services/NotificationService.ts +0 -302
  151. package/app/server/services/UserService.ts +0 -222
  152. package/app/server/services/index.ts +0 -46
  153. package/app/server/types/index.ts +0 -1
  154. package/config/build.config.ts +0 -24
@@ -2,245 +2,78 @@
2
2
  import { treaty } from '@elysiajs/eden'
3
3
  import type { App } from '../../../server/app'
4
4
 
5
- // Get base URL dynamically
6
- const getBaseUrl = () => {
5
+ /**
6
+ * Get base URL dynamically
7
+ */
8
+ export const getBaseUrl = () => {
7
9
  if (typeof window === 'undefined') return 'http://localhost:3000'
8
-
9
- // In production, use current origin
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
- // Enhanced error handling with retry and recovery strategies
25
- import {
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
- // Legacy class for backward compatibility
46
- export class APIException extends Error {
47
- status: number
48
- code?: string
49
- details?: any
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
- // Global circuit breaker for API calls
61
- const apiCircuitBreaker = new CircuitBreaker(5, 60000, 60000)
62
-
63
- // Enhanced API call wrapper with retry and recovery
64
- export async function apiCall<T>(
65
- apiPromise: Promise<any>,
66
- options: {
67
- retry?: Partial<RetryOptions>
68
- fallback?: FallbackOptions<T>
69
- timeout?: number
70
- useCircuitBreaker?: boolean
71
- } = {}
72
- ): Promise<T> {
73
- const { retry, fallback, timeout = 30000, useCircuitBreaker = true } = options
74
-
75
- const executeCall = async (): Promise<T> => {
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
- // Simplified API call for basic usage (backward compatibility)
151
- export async function simpleApiCall(apiPromise: Promise<any>) {
152
- return apiCall(apiPromise)
153
- }
46
+ const res = await fetch(url, init)
154
47
 
155
- // Specialized API calls for different scenarios
156
- export async function criticalApiCall<T>(apiPromise: Promise<any>): Promise<T> {
157
- return apiCall(apiPromise, {
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
- export async function backgroundApiCall<T>(
169
- apiPromise: Promise<any>,
170
- fallbackValue: T
171
- ): Promise<T> {
172
- return apiCall(apiPromise, {
173
- retry: {
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
- export async function userActionApiCall<T>(apiPromise: Promise<any>): Promise<T> {
187
- return apiCall(apiPromise, {
188
- retry: {
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
- // User-friendly error messages (enhanced)
63
+ /**
64
+ * Get user-friendly error message
65
+ */
199
66
  export function getErrorMessage(error: unknown): string {
200
- if (error instanceof ClientAPIError) {
201
- return error.getUserFriendlyMessage()
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
- // Error recovery utilities
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
- }
@@ -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
- <BrowserRouter>
7
+ <StrictMode>
9
8
  <App />
10
- </BrowserRouter>,
9
+ </StrictMode>,
11
10
  )
package/app/server/app.ts CHANGED
@@ -1,10 +1,25 @@
1
- // Export the main app type for Eden Treaty
2
- import { apiRoutes } from "./routes"
1
+ /**
2
+ * 🎯 Application Instance - Single Source of Truth
3
+ *
4
+ * This instance is used by:
5
+ * - index.ts (full-stack mode)
6
+ * - backend-only.ts (backend standalone mode)
7
+ * - Eden Treaty client (type inference)
8
+ *
9
+ * This ensures that the type exported for Eden Treaty is exactly
10
+ * the same as what the server uses.
11
+ */
12
+
3
13
  import { Elysia } from "elysia"
14
+ import { apiRoutes } from "./routes"
15
+ import { envTestRoute } from "./routes/env-test"
4
16
 
5
- // Create the full app structure that matches the server
6
- const appInstance = new Elysia()
7
- .use(apiRoutes)
17
+ /**
18
+ * Main application instance with all routes registered
19
+ */
20
+ export const appInstance = new Elysia()
21
+ .use(envTestRoute) // Environment test/debug endpoint
22
+ .use(apiRoutes) // Main application routes
8
23
 
9
24
  // Export the type correctly for Eden Treaty
10
25
  export type App = typeof appInstance
@@ -1,15 +1,18 @@
1
- // Backend standalone entry point
2
- import { startBackendOnly } from "@/core/server/standalone"
3
- import { apiRoutes } from "./routes"
4
- import { serverConfig } from "@/config/server.config"
1
+ /**
2
+ * Backend Standalone Entry Point
3
+ *
4
+ * This is a minimal wrapper for starting the backend in standalone mode.
5
+ * The core logic is protected in @/core/server/backend-entry.ts
6
+ *
7
+ * You can customize the configuration here if needed.
8
+ */
5
9
 
6
- // Configuração para backend standalone usando config declarativo
7
- const backendConfig = {
8
- port: serverConfig.backendPort,
9
- apiPrefix: serverConfig.apiPrefix
10
- }
10
+ import { startBackend, createBackendConfig } from "@/core/server/backend-entry"
11
+ import { appInstance } from "./app"
12
+ import { serverConfig } from "@/config/server.config"
11
13
 
12
- console.log(`🚀 Backend standalone: ${serverConfig.host}:${backendConfig.port}`)
14
+ // Create backend configuration from declarative config
15
+ const backendConfig = createBackendConfig(serverConfig)
13
16
 
14
- // Iniciar apenas o backend
15
- startBackendOnly(apiRoutes, backendConfig)
17
+ // Start backend in standalone mode
18
+ startBackend(appInstance, backendConfig)
@@ -1,37 +1,56 @@
1
- import type { User, CreateUserRequest, UserResponse } from '../types'
1
+ import type { CreateUserRequest } from '@/app/shared/types'
2
2
 
3
- let users: User[] = [
4
- { id: 1, name: "João", email: "joao@example.com", createdAt: new Date() },
5
- { id: 2, name: "Maria", email: "maria@example.com", createdAt: new Date() }
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 { users }
20
+ return {
21
+ users
22
+ }
11
23
  }
12
24
 
13
- static resetForTesting() {
14
- users.splice(0, users.length)
15
- users.push(
16
- { id: 1, name: "João", email: "joao@example.com", createdAt: new Date() },
17
- { id: 2, name: "Maria", email: "maria@example.com", createdAt: new Date() }
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
- static async createUser(userData: CreateUserRequest): Promise<UserResponse> {
22
- const existingUser = users.find(u => u.email === userData.email)
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: "Email já está em uso"
45
+ message: 'Email já está em uso'
28
46
  }
29
47
  }
30
48
 
49
+ // Create new user
31
50
  const newUser: User = {
32
- id: Date.now(),
33
- name: userData.name,
34
- email: userData.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
- static async getUserById(id: number) {
47
- const user = users.find(u => u.id === id)
48
- return user ? { user } : null
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: "Usuário não encontrado"
74
+ message: 'Usuário não encontrado'
58
75
  }
59
76
  }
60
77
 
61
- const deletedUser = users.splice(userIndex, 1)[0]
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: "Usuário deletado com sucesso"
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
+ }