create-fluxstack 1.0.13 → 1.0.15

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 (214) hide show
  1. package/.env.example +29 -29
  2. package/app/client/README.md +69 -69
  3. package/app/client/index.html +14 -13
  4. package/app/client/src/App.tsx +157 -524
  5. package/app/client/src/components/ErrorBoundary.tsx +107 -0
  6. package/app/client/src/components/ErrorDisplay.css +365 -0
  7. package/app/client/src/components/ErrorDisplay.tsx +258 -0
  8. package/app/client/src/components/FluxStackConfig.tsx +1321 -0
  9. package/app/client/src/components/HybridLiveCounter.tsx +140 -0
  10. package/app/client/src/components/LiveClock.tsx +286 -0
  11. package/app/client/src/components/MainLayout.tsx +390 -0
  12. package/app/client/src/components/SidebarNavigation.tsx +391 -0
  13. package/app/client/src/components/StateDemo.tsx +178 -0
  14. package/app/client/src/components/SystemMonitor.tsx +1038 -0
  15. package/app/client/src/components/Teste.tsx +104 -0
  16. package/app/client/src/components/UserProfile.tsx +809 -0
  17. package/app/client/src/hooks/useAuth.ts +39 -0
  18. package/app/client/src/hooks/useNotifications.ts +56 -0
  19. package/app/client/src/lib/eden-api.ts +189 -53
  20. package/app/client/src/lib/errors.ts +340 -0
  21. package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
  22. package/app/client/src/lib/index.ts +45 -0
  23. package/app/client/src/main.tsx +3 -2
  24. package/app/client/src/pages/ApiDocs.tsx +182 -0
  25. package/app/client/src/pages/Demo.tsx +174 -0
  26. package/app/client/src/pages/HybridLive.tsx +263 -0
  27. package/app/client/src/pages/Overview.tsx +155 -0
  28. package/app/client/src/store/README.md +43 -0
  29. package/app/client/src/store/index.ts +16 -0
  30. package/app/client/src/store/slices/uiSlice.ts +151 -0
  31. package/app/client/src/store/slices/userSlice.ts +161 -0
  32. package/app/client/src/test/README.md +257 -0
  33. package/app/client/src/test/setup.ts +70 -0
  34. package/app/client/src/test/types.ts +12 -0
  35. package/app/client/src/vite-env.d.ts +1 -1
  36. package/app/client/tsconfig.app.json +44 -43
  37. package/app/client/tsconfig.json +7 -7
  38. package/app/client/tsconfig.node.json +25 -25
  39. package/app/client/zustand-setup.md +65 -0
  40. package/app/server/controllers/users.controller.ts +68 -68
  41. package/app/server/index.ts +9 -1
  42. package/app/server/live/CounterComponent.ts +191 -0
  43. package/app/server/live/FluxStackConfig.ts +529 -0
  44. package/app/server/live/LiveClockComponent.ts +214 -0
  45. package/app/server/live/SidebarNavigation.ts +156 -0
  46. package/app/server/live/SystemMonitor.ts +594 -0
  47. package/app/server/live/SystemMonitorIntegration.ts +151 -0
  48. package/app/server/live/TesteComponent.ts +87 -0
  49. package/app/server/live/UserProfileComponent.ts +135 -0
  50. package/app/server/live/register-components.ts +28 -0
  51. package/app/server/middleware/auth.ts +136 -0
  52. package/app/server/middleware/errorHandling.ts +250 -0
  53. package/app/server/middleware/index.ts +10 -0
  54. package/app/server/middleware/rateLimit.ts +193 -0
  55. package/app/server/middleware/requestLogging.ts +215 -0
  56. package/app/server/middleware/validation.ts +270 -0
  57. package/app/server/routes/index.ts +14 -2
  58. package/app/server/routes/upload.ts +92 -0
  59. package/app/server/routes/users.routes.ts +2 -9
  60. package/app/server/services/NotificationService.ts +302 -0
  61. package/app/server/services/UserService.ts +222 -0
  62. package/app/server/services/index.ts +46 -0
  63. package/core/cli/commands/plugin-deps.ts +263 -0
  64. package/core/cli/generators/README.md +339 -0
  65. package/core/cli/generators/component.ts +770 -0
  66. package/core/cli/generators/controller.ts +299 -0
  67. package/core/cli/generators/index.ts +144 -0
  68. package/core/cli/generators/interactive.ts +228 -0
  69. package/core/cli/generators/prompts.ts +83 -0
  70. package/core/cli/generators/route.ts +513 -0
  71. package/core/cli/generators/service.ts +465 -0
  72. package/core/cli/generators/template-engine.ts +154 -0
  73. package/core/cli/generators/types.ts +71 -0
  74. package/core/cli/generators/utils.ts +192 -0
  75. package/core/cli/index.ts +69 -0
  76. package/core/cli/plugin-discovery.ts +16 -85
  77. package/core/client/fluxstack.ts +17 -0
  78. package/core/client/hooks/index.ts +7 -0
  79. package/core/client/hooks/state-validator.ts +130 -0
  80. package/core/client/hooks/useAuth.ts +49 -0
  81. package/core/client/hooks/useChunkedUpload.ts +258 -0
  82. package/core/client/hooks/useHybridLiveComponent.ts +967 -0
  83. package/core/client/hooks/useWebSocket.ts +373 -0
  84. package/core/client/index.ts +47 -0
  85. package/core/client/state/createStore.ts +193 -0
  86. package/core/client/state/index.ts +15 -0
  87. package/core/config/env-dynamic.ts +1 -1
  88. package/core/config/env.ts +2 -1
  89. package/core/config/runtime-config.ts +3 -3
  90. package/core/config/schema.ts +84 -49
  91. package/core/framework/server.ts +30 -0
  92. package/core/index.ts +25 -0
  93. package/core/live/ComponentRegistry.ts +399 -0
  94. package/core/live/types.ts +164 -0
  95. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
  96. package/core/plugins/built-in/live-components/index.ts +27 -0
  97. package/core/plugins/built-in/logger/index.ts +1 -1
  98. package/core/plugins/built-in/monitoring/index.ts +1 -1
  99. package/core/plugins/built-in/static/index.ts +1 -1
  100. package/core/plugins/built-in/swagger/index.ts +1 -1
  101. package/core/plugins/built-in/vite/index.ts +1 -1
  102. package/core/plugins/dependency-manager.ts +384 -0
  103. package/core/plugins/index.ts +5 -1
  104. package/core/plugins/manager.ts +7 -3
  105. package/core/plugins/registry.ts +88 -10
  106. package/core/plugins/types.ts +11 -11
  107. package/core/server/framework.ts +43 -0
  108. package/core/server/index.ts +11 -1
  109. package/core/server/live/ComponentRegistry.ts +1017 -0
  110. package/core/server/live/FileUploadManager.ts +272 -0
  111. package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
  112. package/core/server/live/SingleConnectionManager.ts +0 -0
  113. package/core/server/live/StateSignature.ts +644 -0
  114. package/core/server/live/WebSocketConnectionManager.ts +688 -0
  115. package/core/server/live/websocket-plugin.ts +435 -0
  116. package/core/server/middleware/errorHandling.ts +141 -0
  117. package/core/server/middleware/index.ts +16 -0
  118. package/core/server/plugins/static-files-plugin.ts +232 -0
  119. package/core/server/services/BaseService.ts +95 -0
  120. package/core/server/services/ServiceContainer.ts +144 -0
  121. package/core/server/services/index.ts +9 -0
  122. package/core/templates/create-project.ts +196 -33
  123. package/core/testing/index.ts +10 -0
  124. package/core/testing/setup.ts +74 -0
  125. package/core/types/build.ts +38 -14
  126. package/core/types/types.ts +319 -0
  127. package/core/utils/env-runtime.ts +7 -0
  128. package/core/utils/errors/handlers.ts +264 -39
  129. package/core/utils/errors/index.ts +528 -18
  130. package/core/utils/errors/middleware.ts +114 -0
  131. package/core/utils/logger/formatters.ts +222 -0
  132. package/core/utils/logger/index.ts +167 -48
  133. package/core/utils/logger/middleware.ts +253 -0
  134. package/core/utils/logger/performance.ts +384 -0
  135. package/core/utils/logger/transports.ts +365 -0
  136. package/create-fluxstack.ts +296 -296
  137. package/fluxstack.config.ts +17 -1
  138. package/package-template.json +66 -66
  139. package/package.json +31 -6
  140. package/public/README.md +16 -0
  141. package/vite.config.ts +29 -14
  142. package/.claude/settings.local.json +0 -74
  143. package/.github/workflows/ci-build-tests.yml +0 -480
  144. package/.github/workflows/dependency-management.yml +0 -324
  145. package/.github/workflows/release-validation.yml +0 -355
  146. package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
  147. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
  148. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
  149. package/CLAUDE.md +0 -200
  150. package/Dockerfile +0 -58
  151. package/Dockerfile.backend +0 -52
  152. package/Dockerfile.frontend +0 -54
  153. package/README-Docker.md +0 -85
  154. package/ai-context/00-QUICK-START.md +0 -86
  155. package/ai-context/README.md +0 -88
  156. package/ai-context/development/eden-treaty-guide.md +0 -362
  157. package/ai-context/development/patterns.md +0 -382
  158. package/ai-context/development/plugins-guide.md +0 -572
  159. package/ai-context/examples/crud-complete.md +0 -626
  160. package/ai-context/project/architecture.md +0 -399
  161. package/ai-context/project/overview.md +0 -213
  162. package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
  163. package/ai-context/recent-changes/type-inference-fix.md +0 -223
  164. package/ai-context/reference/environment-vars.md +0 -384
  165. package/ai-context/reference/troubleshooting.md +0 -407
  166. package/app/client/src/components/TestPage.tsx +0 -453
  167. package/bun.lock +0 -1063
  168. package/bunfig.toml +0 -16
  169. package/core/__tests__/integration.test.ts +0 -227
  170. package/core/build/index.ts +0 -186
  171. package/core/config/__tests__/config-loader.test.ts +0 -554
  172. package/core/config/__tests__/config-merger.test.ts +0 -657
  173. package/core/config/__tests__/env-converter.test.ts +0 -372
  174. package/core/config/__tests__/env-processor.test.ts +0 -431
  175. package/core/config/__tests__/env.test.ts +0 -452
  176. package/core/config/__tests__/integration.test.ts +0 -418
  177. package/core/config/__tests__/loader.test.ts +0 -331
  178. package/core/config/__tests__/schema.test.ts +0 -129
  179. package/core/config/__tests__/validator.test.ts +0 -318
  180. package/core/framework/__tests__/server.test.ts +0 -233
  181. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  182. package/core/plugins/__tests__/manager.test.ts +0 -398
  183. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  184. package/core/plugins/__tests__/registry.test.ts +0 -335
  185. package/core/utils/__tests__/errors.test.ts +0 -139
  186. package/core/utils/__tests__/helpers.test.ts +0 -297
  187. package/core/utils/__tests__/logger.test.ts +0 -141
  188. package/create-test-app.ts +0 -156
  189. package/docker-compose.microservices.yml +0 -75
  190. package/docker-compose.simple.yml +0 -57
  191. package/docker-compose.yml +0 -71
  192. package/eslint.config.js +0 -23
  193. package/flux-cli.ts +0 -214
  194. package/nginx-lb.conf +0 -37
  195. package/publish.sh +0 -63
  196. package/run-clean.ts +0 -26
  197. package/run-env-tests.ts +0 -313
  198. package/tailwind.config.js +0 -34
  199. package/tests/__mocks__/api.ts +0 -56
  200. package/tests/fixtures/users.ts +0 -69
  201. package/tests/integration/api/users.routes.test.ts +0 -221
  202. package/tests/setup.ts +0 -29
  203. package/tests/unit/app/client/App-simple.test.tsx +0 -56
  204. package/tests/unit/app/client/App.test.tsx.skip +0 -237
  205. package/tests/unit/app/client/eden-api.test.ts +0 -186
  206. package/tests/unit/app/client/simple.test.tsx +0 -23
  207. package/tests/unit/app/controllers/users.controller.test.ts +0 -150
  208. package/tests/unit/core/create-project.test.ts.skip +0 -95
  209. package/tests/unit/core/framework.test.ts +0 -144
  210. package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
  211. package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
  212. package/tests/utils/test-helpers.ts +0 -61
  213. package/vitest.config.ts +0 -50
  214. package/workspace.json +0 -6
