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
package/app/client/src/App.tsx
CHANGED
|
@@ -1,319 +1,184 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react'
|
|
2
|
-
import { api
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import { OverviewPage } from './pages/Overview'
|
|
15
|
-
import { DemoPage } from './pages/Demo'
|
|
16
|
-
import { HybridLivePage } from './pages/HybridLive'
|
|
17
|
-
import { ApiDocsPage } from './pages/ApiDocs'
|
|
18
|
-
import { CryptoAuthPage } from './pages/CryptoAuthPage'
|
|
19
|
-
import { MainLayout } from './components/MainLayout'
|
|
20
|
-
|
|
21
|
-
// State management is now handled by Zustand stores directly
|
|
22
|
-
|
|
23
|
-
interface User {
|
|
24
|
-
id: number
|
|
25
|
-
name: string
|
|
26
|
-
email: string
|
|
27
|
-
createdAt: string | Date
|
|
2
|
+
import { api } from './lib/eden-api'
|
|
3
|
+
import { FaFire, FaBook, FaGithub, FaClock } from 'react-icons/fa'
|
|
4
|
+
import { LiveComponentsProvider, useHybridLiveComponent } from '@/core/client'
|
|
5
|
+
|
|
6
|
+
interface LiveClockState {
|
|
7
|
+
currentTime: string
|
|
8
|
+
timeZone: string
|
|
9
|
+
format: '12h' | '24h'
|
|
10
|
+
showSeconds: boolean
|
|
11
|
+
showDate: boolean
|
|
12
|
+
lastSync: Date
|
|
13
|
+
serverUptime: number
|
|
28
14
|
}
|
|
29
15
|
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
const initialClockState: LiveClockState = {
|
|
17
|
+
currentTime: "Loading...",
|
|
18
|
+
timeZone: "America/Sao_Paulo",
|
|
19
|
+
format: "24h",
|
|
20
|
+
showSeconds: true,
|
|
21
|
+
showDate: true,
|
|
22
|
+
lastSync: new Date(),
|
|
23
|
+
serverUptime: 0,
|
|
32
24
|
}
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
// Minimal Live Clock Component
|
|
27
|
+
function MinimalLiveClock() {
|
|
28
|
+
const { state } = useHybridLiveComponent<LiveClockState>(
|
|
29
|
+
'LiveClock',
|
|
30
|
+
initialClockState
|
|
31
|
+
)
|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
return (
|
|
34
|
+
<div className="bg-gradient-to-br from-blue-500/10 to-purple-500/10 rounded-xl p-4 border border-blue-400/20">
|
|
35
|
+
<div className="text-4xl font-mono font-bold text-white text-center tracking-wider">
|
|
36
|
+
{state.currentTime}
|
|
37
|
+
</div>
|
|
38
|
+
<div className="text-center mt-2">
|
|
39
|
+
<span className="text-xs text-gray-400">{state.timeZone}</span>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function AppContent() {
|
|
46
|
-
const [
|
|
47
|
-
const [loading, setLoading] = useState(false)
|
|
48
|
-
const [apiStatus, setApiStatus] = useState<'online' | 'offline'>('offline')
|
|
49
|
-
const [name, setName] = useState('')
|
|
50
|
-
const [email, setEmail] = useState('')
|
|
51
|
-
const [submitting, setSubmitting] = useState(false)
|
|
52
|
-
const [message, setMessage] = useState<{ type: 'success' | 'error', text: string } | null>(null)
|
|
46
|
+
const [apiStatus, setApiStatus] = useState<'checking' | 'online' | 'offline'>('checking')
|
|
53
47
|
|
|
54
48
|
useEffect(() => {
|
|
55
49
|
checkApiStatus()
|
|
56
|
-
|
|
57
|
-
}, []) // eslint-disable-line react-hooks/exhaustive-deps
|
|
50
|
+
}, [])
|
|
58
51
|
|
|
59
52
|
const checkApiStatus = async () => {
|
|
60
53
|
try {
|
|
61
54
|
const { error } = await api.health.get()
|
|
62
|
-
|
|
63
|
-
setApiStatus('offline')
|
|
64
|
-
} else {
|
|
65
|
-
setApiStatus('online')
|
|
66
|
-
}
|
|
55
|
+
setApiStatus(error ? 'offline' : 'online')
|
|
67
56
|
} catch {
|
|
68
57
|
setApiStatus('offline')
|
|
69
58
|
}
|
|
70
59
|
}
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
setUsers((data as UsersResponse).users || [])
|
|
83
|
-
} catch (error) {
|
|
84
|
-
showMessage('error', getErrorMessage(error))
|
|
85
|
-
} finally {
|
|
86
|
-
setLoading(false)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const handleSubmit = async (e: React.FormEvent) => {
|
|
91
|
-
e.preventDefault()
|
|
92
|
-
if (!name.trim() || !email.trim()) return
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
setSubmitting(true)
|
|
96
|
-
const { data: result, error } = await api.users.post({
|
|
97
|
-
name: name.trim(),
|
|
98
|
-
email: email.trim()
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
if (error) {
|
|
102
|
-
showMessage('error', `Erro ao criar usuรกrio: ${error.status}`)
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const createResult = result as UserCreateResponse
|
|
107
|
-
if (createResult.success && createResult.user) {
|
|
108
|
-
setUsers(prev => [...prev, createResult.user!])
|
|
109
|
-
setName('')
|
|
110
|
-
setEmail('')
|
|
111
|
-
showMessage('success', `Usuรกrio ${name} adicionado com sucesso!`)
|
|
112
|
-
} else {
|
|
113
|
-
showMessage('error', createResult.message || 'Erro ao criar usuรกrio')
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
showMessage('error', getErrorMessage(error))
|
|
117
|
-
} finally {
|
|
118
|
-
setSubmitting(false)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const handleDelete = async (userId: number, userName: string) => {
|
|
123
|
-
if (!confirm(`Tem certeza que deseja remover ${userName}?`)) return
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const { data: result, error } = await api.users({ id: userId }).delete()
|
|
127
|
-
|
|
128
|
-
if (error) {
|
|
129
|
-
showMessage('error', `Erro ao deletar usuรกrio: ${error.status}`)
|
|
130
|
-
return
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const deleteResult = result as UserDeleteResponse
|
|
134
|
-
if (deleteResult.success) {
|
|
135
|
-
setUsers(prev => prev.filter(user => user.id !== userId))
|
|
136
|
-
showMessage('success', `Usuรกrio ${userName} removido com sucesso!`)
|
|
137
|
-
} else {
|
|
138
|
-
showMessage('error', deleteResult.message || 'Erro ao deletar usuรกrio')
|
|
139
|
-
}
|
|
140
|
-
} catch (error) {
|
|
141
|
-
showMessage('error', getErrorMessage(error))
|
|
142
|
-
}
|
|
143
|
-
}
|
|
61
|
+
return (
|
|
62
|
+
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900">
|
|
63
|
+
<div className="flex flex-col items-center justify-center min-h-screen px-6 text-center">
|
|
64
|
+
{/* Logo */}
|
|
65
|
+
<div className="mb-8 animate-pulse-slow">
|
|
66
|
+
<FaFire className="text-8xl text-orange-500 drop-shadow-2xl" />
|
|
67
|
+
</div>
|
|
144
68
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
69
|
+
{/* Title */}
|
|
70
|
+
<h1 className="text-6xl md:text-7xl font-bold mb-4 bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">
|
|
71
|
+
FluxStack
|
|
72
|
+
</h1>
|
|
73
|
+
|
|
74
|
+
{/* Subtitle */}
|
|
75
|
+
<p className="text-xl md:text-2xl text-gray-300 mb-8 max-w-2xl">
|
|
76
|
+
Full-stack TypeScript framework with{' '}
|
|
77
|
+
<span className="text-purple-400 font-semibold">Bun</span>,{' '}
|
|
78
|
+
<span className="text-blue-400 font-semibold">Elysia</span>, and{' '}
|
|
79
|
+
<span className="text-cyan-400 font-semibold">React</span>
|
|
80
|
+
</p>
|
|
81
|
+
|
|
82
|
+
{/* API Status Badge */}
|
|
83
|
+
<div className="mb-12">
|
|
84
|
+
<div className={`inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium transition-all ${
|
|
85
|
+
apiStatus === 'online'
|
|
86
|
+
? 'bg-emerald-500/20 text-emerald-300 border border-emerald-500/30'
|
|
87
|
+
: apiStatus === 'offline'
|
|
88
|
+
? 'bg-red-500/20 text-red-300 border border-red-500/30'
|
|
89
|
+
: 'bg-yellow-500/20 text-yellow-300 border border-yellow-500/30'
|
|
90
|
+
}`}>
|
|
91
|
+
<div className={`w-2 h-2 rounded-full ${
|
|
92
|
+
apiStatus === 'online' ? 'bg-emerald-400' : apiStatus === 'offline' ? 'bg-red-400' : 'bg-yellow-400'
|
|
93
|
+
}`}></div>
|
|
94
|
+
<span>{apiStatus === 'checking' ? 'Checking API...' : apiStatus === 'online' ? 'API Online' : 'API Offline'}</span>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
149
97
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
98
|
+
{/* Feature Cards */}
|
|
99
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12 max-w-6xl">
|
|
100
|
+
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
|
|
101
|
+
<div className="text-3xl mb-3">โก</div>
|
|
102
|
+
<h3 className="text-lg font-semibold text-white mb-2">Ultra Rรกpido</h3>
|
|
103
|
+
<p className="text-gray-400 text-sm">Bun runtime 3x mais rรกpido que Node.js</p>
|
|
104
|
+
</div>
|
|
153
105
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
{/* Regular routes with header and layout */}
|
|
161
|
-
<Route path="*" element={
|
|
162
|
-
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100">
|
|
163
|
-
{/* Header */}
|
|
164
|
-
<header className="bg-white/80 backdrop-blur-sm border-b border-gray-200 sticky top-0 z-50">
|
|
165
|
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
166
|
-
<div className="flex justify-between items-center h-16">
|
|
167
|
-
{/* Logo and Navigation */}
|
|
168
|
-
<div className="flex items-center space-x-8">
|
|
169
|
-
<div className="flex items-center space-x-3">
|
|
170
|
-
<div className="flex items-center gap-2">
|
|
171
|
-
<FaFire className="text-2xl text-orange-500" />
|
|
172
|
-
<div className="text-2xl font-bold bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent">
|
|
173
|
-
FluxStack
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
<span className="px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
|
|
177
|
-
v1.4.0
|
|
178
|
-
</span>
|
|
179
|
-
</div>
|
|
180
|
-
|
|
181
|
-
{/* Navigation Tabs */}
|
|
182
|
-
<nav className="hidden md:flex space-x-1">
|
|
183
|
-
{[
|
|
184
|
-
{ id: 'overview', label: 'Visรฃo Geral', icon: <FaClipboardList />, path: '/' },
|
|
185
|
-
{ id: 'demo', label: 'Demo', icon: <FaRocket />, path: '/demo' },
|
|
186
|
-
{ id: 'crypto-auth', label: 'Crypto Auth', icon: <FaShieldAlt />, path: '/crypto-auth' },
|
|
187
|
-
{ id: 'hybrid-live', label: 'Hybrid Live', icon: <FaBolt />, path: '/hybrid-live' },
|
|
188
|
-
{ id: 'live-app', label: 'Live App', icon: <FaFire />, path: '/live-app' },
|
|
189
|
-
{ id: 'api-docs', label: 'API Docs', icon: <FaBook />, path: '/api-docs' },
|
|
190
|
-
{ id: 'tests', label: 'Testes', icon: <FaTest />, path: '/tests' }
|
|
191
|
-
].map(tab => (
|
|
192
|
-
<Link
|
|
193
|
-
key={tab.id}
|
|
194
|
-
to={tab.path}
|
|
195
|
-
className={`px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 ${
|
|
196
|
-
location.pathname === tab.path
|
|
197
|
-
? 'bg-blue-100 text-blue-700 shadow-sm'
|
|
198
|
-
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
|
|
199
|
-
}`}
|
|
200
|
-
>
|
|
201
|
-
<div className="flex items-center gap-2">
|
|
202
|
-
{tab.icon}
|
|
203
|
-
{tab.label}
|
|
204
|
-
</div>
|
|
205
|
-
</Link>
|
|
206
|
-
))}
|
|
207
|
-
</nav>
|
|
208
|
-
</div>
|
|
106
|
+
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
|
|
107
|
+
<div className="text-3xl mb-3">๐</div>
|
|
108
|
+
<h3 className="text-lg font-semibold text-white mb-2">Type Safe</h3>
|
|
109
|
+
<p className="text-gray-400 text-sm">Eden Treaty com inferรชncia automรกtica</p>
|
|
110
|
+
</div>
|
|
209
111
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}`}>
|
|
216
|
-
<div className={`w-2 h-2 rounded-full ${
|
|
217
|
-
apiStatus === 'online' ? 'bg-emerald-400' : 'bg-red-400'
|
|
218
|
-
}`}></div>
|
|
219
|
-
<span>API {apiStatus === 'online' ? 'Online' : 'Offline'}</span>
|
|
220
|
-
</div>
|
|
221
|
-
</div>
|
|
112
|
+
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
|
|
113
|
+
<div className="text-3xl mb-3">๐จ</div>
|
|
114
|
+
<h3 className="text-lg font-semibold text-white mb-2">Moderno</h3>
|
|
115
|
+
<p className="text-gray-400 text-sm">React 19 + Vite + Tailwind CSS</p>
|
|
116
|
+
</div>
|
|
222
117
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
{ id: 'hybrid-live', label: 'Hybrid', icon: <FaBolt />, path: '/hybrid-live' },
|
|
231
|
-
{ id: 'api-docs', label: 'Docs', icon: <FaBook />, path: '/api-docs' },
|
|
232
|
-
{ id: 'tests', label: 'Testes', icon: <FaTest />, path: '/tests' }
|
|
233
|
-
].map(tab => (
|
|
234
|
-
<Link
|
|
235
|
-
key={tab.id}
|
|
236
|
-
to={tab.path}
|
|
237
|
-
className={`flex-1 px-3 py-2 text-xs font-medium rounded-lg transition-all duration-200 ${
|
|
238
|
-
location.pathname === tab.path
|
|
239
|
-
? 'bg-blue-100 text-blue-700'
|
|
240
|
-
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
|
|
241
|
-
}`}
|
|
242
|
-
>
|
|
243
|
-
<div className="flex flex-col items-center gap-1">
|
|
244
|
-
{tab.icon}
|
|
245
|
-
<span>{tab.label}</span>
|
|
246
|
-
</div>
|
|
247
|
-
</Link>
|
|
248
|
-
))}
|
|
249
|
-
</nav>
|
|
250
|
-
</div>
|
|
118
|
+
{/* Live Clock Card */}
|
|
119
|
+
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
|
|
120
|
+
<div className="flex items-center gap-3 mb-3">
|
|
121
|
+
<FaClock className="text-2xl text-emerald-400" />
|
|
122
|
+
<div>
|
|
123
|
+
<h3 className="text-lg font-semibold text-white">Live Clock</h3>
|
|
124
|
+
<p className="text-gray-400 text-sm">Provido via LiveComponent</p>
|
|
251
125
|
</div>
|
|
252
|
-
</
|
|
253
|
-
|
|
254
|
-
{/* Main Content */}
|
|
255
|
-
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
256
|
-
<Routes>
|
|
257
|
-
<Route path="/" element={<OverviewPage />} />
|
|
258
|
-
<Route
|
|
259
|
-
path="/demo"
|
|
260
|
-
element={
|
|
261
|
-
<DemoPage
|
|
262
|
-
users={users}
|
|
263
|
-
apiStatus={apiStatus}
|
|
264
|
-
loading={loading}
|
|
265
|
-
submitting={submitting}
|
|
266
|
-
name={name}
|
|
267
|
-
email={email}
|
|
268
|
-
setName={setName}
|
|
269
|
-
setEmail={setEmail}
|
|
270
|
-
handleSubmit={handleSubmit}
|
|
271
|
-
handleDelete={handleDelete}
|
|
272
|
-
loadUsers={loadUsers}
|
|
273
|
-
getInitials={getInitials}
|
|
274
|
-
/>
|
|
275
|
-
}
|
|
276
|
-
/>
|
|
277
|
-
<Route path="/crypto-auth" element={<CryptoAuthPage />} />
|
|
278
|
-
<Route path="/hybrid-live" element={<HybridLivePage />} />
|
|
279
|
-
<Route path="/api-docs" element={<ApiDocsPage />} />
|
|
280
|
-
<Route path="/tests" element={
|
|
281
|
-
<div className="p-6">
|
|
282
|
-
<h2 className="text-2xl font-bold mb-4">๐งช Tests</h2>
|
|
283
|
-
<p className="text-gray-600">Test suite functionality will be available here.</p>
|
|
284
|
-
</div>
|
|
285
|
-
} />
|
|
286
|
-
</Routes>
|
|
287
|
-
</main>
|
|
126
|
+
</div>
|
|
127
|
+
<MinimalLiveClock />
|
|
288
128
|
</div>
|
|
289
|
-
|
|
290
|
-
</Routes>
|
|
129
|
+
</div>
|
|
291
130
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
131
|
+
{/* Action Buttons */}
|
|
132
|
+
<div className="flex flex-wrap gap-4 justify-center">
|
|
133
|
+
<a
|
|
134
|
+
href="http://localhost:3000/swagger"
|
|
135
|
+
target="_blank"
|
|
136
|
+
rel="noopener noreferrer"
|
|
137
|
+
className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-xl font-medium hover:shadow-lg hover:shadow-purple-500/50 transition-all"
|
|
138
|
+
>
|
|
139
|
+
<FaBook />
|
|
140
|
+
API Docs
|
|
141
|
+
</a>
|
|
142
|
+
<a
|
|
143
|
+
href="https://github.com/MarcosBrendonDePaula/FluxStack"
|
|
144
|
+
target="_blank"
|
|
145
|
+
rel="noopener noreferrer"
|
|
146
|
+
className="inline-flex items-center gap-2 px-6 py-3 bg-white/10 backdrop-blur-sm border border-white/20 text-white rounded-xl font-medium hover:bg-white/20 transition-all"
|
|
147
|
+
>
|
|
148
|
+
<FaGithub />
|
|
149
|
+
GitHub
|
|
150
|
+
</a>
|
|
151
|
+
<a
|
|
152
|
+
href="http://localhost:3000/api"
|
|
153
|
+
target="_blank"
|
|
154
|
+
rel="noopener noreferrer"
|
|
155
|
+
className="inline-flex items-center gap-2 px-6 py-3 bg-white/10 backdrop-blur-sm border border-white/20 text-white rounded-xl font-medium hover:bg-white/20 transition-all"
|
|
156
|
+
>
|
|
157
|
+
๐ API Root
|
|
158
|
+
</a>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
{/* Footer */}
|
|
162
|
+
<div className="mt-16 text-gray-500 text-sm">
|
|
163
|
+
<p>Desenvolvido com โค๏ธ usando TypeScript</p>
|
|
310
164
|
</div>
|
|
311
|
-
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
{/* Animations */}
|
|
168
|
+
<style>{`
|
|
169
|
+
@keyframes pulse-slow {
|
|
170
|
+
0%, 100% { opacity: 1; }
|
|
171
|
+
50% { opacity: 0.8; }
|
|
172
|
+
}
|
|
173
|
+
.animate-pulse-slow {
|
|
174
|
+
animation: pulse-slow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
175
|
+
}
|
|
176
|
+
`}</style>
|
|
312
177
|
</div>
|
|
313
178
|
)
|
|
314
179
|
}
|
|
315
180
|
|
|
316
|
-
// Main App
|
|
181
|
+
// Main App with LiveComponentsProvider
|
|
317
182
|
function App() {
|
|
318
183
|
return (
|
|
319
184
|
<LiveComponentsProvider
|
|
@@ -328,4 +193,4 @@ function App() {
|
|
|
328
193
|
)
|
|
329
194
|
}
|
|
330
195
|
|
|
331
|
-
export default App
|
|
196
|
+
export default App
|
package/app/client/src/index.css
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
|
|
3
|
-
/*
|
|
4
|
-
:root {
|
|
5
|
-
--gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
6
|
-
--gradient-secondary: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
|
7
|
-
--gradient-accent: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/* Base styles with improved typography */
|
|
3
|
+
/* Base styles */
|
|
11
4
|
* {
|
|
12
5
|
box-sizing: border-box;
|
|
13
6
|
}
|
|
@@ -18,34 +11,26 @@ body {
|
|
|
18
11
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
|
|
19
12
|
-webkit-font-smoothing: antialiased;
|
|
20
13
|
-moz-osx-font-smoothing: grayscale;
|
|
21
|
-
line-height: 1.6;
|
|
22
14
|
}
|
|
23
15
|
|
|
24
|
-
/* Smooth scrolling */
|
|
25
16
|
html {
|
|
26
17
|
scroll-behavior: smooth;
|
|
27
18
|
}
|
|
28
19
|
|
|
29
|
-
/* Custom scrollbar
|
|
20
|
+
/* Custom scrollbar */
|
|
30
21
|
::-webkit-scrollbar {
|
|
31
22
|
width: 8px;
|
|
32
23
|
}
|
|
33
24
|
|
|
34
25
|
::-webkit-scrollbar-track {
|
|
35
|
-
background: #
|
|
26
|
+
background: #1e293b;
|
|
36
27
|
}
|
|
37
28
|
|
|
38
29
|
::-webkit-scrollbar-thumb {
|
|
39
|
-
background: #
|
|
30
|
+
background: #475569;
|
|
40
31
|
border-radius: 4px;
|
|
41
32
|
}
|
|
42
33
|
|
|
43
34
|
::-webkit-scrollbar-thumb:hover {
|
|
44
|
-
background: #
|
|
35
|
+
background: #64748b;
|
|
45
36
|
}
|
|
46
|
-
|
|
47
|
-
/* Focus styles for accessibility */
|
|
48
|
-
*:focus {
|
|
49
|
-
outline: 2px solid #3b82f6;
|
|
50
|
-
outline-offset: 2px;
|
|
51
|
-
}
|