@@ -0,0 +1,258 @@
1
+ import React, { useState, useCallback, useRef } from 'react'
2
+ import { logClientError } from '../errors'
3
+ import { getErrorMessage, isRetryableError, shouldShowErrorToUser } from '../eden-api'
4
+
5
+ export interface ErrorState {
6
+ error: Error | null
7
+ isRetrying: boolean
8
+ retryCount: number
9
+ canRetry: boolean
10
+ userMessage: string | null
11
+ }
12
+
13
+ export interface UseErrorHandlerOptions {
14
+ maxRetries?: number
15
+ showUserFriendlyMessages?: boolean
16
+ logErrors?: boolean
17
+ onError?: (error: Error) => void
18
+ onRetry?: (retryCount: number) => void
19
+ onMaxRetriesReached?: (error: Error) => void
20
+ }
21
+
22
+ export function useErrorHandler(options: UseErrorHandlerOptions = {}) {
23
+ const {
24
+ maxRetries = 3,
25
+ showUserFriendlyMessages = true,
26
+ logErrors = true,
27
+ onError,
28
+ onRetry,
29
+ onMaxRetriesReached
30
+ } = options
31
+
32
+ const [errorState, setErrorState] = useState<ErrorState>({
33
+ error: null,
34
+ isRetrying: false,
35
+ retryCount: 0,
36
+ canRetry: false,
37
+ userMessage: null
38
+ })
39
+
40
+ const retryTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined)
41
+
42
+ const handleError = useCallback((error: Error) => {
43
+ if (logErrors) {
44
+ logClientError(error, undefined)
45
+ }
46
+
47
+ setErrorState(prevState => {
48
+ const currentRetryCount = prevState?.retryCount || 0
49
+ const canRetry = isRetryableError(error) && currentRetryCount < maxRetries
50
+ const userMessage = showUserFriendlyMessages && shouldShowErrorToUser(error)
51
+ ? getErrorMessage(error)
52
+ : null
53
+
54
+ return {
55
+ error,
56
+ isRetrying: false,
57
+ retryCount: currentRetryCount,
58
+ canRetry,
59
+ userMessage
60
+ }
61
+ })
62
+
63
+ onError?.(error)
64
+ }, [maxRetries, showUserFriendlyMessages, logErrors, onError])
65
+
66
+ const retry = useCallback(async (operation: () => Promise<any>) => {
67
+ if (!errorState.canRetry || errorState.isRetrying) {
68
+ return
69
+ }
70
+
71
+ const newRetryCount = (errorState?.retryCount || 0) + 1
72
+
73
+ setErrorState(prev => ({
74
+ ...prev,
75
+ isRetrying: true,
76
+ retryCount: newRetryCount
77
+ }))
78
+
79
+ onRetry?.(newRetryCount)
80
+
81
+ try {
82
+ // Add exponential backoff delay
83
+ const delay = Math.min(1000 * Math.pow(2, newRetryCount - 1), 10000)
84
+ await new Promise(resolve => {
85
+ retryTimeoutRef.current = setTimeout(resolve, delay)
86
+ })
87
+
88
+ const result = await operation()
89
+
90
+ // Clear error state on successful retry
91
+ setErrorState({
92
+ error: null,
93
+ isRetrying: false,
94
+ retryCount: 0,
95
+ canRetry: false,
96
+ userMessage: null
97
+ })
98
+
99
+ return result
100
+ } catch (error) {
101
+ const canRetryAgain = isRetryableError(error as Error) && newRetryCount < maxRetries
102
+
103
+ setErrorState(prev => ({
104
+ ...prev,
105
+ error: error as Error,
106
+ isRetrying: false,
107
+ retryCount: newRetryCount,
108
+ canRetry: canRetryAgain,
109
+ userMessage: showUserFriendlyMessages && shouldShowErrorToUser(error)
110
+ ? getErrorMessage(error)
111
+ : null
112
+ }))
113
+
114
+ if (!canRetryAgain) {
115
+ onMaxRetriesReached?.(error as Error)
116
+ }
117
+
118
+ throw error
119
+ }
120
+ }, [errorState?.retryCount, errorState?.canRetry, errorState?.isRetrying, maxRetries, showUserFriendlyMessages, onRetry, onMaxRetriesReached])
121
+
122
+ const clearError = useCallback(() => {
123
+ if (retryTimeoutRef.current) {
124
+ clearTimeout(retryTimeoutRef.current)
125
+ }
126
+
127
+ setErrorState({
128
+ error: null,
129
+ isRetrying: false,
130
+ retryCount: 0,
131
+ canRetry: false,
132
+ userMessage: null
133
+ })
134
+ }, [])
135
+
136
+ const executeWithErrorHandling = useCallback(async <T>(
137
+ operation: () => Promise<T>
138
+ ): Promise<T | null> => {
139
+ try {
140
+ clearError()
141
+ return await operation()
142
+ } catch (error) {
143
+ handleError(error as Error)
144
+ return null
145
+ }
146
+ }, [handleError, clearError])
147
+
148
+ return {
149
+ ...errorState,
150
+ handleError,
151
+ retry,
152
+ clearError,
153
+ executeWithErrorHandling
154
+ }
155
+ }
156
+
157
+ // Hook for handling API calls with automatic error handling
158
+ export function useApiCall<T>(
159
+ apiCall: () => Promise<T>,
160
+ options: UseErrorHandlerOptions & {
161
+ immediate?: boolean
162
+ dependencies?: any[]
163
+ } = {}
164
+ ) {
165
+ const { immediate = false, dependencies = [], ...errorOptions } = options
166
+
167
+ const [data, setData] = useState<T | null>(null)
168
+ const [loading, setLoading] = useState(immediate)
169
+
170
+ const errorHandler = useErrorHandler(errorOptions)
171
+
172
+ const execute = useCallback(async (): Promise<T | null> => {
173
+ setLoading(true)
174
+
175
+ try {
176
+ const result = await apiCall()
177
+ setData(result)
178
+ errorHandler.clearError()
179
+ return result
180
+ } catch (error) {
181
+ errorHandler.handleError(error as Error)
182
+ return null
183
+ } finally {
184
+ setLoading(false)
185
+ }
186
+ }, [apiCall, errorHandler])
187
+
188
+ const retryCall = useCallback(async () => {
189
+ return errorHandler.retry(async () => {
190
+ setLoading(true)
191
+ try {
192
+ const result = await apiCall()
193
+ setData(result)
194
+ return result
195
+ } finally {
196
+ setLoading(false)
197
+ }
198
+ })
199
+ }, [apiCall, errorHandler])
200
+
201
+ // Execute immediately if requested
202
+ React.useEffect(() => {
203
+ if (immediate) {
204
+ execute()
205
+ }
206
+ }, [immediate, ...dependencies])
207
+
208
+ const { retry: errorHandlerRetry, ...restErrorHandler } = errorHandler
209
+
210
+ return {
211
+ data,
212
+ loading,
213
+ execute,
214
+ retry: retryCall,
215
+ ...restErrorHandler
216
+ }
217
+ }
218
+
219
+ // Hook for form submission with error handling
220
+ export function useFormSubmission<T>(
221
+ submitFunction: (data: any) => Promise<T>,
222
+ options: UseErrorHandlerOptions = {}
223
+ ) {
224
+ const [isSubmitting, setIsSubmitting] = useState(false)
225
+ const [submitData, setSubmitData] = useState<T | null>(null)
226
+
227
+ const errorHandler = useErrorHandler(options)
228
+
229
+ const submit = useCallback(async (formData: any): Promise<T | null> => {
230
+ setIsSubmitting(true)
231
+
232
+ try {
233
+ const result = await submitFunction(formData)
234
+ setSubmitData(result)
235
+ errorHandler.clearError()
236
+ return result
237
+ } catch (error) {
238
+ errorHandler.handleError(error as Error)
239
+ return null
240
+ } finally {
241
+ setIsSubmitting(false)
242
+ }
243
+ }, [submitFunction, errorHandler])
244
+
245
+ const retrySubmit = useCallback(async (formData: any) => {
246
+ return errorHandler.retry(() => submit(formData))
247
+ }, [submit, errorHandler])
248
+
249
+ const { retry: errorHandlerRetry, ...restErrorHandler } = errorHandler
250
+
251
+ return {
252
+ submit,
253
+ retry: retrySubmit,
254
+ isSubmitting,
255
+ submitData,
256
+ ...restErrorHandler
257
+ }
258
+ }
@@ -0,0 +1,45 @@
1
+ // Enhanced error handling exports
2
+ export * from './errors'
3
+ export * from './eden-api'
4
+ export * from './hooks/useErrorHandler'
5
+
6
+ // Re-export components
7
+ export { ErrorBoundary, useErrorBoundary } from '../components/ErrorBoundary'
8
+ export {
9
+ ErrorDisplay,
10
+ ErrorToast,
11
+ InlineError,
12
+ LoadingWithError,
13
+ ErrorSummary
14
+ } from '../components/ErrorDisplay'
15
+
16
+ // Convenience exports for common patterns
17
+ export {
18
+ apiCall,
19
+ simpleApiCall,
20
+ criticalApiCall,
21
+ backgroundApiCall,
22
+ userActionApiCall,
23
+ getErrorMessage,
24
+ isRetryableError,
25
+ shouldShowErrorToUser,
26
+ getCircuitBreakerState,
27
+ resetCircuitBreaker
28
+ } from './eden-api'
29
+
30
+ export {
31
+ ClientAPIError,
32
+ NetworkError,
33
+ TimeoutError,
34
+ withRetry,
35
+ withFallback,
36
+ CircuitBreaker,
37
+ getDefaultUserMessage,
38
+ logClientError
39
+ } from './errors'
40
+
41
+ export {
42
+ useErrorHandler,
43
+ useApiCall,
44
+ useFormSubmission
45
+ } from './hooks/useErrorHandler'
@@ -1,10 +1,11 @@
1
1
  import { StrictMode } from 'react'
2
2
  import { createRoot } from 'react-dom/client'
3
+ import { BrowserRouter } from 'react-router-dom'
3
4
  import './index.css'
4
5
  import App from './App.tsx'
5
6
 
6
7
  createRoot(document.getElementById('root')!).render(
7
- <StrictMode>
8
+ <BrowserRouter>
8
9
  <App />
9
- </StrictMode>,
10
+ </BrowserRouter>,
10
11
  )
@@ -0,0 +1,182 @@
1
+ import {
2
+ FaBook, FaClipboardList, FaRocket, FaFileAlt, FaCog, FaLock, FaSync, FaCode, FaEye,
3
+ FaBolt
4
+ } from 'react-icons/fa';
5
+
6
+
7
+ export function ApiDocsPage() {
8
+ return (
9
+ <div className="space-y-8">
10
+ {/* Header */}
11
+ <div className="text-center">
12
+ <div className="flex items-center justify-center gap-3 mb-4">
13
+ <FaBook className="text-3xl text-blue-500" />
14
+ <h2 className="text-3xl font-bold text-gray-900">Documentação da API</h2>
15
+ </div>
16
+ <p className="text-lg text-gray-600 max-w-2xl mx-auto">
17
+ Documentação interativa gerada automaticamente com Swagger UI
18
+ </p>
19
+ </div>
20
+
21
+ {/* Quick Links */}
22
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
23
+ <div className="group bg-white rounded-2xl p-6 shadow-lg border border-gray-200 hover:shadow-xl hover:border-blue-300 transition-all duration-300">
24
+ <div className="text-center">
25
+ <div className="text-4xl mb-4">
26
+ <FaClipboardList className="text-blue-500 mx-auto" />
27
+ </div>
28
+ <h3 className="text-xl font-semibold text-gray-900 mb-2">Swagger UI Interativo</h3>
29
+ <p className="text-gray-600 mb-6">Interface completa para testar todos os endpoints da API</p>
30
+ <a
31
+ href="/swagger"
32
+ target="_blank"
33
+ rel="noopener noreferrer"
34
+ className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white font-medium rounded-xl hover:from-blue-700 hover:to-blue-800 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all duration-200 shadow-lg hover:shadow-xl"
35
+ >
36
+ <FaRocket className="w-4 h-4" />
37
+ Abrir em Nova Aba
38
+ </a>
39
+ </div>
40
+ </div>
41
+
42
+ <div className="group bg-white rounded-2xl p-6 shadow-lg border border-gray-200 hover:shadow-xl hover:border-purple-300 transition-all duration-300">
43
+ <div className="text-center">
44
+ <div className="text-4xl mb-4">
45
+ <FaFileAlt className="text-purple-500 mx-auto" />
46
+ </div>
47
+ <h3 className="text-xl font-semibold text-gray-900 mb-2">OpenAPI Spec (JSON)</h3>
48
+ <p className="text-gray-600 mb-6">Especificação OpenAPI em formato JSON para integração</p>
49
+ <a
50
+ href="/swagger/json"
51
+ target="_blank"
52
+ rel="noopener noreferrer"
53
+ className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-purple-600 to-purple-700 text-white font-medium rounded-xl hover:from-purple-700 hover:to-purple-800 focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition-all duration-200 shadow-lg hover:shadow-xl"
54
+ >
55
+ <FaClipboardList className="w-4 h-4" />
56
+ Ver JSON
57
+ </a>
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ {/* Embedded Swagger */}
63
+ <div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
64
+ <div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
65
+ <div className="flex items-center gap-2">
66
+ <FaCog className="text-gray-900" />
67
+ <h3 className="text-lg font-semibold text-gray-900">Documentação Integrada</h3>
68
+ </div>
69
+ </div>
70
+ <iframe
71
+ src="/swagger"
72
+ className="w-full h-[600px] border-0"
73
+ title="Swagger UI"
74
+ />
75
+ </div>
76
+
77
+ {/* Eden Treaty Guide */}
78
+ <div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
79
+ <div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
80
+ <div className="flex items-center gap-2">
81
+ <FaCog className="text-gray-900" />
82
+ <h3 className="text-lg font-semibold text-gray-900">Como usar Eden Treaty</h3>
83
+ </div>
84
+ </div>
85
+ <div className="p-6 space-y-6">
86
+ <div>
87
+ <h4 className="text-base font-semibold text-gray-900 mb-3">Configuração do Cliente:</h4>
88
+ <pre className="bg-gray-900 text-gray-100 p-4 rounded-xl overflow-x-auto text-sm border border-gray-700">
89
+ {`import { treaty } from '@elysiajs/eden'
90
+ import type { App } from './server'
91
+
92
+ const client = treaty<App>('http://localhost:3000')
93
+ export const api = client.api`}
94
+ </pre>
95
+ </div>
96
+
97
+ <div>
98
+ <h4 className="text-base font-semibold text-gray-900 mb-3">Exemplos de Uso:</h4>
99
+ <pre className="bg-gray-900 text-gray-100 p-4 rounded-xl overflow-x-auto text-sm border border-gray-700">
100
+ {`// Listar usuários
101
+ const users = await api.users.get()
102
+
103
+ // Criar usuário
104
+ const newUser = await api.users.post({
105
+ name: "João Silva",
106
+ email: "joao@example.com"
107
+ })
108
+
109
+ // Deletar usuário
110
+ await api.users["1"].delete()
111
+
112
+ // Health check
113
+ const health = await api.health.get()`}
114
+ </pre>
115
+ </div>
116
+
117
+ <div>
118
+ <h4 className="text-base font-semibold text-gray-900 mb-3">Com tratamento de erros:</h4>
119
+ <pre className="bg-gray-900 text-gray-100 p-4 rounded-xl overflow-x-auto text-sm border border-gray-700">
120
+ {`try {
121
+ const result = await apiCall(api.users.post({
122
+ name: "Maria Silva",
123
+ email: "maria@example.com"
124
+ }))
125
+
126
+ if (result.success) {
127
+ console.log('Usuário criado:', result.user)
128
+ }
129
+ } catch (error) {
130
+ console.error('Erro:', getErrorMessage(error))
131
+ }`}
132
+ </pre>
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ {/* Features */}
138
+ <div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
139
+ <div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
140
+ <div className="flex items-center justify-center gap-2">
141
+ <FaBolt className="text-gray-900" />
142
+ <h3 className="text-lg font-semibold text-gray-900">Funcionalidades</h3>
143
+ </div>
144
+ </div>
145
+ <div className="p-6">
146
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
147
+ {[
148
+ {
149
+ icon: <FaLock className="text-blue-500" />,
150
+ title: "Type Safety",
151
+ description: "Tipos TypeScript inferidos automaticamente"
152
+ },
153
+ {
154
+ icon: <FaBolt className="text-yellow-500" />,
155
+ title: "Auto-complete",
156
+ description: "IntelliSense completo no editor"
157
+ },
158
+ {
159
+ icon: <FaSync className="text-green-500" />,
160
+ title: "Sincronização",
161
+ description: "Mudanças no backend refletem automaticamente no frontend"
162
+ },
163
+ {
164
+ icon: <FaCode className="text-purple-500" />,
165
+ title: "Debugging",
166
+ description: "Erros de tipo detectados em tempo de compilação"
167
+ }
168
+ ].map((feature, index) => (
169
+ <div key={index} className="flex items-start gap-4 p-4 rounded-xl bg-gray-50 hover:bg-gray-100 transition-colors duration-200">
170
+ <div className="text-2xl">{feature.icon}</div>
171
+ <div>
172
+ <h4 className="font-semibold text-gray-900 mb-1">{feature.title}</h4>
173
+ <p className="text-gray-600 text-sm">{feature.description}</p>
174
+ </div>
175
+ </div>
176
+ ))}
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ );
182
+ }
@@ -0,0 +1,174 @@
1
+ import React from 'react';
2
+ import {
3
+ FaFire, FaRocket, FaCheckCircle, FaTimesCircle, FaSpinner, FaSync, FaUsers, FaPlus, FaTrash
4
+ } from 'react-icons/fa';
5
+
6
+ // This component will receive a lot of props from App.tsx initially.
7
+ // A good next step would be to move this state to a shared context.
8
+ export function DemoPage({
9
+ users,
10
+ apiStatus,
11
+ loading,
12
+ submitting,
13
+ name,
14
+ email,
15
+ setName,
16
+ setEmail,
17
+ handleSubmit,
18
+ handleDelete,
19
+ loadUsers,
20
+ getInitials
21
+ }) {
22
+ return (
23
+ <div className="space-y-8">
24
+ {/* Header */}
25
+ <div className="text-center">
26
+ <div className="flex items-center justify-center gap-3 mb-4">
27
+ <FaFire className="text-3xl text-orange-500" />
28
+ <h2 className="text-3xl font-bold text-gray-900">Demo Interativo</h2>
29
+ </div>
30
+ <div className="flex items-center justify-center gap-2">
31
+ <p className="text-lg text-gray-600 max-w-2xl mx-auto">
32
+ Teste a API em tempo real com hot reload coordenado e Eden Treaty
33
+ </p>
34
+ <FaRocket className="text-lg text-blue-500" />
35
+ </div>
36
+ </div>
37
+
38
+ {/* Stats Cards */}
39
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
40
+ <div className="bg-gradient-to-br from-blue-50 to-blue-100 border border-blue-200 rounded-2xl p-6 text-center">
41
+ <div className="text-4xl font-bold text-blue-600 mb-2">{users.length}</div>
42
+ <div className="text-sm font-medium text-blue-700 uppercase tracking-wide">Usuários</div>
43
+ </div>
44
+ <div className={`bg-gradient-to-br ${apiStatus === 'online' ? 'from-emerald-50 to-emerald-100 border-emerald-200' : 'from-red-50 to-red-100 border-red-200'} border rounded-2xl p-6 text-center`}>
45
+ <div className="text-4xl mb-2">
46
+ {apiStatus === 'online' ? (
47
+ <FaCheckCircle className="text-emerald-500 mx-auto" />
48
+ ) : (
49
+ <FaTimesCircle className="text-red-500 mx-auto" />
50
+ )}
51
+ </div>
52
+ <div className={`text-sm font-medium uppercase tracking-wide ${apiStatus === 'online' ? 'text-emerald-700' : 'text-red-700'}`}>
53
+ API {apiStatus === 'online' ? 'Online' : 'Offline'}
54
+ </div>
55
+ </div>
56
+ <div className="bg-gradient-to-br from-purple-50 to-purple-100 border border-purple-200 rounded-2xl p-6 text-center">
57
+ <div className="text-4xl mb-2">
58
+ <FaRocket className="text-purple-500 mx-auto" />
59
+ </div>
60
+ <div className="text-sm font-medium text-purple-700 uppercase tracking-wide">Eden Treaty</div>
61
+ </div>
62
+ </div>
63
+
64
+ {/* Add User Form */}
65
+ <div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
66
+ <div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
67
+ <h3 className="text-lg font-semibold text-gray-900">Adicionar Usuário</h3>
68
+ </div>
69
+ <div className="p-6">
70
+ <form onSubmit={handleSubmit} className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6">
71
+ <div className="space-y-2">
72
+ <label className="block text-sm font-medium text-gray-700">Nome</label>
73
+ <input
74
+ type="text"
75
+ className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 placeholder-gray-400"
76
+ value={name}
77
+ onChange={(e) => setName(e.target.value)}
78
+ placeholder="Nome completo"
79
+ required
80
+ />
81
+ </div>
82
+ <div className="space-y-2">
83
+ <label className="block text-sm font-medium text-gray-700">Email</label>
84
+ <input
85
+ type="email"
86
+ className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 placeholder-gray-400"
87
+ value={email}
88
+ onChange={(e) => setEmail(e.target.value)}
89
+ placeholder="email@exemplo.com"
90
+ required
91
+ />
92
+ </div>
93
+ <div className="md:col-span-2">
94
+ <button
95
+ type="submit"
96
+ className="w-full md:w-auto px-8 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white font-medium rounded-xl hover:from-blue-700 hover:to-blue-800 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 shadow-lg hover:shadow-xl"
97
+ disabled={submitting || !name.trim() || !email.trim()}
98
+ >
99
+ {submitting ? (
100
+ <span className="flex items-center gap-2">
101
+ <FaSpinner className="w-4 h-4 animate-spin" />
102
+ Adicionando...
103
+ </span>
104
+ ) : (
105
+ <span className="flex items-center gap-2">
106
+ <FaPlus className="w-4 h-4" />
107
+ Adicionar Usuário
108
+ </span>
109
+ )}
110
+ </button>
111
+ </div>
112
+ </form>
113
+ </div>
114
+ </div>
115
+
116
+ {/* Users List */}
117
+ <div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
118
+ <div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200 flex justify-between items-center">
119
+ <h3 className="text-lg font-semibold text-gray-900">Usuários ({users.length})</h3>
120
+ <button
121
+ className="flex items-center gap-2 px-4 py-2 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 transition-all duration-200"
122
+ onClick={loadUsers}
123
+ disabled={loading}
124
+ >
125
+ {loading ? (
126
+ <FaSpinner className="w-4 h-4 animate-spin" />
127
+ ) : (
128
+ <FaSync className="w-4 h-4" />
129
+ )}
130
+ Atualizar
131
+ </button>
132
+ </div>
133
+
134
+ <div className="p-6">
135
+ {loading ? (
136
+ <div className="text-center py-12">
137
+ <FaSpinner className="w-8 h-8 text-blue-600 animate-spin mx-auto mb-4" />
138
+ <p className="text-gray-600">Carregando usuários...</p>
139
+ </div>
140
+ ) : users.length === 0 ? (
141
+ <div className="text-center py-12">
142
+ <FaUsers className="text-6xl text-gray-400 mx-auto mb-4" />
143
+ <h4 className="text-lg font-medium text-gray-900 mb-2">Nenhum usuário encontrado</h4>
144
+ <p className="text-gray-600">Adicione o primeiro usuário usando o formulário acima</p>
145
+ </div>
146
+ ) : (
147
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
148
+ {users.map(user => (
149
+ <div key={user.id} className="group bg-gray-50 border border-gray-200 rounded-xl p-4 hover:shadow-lg hover:border-blue-300 transition-all duration-200">
150
+ <div className="flex items-start gap-3">
151
+ <div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-bold text-sm flex-shrink-0">
152
+ {getInitials(user.name)}
153
+ </div>
154
+ <div className="flex-1 min-w-0">
155
+ <h4 className="font-medium text-gray-900 truncate">{user.name}</h4>
156
+ <p className="text-sm text-gray-600 truncate">{user.email}</p>
157
+ <button
158
+ className="mt-3 w-full px-3 py-2 bg-red-50 text-red-700 border border-red-200 rounded-lg hover:bg-red-100 hover:border-red-300 focus:ring-2 focus:ring-red-500 focus:ring-offset-2 transition-all duration-200 text-sm font-medium flex items-center justify-center gap-2"
159
+ onClick={() => handleDelete(user.id, user.name)}
160
+ >
161
+ <FaTrash className="w-3 h-3" />
162
+ Remover
163
+ </button>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ ))}
168
+ </div>
169
+ )}
170
+ </div>
171
+ </div>
172
+ </div>
173
+ );
174
+ }