create-fluxstack 1.10.1 → 1.12.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.
Files changed (257) hide show
  1. package/.dockerignore +1 -2
  2. package/Dockerfile +8 -8
  3. package/LLMD/INDEX.md +64 -0
  4. package/LLMD/MAINTENANCE.md +197 -0
  5. package/LLMD/MIGRATION.md +156 -0
  6. package/LLMD/config/.gitkeep +1 -0
  7. package/LLMD/config/declarative-system.md +268 -0
  8. package/LLMD/config/environment-vars.md +327 -0
  9. package/LLMD/config/runtime-reload.md +401 -0
  10. package/LLMD/core/.gitkeep +1 -0
  11. package/LLMD/core/build-system.md +599 -0
  12. package/LLMD/core/framework-lifecycle.md +229 -0
  13. package/LLMD/core/plugin-system.md +451 -0
  14. package/LLMD/patterns/.gitkeep +1 -0
  15. package/LLMD/patterns/anti-patterns.md +297 -0
  16. package/LLMD/patterns/project-structure.md +264 -0
  17. package/LLMD/patterns/type-safety.md +440 -0
  18. package/LLMD/reference/.gitkeep +1 -0
  19. package/LLMD/reference/cli-commands.md +250 -0
  20. package/LLMD/reference/plugin-hooks.md +357 -0
  21. package/LLMD/reference/routing.md +39 -0
  22. package/LLMD/reference/troubleshooting.md +364 -0
  23. package/LLMD/resources/.gitkeep +1 -0
  24. package/LLMD/resources/controllers.md +465 -0
  25. package/LLMD/resources/live-components.md +703 -0
  26. package/LLMD/resources/live-rooms.md +482 -0
  27. package/LLMD/resources/live-upload.md +130 -0
  28. package/LLMD/resources/plugins-external.md +617 -0
  29. package/LLMD/resources/routes-eden.md +254 -0
  30. package/README.md +37 -17
  31. package/app/client/index.html +0 -1
  32. package/app/client/src/App.tsx +107 -150
  33. package/app/client/src/components/AppLayout.tsx +68 -0
  34. package/app/client/src/components/BackButton.tsx +13 -0
  35. package/app/client/src/components/DemoPage.tsx +20 -0
  36. package/app/client/src/components/LiveUploadWidget.tsx +204 -0
  37. package/app/client/src/lib/eden-api.ts +85 -60
  38. package/app/client/src/live/ChatDemo.tsx +107 -0
  39. package/app/client/src/live/CounterDemo.tsx +206 -0
  40. package/app/client/src/live/FormDemo.tsx +119 -0
  41. package/app/client/src/live/RoomChatDemo.tsx +161 -0
  42. package/app/client/src/live/UploadDemo.tsx +21 -0
  43. package/app/client/src/main.tsx +4 -1
  44. package/app/client/src/pages/ApiTestPage.tsx +108 -0
  45. package/app/client/src/pages/HomePage.tsx +76 -0
  46. package/app/server/app.ts +1 -4
  47. package/app/server/controllers/users.controller.ts +36 -44
  48. package/app/server/index.ts +25 -35
  49. package/app/server/live/LiveChat.ts +77 -0
  50. package/app/server/live/LiveCounter.ts +67 -0
  51. package/app/server/live/LiveForm.ts +63 -0
  52. package/app/server/live/LiveLocalCounter.ts +32 -0
  53. package/app/server/live/LiveRoomChat.ts +127 -0
  54. package/app/server/live/LiveUpload.ts +81 -0
  55. package/app/server/routes/index.ts +3 -1
  56. package/app/server/routes/room.routes.ts +117 -0
  57. package/app/server/routes/users.routes.ts +35 -27
  58. package/app/shared/types/index.ts +14 -2
  59. package/config/app.config.ts +2 -62
  60. package/config/client.config.ts +2 -95
  61. package/config/database.config.ts +2 -99
  62. package/config/fluxstack.config.ts +25 -45
  63. package/config/index.ts +57 -38
  64. package/config/monitoring.config.ts +2 -114
  65. package/config/plugins.config.ts +2 -80
  66. package/config/server.config.ts +2 -68
  67. package/config/services.config.ts +2 -130
  68. package/config/system/app.config.ts +29 -0
  69. package/config/system/build.config.ts +49 -0
  70. package/config/system/client.config.ts +68 -0
  71. package/config/system/database.config.ts +17 -0
  72. package/config/system/fluxstack.config.ts +114 -0
  73. package/config/{logger.config.ts → system/logger.config.ts} +3 -1
  74. package/config/system/monitoring.config.ts +114 -0
  75. package/config/system/plugins.config.ts +84 -0
  76. package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
  77. package/config/system/server.config.ts +68 -0
  78. package/config/system/services.config.ts +46 -0
  79. package/config/{system.config.ts → system/system.config.ts} +1 -1
  80. package/core/build/flux-plugins-generator.ts +325 -325
  81. package/core/build/index.ts +39 -27
  82. package/core/build/live-components-generator.ts +3 -3
  83. package/core/build/optimizer.ts +235 -235
  84. package/core/cli/command-registry.ts +6 -4
  85. package/core/cli/commands/build.ts +79 -0
  86. package/core/cli/commands/create.ts +54 -0
  87. package/core/cli/commands/dev.ts +101 -0
  88. package/core/cli/commands/help.ts +34 -0
  89. package/core/cli/commands/index.ts +34 -0
  90. package/core/cli/commands/make-plugin.ts +90 -0
  91. package/core/cli/commands/plugin-add.ts +197 -0
  92. package/core/cli/commands/plugin-deps.ts +2 -2
  93. package/core/cli/commands/plugin-list.ts +208 -0
  94. package/core/cli/commands/plugin-remove.ts +170 -0
  95. package/core/cli/generators/component.ts +769 -769
  96. package/core/cli/generators/controller.ts +1 -1
  97. package/core/cli/generators/index.ts +146 -146
  98. package/core/cli/generators/interactive.ts +227 -227
  99. package/core/cli/generators/plugin.ts +2 -2
  100. package/core/cli/generators/prompts.ts +82 -82
  101. package/core/cli/generators/route.ts +6 -6
  102. package/core/cli/generators/service.ts +2 -2
  103. package/core/cli/generators/template-engine.ts +4 -3
  104. package/core/cli/generators/types.ts +2 -2
  105. package/core/cli/generators/utils.ts +191 -191
  106. package/core/cli/index.ts +115 -686
  107. package/core/cli/plugin-discovery.ts +2 -2
  108. package/core/client/LiveComponentsProvider.tsx +60 -8
  109. package/core/client/api/eden.ts +183 -0
  110. package/core/client/api/index.ts +11 -0
  111. package/core/client/components/Live.tsx +104 -0
  112. package/core/client/fluxstack.ts +1 -9
  113. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
  114. package/core/client/hooks/state-validator.ts +1 -1
  115. package/core/client/hooks/useAuth.ts +48 -48
  116. package/core/client/hooks/useChunkedUpload.ts +85 -35
  117. package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
  118. package/core/client/hooks/useLiveComponent.ts +800 -0
  119. package/core/client/hooks/useLiveUpload.ts +71 -0
  120. package/core/client/hooks/useRoom.ts +409 -0
  121. package/core/client/hooks/useRoomProxy.ts +382 -0
  122. package/core/client/index.ts +17 -68
  123. package/core/client/standalone-entry.ts +8 -0
  124. package/core/client/standalone.ts +74 -53
  125. package/core/client/state/createStore.ts +192 -192
  126. package/core/client/state/index.ts +14 -14
  127. package/core/config/index.ts +70 -291
  128. package/core/config/schema.ts +42 -723
  129. package/core/framework/client.ts +131 -131
  130. package/core/framework/index.ts +7 -7
  131. package/core/framework/server.ts +47 -40
  132. package/core/framework/types.ts +2 -2
  133. package/core/index.ts +23 -4
  134. package/core/live/ComponentRegistry.ts +3 -3
  135. package/core/live/types.ts +77 -0
  136. package/core/plugins/built-in/index.ts +134 -134
  137. package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1066
  138. package/core/plugins/built-in/live-components/index.ts +1 -1
  139. package/core/plugins/built-in/monitoring/index.ts +111 -47
  140. package/core/plugins/built-in/static/index.ts +1 -1
  141. package/core/plugins/built-in/swagger/index.ts +68 -265
  142. package/core/plugins/built-in/vite/index.ts +85 -185
  143. package/core/plugins/built-in/vite/vite-dev.ts +10 -16
  144. package/core/plugins/config.ts +9 -7
  145. package/core/plugins/dependency-manager.ts +31 -1
  146. package/core/plugins/discovery.ts +19 -7
  147. package/core/plugins/executor.ts +2 -2
  148. package/core/plugins/index.ts +203 -203
  149. package/core/plugins/manager.ts +27 -39
  150. package/core/plugins/module-resolver.ts +19 -8
  151. package/core/plugins/registry.ts +255 -19
  152. package/core/plugins/types.ts +20 -53
  153. package/core/server/framework.ts +66 -43
  154. package/core/server/index.ts +15 -15
  155. package/core/server/live/ComponentRegistry.ts +78 -71
  156. package/core/server/live/FileUploadManager.ts +23 -10
  157. package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
  158. package/core/server/live/LiveRoomManager.ts +261 -0
  159. package/core/server/live/RoomEventBus.ts +234 -0
  160. package/core/server/live/RoomStateManager.ts +172 -0
  161. package/core/server/live/StateSignature.ts +643 -643
  162. package/core/server/live/WebSocketConnectionManager.ts +30 -19
  163. package/core/server/live/auto-generated-components.ts +21 -9
  164. package/core/server/live/index.ts +14 -0
  165. package/core/server/live/websocket-plugin.ts +214 -67
  166. package/core/server/middleware/elysia-helpers.ts +7 -2
  167. package/core/server/middleware/errorHandling.ts +1 -1
  168. package/core/server/middleware/index.ts +31 -31
  169. package/core/server/plugins/database.ts +180 -180
  170. package/core/server/plugins/static-files-plugin.ts +69 -69
  171. package/core/server/plugins/swagger.ts +1 -1
  172. package/core/server/rooms/RoomBroadcaster.ts +357 -0
  173. package/core/server/rooms/RoomSystem.ts +463 -0
  174. package/core/server/rooms/index.ts +13 -0
  175. package/core/server/services/BaseService.ts +1 -1
  176. package/core/server/services/ServiceContainer.ts +1 -1
  177. package/core/server/services/index.ts +8 -8
  178. package/core/templates/create-project.ts +12 -12
  179. package/core/testing/index.ts +9 -9
  180. package/core/testing/setup.ts +73 -73
  181. package/core/types/api.ts +168 -168
  182. package/core/types/build.ts +219 -219
  183. package/core/types/config.ts +56 -26
  184. package/core/types/index.ts +4 -4
  185. package/core/types/plugin.ts +107 -107
  186. package/core/types/types.ts +353 -14
  187. package/core/utils/build-logger.ts +324 -324
  188. package/core/utils/config-schema.ts +480 -480
  189. package/core/utils/env.ts +2 -8
  190. package/core/utils/errors/codes.ts +114 -114
  191. package/core/utils/errors/handlers.ts +36 -1
  192. package/core/utils/errors/index.ts +49 -5
  193. package/core/utils/errors/middleware.ts +113 -113
  194. package/core/utils/helpers.ts +6 -16
  195. package/core/utils/index.ts +17 -17
  196. package/core/utils/logger/colors.ts +114 -114
  197. package/core/utils/logger/config.ts +13 -9
  198. package/core/utils/logger/formatter.ts +82 -82
  199. package/core/utils/logger/group-logger.ts +101 -101
  200. package/core/utils/logger/index.ts +6 -1
  201. package/core/utils/logger/stack-trace.ts +3 -1
  202. package/core/utils/logger/startup-banner.ts +82 -82
  203. package/core/utils/logger/winston-logger.ts +152 -152
  204. package/core/utils/monitoring/index.ts +211 -211
  205. package/core/utils/sync-version.ts +66 -66
  206. package/core/utils/version.ts +1 -1
  207. package/create-fluxstack.ts +8 -7
  208. package/package.json +12 -13
  209. package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
  210. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  211. package/plugins/crypto-auth/client/components/index.ts +11 -11
  212. package/plugins/crypto-auth/client/index.ts +11 -11
  213. package/plugins/crypto-auth/config/index.ts +1 -1
  214. package/plugins/crypto-auth/index.ts +4 -4
  215. package/plugins/crypto-auth/package.json +65 -65
  216. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  217. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  218. package/plugins/crypto-auth/server/index.ts +21 -21
  219. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
  220. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
  221. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
  222. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
  223. package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
  224. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  225. package/tsconfig.api-strict.json +16 -0
  226. package/tsconfig.json +48 -52
  227. package/{app/client/tsconfig.node.json → tsconfig.node.json} +25 -25
  228. package/types/global.d.ts +29 -29
  229. package/types/vitest.d.ts +8 -8
  230. package/vite.config.ts +38 -62
  231. package/vitest.config.live.ts +10 -9
  232. package/vitest.config.ts +29 -17
  233. package/app/client/README.md +0 -69
  234. package/app/client/SIMPLIFICATION.md +0 -140
  235. package/app/client/frontend-only.ts +0 -12
  236. package/app/client/src/live/FileUploadExample.tsx +0 -359
  237. package/app/client/src/live/MinimalLiveClock.tsx +0 -47
  238. package/app/client/src/live/QuickUploadTest.tsx +0 -193
  239. package/app/client/tsconfig.app.json +0 -45
  240. package/app/client/tsconfig.json +0 -7
  241. package/app/client/zustand-setup.md +0 -65
  242. package/app/server/backend-only.ts +0 -18
  243. package/app/server/live/LiveClockComponent.ts +0 -215
  244. package/app/server/live/LiveFileUploadComponent.ts +0 -77
  245. package/app/server/routes/env-test.ts +0 -110
  246. package/core/client/hooks/index.ts +0 -7
  247. package/core/client/hooks/useHybridLiveComponent.ts +0 -685
  248. package/core/client/hooks/useTypedLiveComponent.ts +0 -133
  249. package/core/client/hooks/useWebSocket.ts +0 -361
  250. package/core/config/env.ts +0 -546
  251. package/core/config/loader.ts +0 -522
  252. package/core/config/runtime-config.ts +0 -327
  253. package/core/config/validator.ts +0 -540
  254. package/core/server/backend-entry.ts +0 -51
  255. package/core/server/standalone.ts +0 -106
  256. package/core/utils/regenerate-files.ts +0 -69
  257. package/fluxstack.config.ts +0 -354
@@ -1,140 +0,0 @@
1
- # 🎨 FluxStack Client - Simplified Version
2
-
3
- This is a **simplified, single-page version** of the FluxStack client, inspired by the clean and modern design of Vite's landing page.
4
-
5
- ## 🚀 What Changed?
6
-
7
- ### ✅ **Kept (Essential)**
8
- - ✅ **Eden Treaty** - Core type-safe API client
9
- - ✅ **React 19** - Modern React with hooks
10
- - ✅ **Vite 7** - Lightning-fast dev server
11
- - ✅ **TailwindCSS** - Utility-first styling
12
- - ✅ **TypeScript** - Full type safety
13
- - ✅ **react-icons** - Icon library
14
-
15
- ### ❌ **Removed (Complexity)**
16
- - ❌ **React Router** - No more multi-page routing
17
- - ❌ **Zustand** - Removed complex state management (using simple `useState`)
18
- - ❌ **Multiple Pages** - Consolidated into single page (Overview, Demo, HybridLive, ApiDocs, CryptoAuth)
19
- - ❌ **Complex Error System** - Simplified error handling
20
- - ❌ **Navigation System** - No more tabs and complex navigation
21
- - ❌ **Detailed API Status Section** - Replaced with simple badge
22
- - ❌ **Complex Live Component UIs** - Simplified to minimal clock display
23
-
24
- ### ✅ **Kept (Advanced Features)**
25
- - ✅ **LiveComponents** - Live Clock provido via LiveComponent
26
- - ✅ **LiveComponentsProvider** - Full real-time capabilities maintained
27
- - ✅ **Hybrid Live Component** - Clock synced with server in real-time
28
-
29
- ## 📊 Comparison
30
-
31
- | Metric | Before | After | Reduction |
32
- |--------|--------|-------|-----------|
33
- | **Files** | 43 | ~10 | **-76%** |
34
- | **Components** | 11 | 2 | **-82%** |
35
- | **Pages** | 5 | 1 | **-80%** |
36
- | **Dependencies** | 27 | 19 | **-30%** |
37
- | **Lines in App.tsx** | 331 | 213 | **-36%** |
38
- | **Live Components** | 6 complex | 1 minimal | **-83%** |
39
-
40
- ## 🎯 What Does It Show?
41
-
42
- The simplified client demonstrates:
43
-
44
- 1. **🎨 Minimalist Design** - Clean, centered design inspired by Next.js, React, and Vite
45
- 2. **⚡ Simple API Status** - Single badge showing API online/offline
46
- 3. **🚀 Core Features** - 4 feature cards highlighting main capabilities
47
- 4. **🕐 Live Clock** - Real LiveComponent synced with server in real-time
48
- 5. **📖 Quick Actions** - Direct links to API Docs, GitHub, and API Demo
49
- 6. **🔥 Clean but Powerful** - Minimalist UI with full real-time capabilities
50
-
51
- ## 📝 Structure
52
-
53
- ```
54
- app/client/src/
55
- ├── App.tsx # Single-page application (213 lines)
56
- │ # - AppContent component (main UI)
57
- │ # - MinimalLiveClock component (LiveComponent)
58
- │ # - LiveComponentsProvider wrapper
59
- ├── main.tsx # Entry point (simplified)
60
- ├── index.css # Minimal global styles
61
- ├── vite-env.d.ts # Vite type definitions
62
- ├── assets/ # Static assets
63
- │ └── react.svg # React logo
64
- └── lib/ # Core utilities
65
- ├── eden-api.ts # Eden Treaty API client
66
- └── errors.ts # Error handling utilities
67
- ```
68
-
69
- **Total files in src/**: 6 core files (vs 43+ before)
70
-
71
- ## 🎨 Design Philosophy
72
-
73
- Inspired by **Next.js, React, and Vite landing pages**:
74
- - Everything centered vertically and horizontally
75
- - Large animated logo (fire icon with pulse animation)
76
- - Minimal text, maximum impact
77
- - Simple API status badge (online/offline)
78
- - 4 feature cards in responsive grid
79
- - **Live Clock via LiveComponent** - Real-time sync with server
80
- - Clean action buttons at bottom
81
- - No background blob animations (clean and fast)
82
- - Mobile-first responsive design
83
- - **Full Live Components support** - Maintains advanced real-time features
84
-
85
- ## 🔧 How to Use
86
-
87
- ```bash
88
- # Start development server (backend + frontend)
89
- bun run dev
90
-
91
- # Frontend only
92
- bun run dev:frontend
93
-
94
- # Backend only
95
- bun run dev:backend
96
- ```
97
-
98
- The page will automatically show:
99
- - ✅ **Green badge** - Backend is running and healthy
100
- - ⚠️ **Yellow badge** - Checking backend status
101
- - ❌ **Red badge** - Backend is offline
102
-
103
- ## 🎯 When to Use This Version?
104
-
105
- **Use this ultra-simplified version when:**
106
- - You want the cleanest possible presentation
107
- - You're showcasing FluxStack to newcomers or investors
108
- - You need a professional landing page
109
- - You want maximum simplicity (like Next.js/React/Vite)
110
- - You prefer minimalism over features
111
- - You want fast loading and minimal JavaScript
112
-
113
- **Use the full version when:**
114
- - You need multiple pages/routes
115
- - You require complex state management
116
- - You want real-time features (WebSocket)
117
- - You need complete demos (CRUD, Auth, etc.)
118
- - You're building a full application with all features
119
-
120
- ## 💡 Future Enhancements (Optional)
121
-
122
- If you want to extend this simplified version, consider adding:
123
- - [ ] Simple counter demo using Eden Treaty
124
- - [ ] User CRUD with minimal UI
125
- - [ ] Dark/Light theme toggle
126
- - [ ] Smooth scroll to sections
127
- - [ ] More feature cards
128
-
129
- ## 📚 References
130
-
131
- - [FluxStack Documentation](../../ai-context/)
132
- - [Eden Treaty Guide](../../ai-context/development/eden-treaty-guide.md)
133
- - [Vite Documentation](https://vite.dev)
134
- - [React Documentation](https://react.dev)
135
-
136
- ---
137
-
138
- **🎯 Goal**: Provide a clean, simple, and beautiful client that showcases FluxStack's core value proposition without overwhelming complexity.
139
-
140
- **Made with ❤️ by FluxStack Team**
@@ -1,12 +0,0 @@
1
- // Frontend standalone entry point
2
- import { startFrontendOnly } from "@/core/client/standalone"
3
-
4
- // Configuração para frontend standalone
5
- const frontendConfig = {
6
- clientPath: "app/client",
7
- vitePort: (globalThis as any).process?.env?.FRONTEND_PORT || 5173,
8
- apiUrl: (globalThis as any).process?.env?.API_URL || "http://localhost:3001"
9
- }
10
-
11
- // Iniciar apenas o frontend
12
- startFrontendOnly(frontendConfig)
@@ -1,359 +0,0 @@
1
- // 📤 File Upload Example - Demonstrates chunked file upload with Live Components
2
- import { useState, useRef } from 'react'
3
- import { useTypedLiveComponent, useChunkedUpload, useLiveComponents } from '@/core/client'
4
-
5
- // Import component type DIRECTLY from backend - full type inference!
6
- import type { LiveFileUploadComponent } from '@/server/live/LiveFileUploadComponent'
7
-
8
- export function FileUploadExample() {
9
- const fileInputRef = useRef<HTMLInputElement>(null)
10
- const [selectedFile, setSelectedFile] = useState<File | null>(null)
11
-
12
- // Get sendMessageAndWait from LiveComponents context
13
- const { sendMessageAndWait } = useLiveComponents()
14
-
15
- // Setup Live Component with full type inference
16
- const {
17
- state,
18
- call,
19
- componentId,
20
- connected
21
- } = useTypedLiveComponent<LiveFileUploadComponent>('LiveFileUpload', {
22
- uploadedFiles: [],
23
- maxFiles: 10
24
- })
25
-
26
- // Setup Chunked Upload Hook with Adaptive Chunking
27
- const {
28
- uploading,
29
- progress,
30
- error: uploadError,
31
- uploadFile,
32
- cancelUpload,
33
- reset: resetUpload,
34
- bytesUploaded,
35
- totalBytes
36
- } = useChunkedUpload(componentId || '', {
37
- chunkSize: 64 * 1024, // 64KB initial chunk size
38
- maxFileSize: 500 * 1024 * 1024, // 500MB max (aceita qualquer arquivo)
39
- allowedTypes: [], // Aceita todos os tipos de arquivo
40
- sendMessageAndWait,
41
-
42
- // Enable Adaptive Chunking for optimal upload speed
43
- adaptiveChunking: true,
44
- adaptiveConfig: {
45
- minChunkSize: 16 * 1024, // 16KB minimum
46
- maxChunkSize: 512 * 1024, // 512KB maximum (safer for web)
47
- initialChunkSize: 64 * 1024, // 64KB start
48
- targetLatency: 200, // Target 200ms per chunk
49
- adjustmentFactor: 1.5, // Moderate adjustment
50
- measurementWindow: 3 // Measure last 3 chunks
51
- },
52
-
53
- onProgress: (progress, uploaded, total) => {
54
- console.log(`📤 Upload progress: ${progress.toFixed(1)}% (${uploaded}/${total} bytes)`)
55
- },
56
-
57
- onComplete: async (response) => {
58
- console.log('✅ Upload complete:', response)
59
-
60
- // Notify the Live Component about the successful upload
61
- if (selectedFile && response.fileUrl) {
62
- await call('onFileUploaded', {
63
- filename: selectedFile.name,
64
- fileUrl: response.fileUrl
65
- })
66
- }
67
-
68
- // Reset state
69
- setSelectedFile(null)
70
- resetUpload()
71
- if (fileInputRef.current) {
72
- fileInputRef.current.value = ''
73
- }
74
- },
75
-
76
- onError: (error) => {
77
- console.error('❌ Upload error:', error)
78
- }
79
- })
80
-
81
- const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
82
- const file = e.target.files?.[0]
83
- if (file) {
84
- setSelectedFile(file)
85
- resetUpload()
86
- }
87
- }
88
-
89
- const handleUpload = async () => {
90
- if (!selectedFile) return
91
- await uploadFile(selectedFile)
92
- }
93
-
94
- const handleRemoveFile = async (fileId: string) => {
95
- await call('removeFile', { fileId })
96
- }
97
-
98
- const handleClearAll = async () => {
99
- await call('clearAll', {})
100
- }
101
-
102
- const formatBytes = (bytes: number): string => {
103
- if (bytes === 0) return '0 Bytes'
104
- const k = 1024
105
- const sizes = ['Bytes', 'KB', 'MB', 'GB']
106
- const i = Math.floor(Math.log(bytes) / Math.log(k))
107
- return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
108
- }
109
-
110
- const getFileIcon = (filename: string): string => {
111
- const ext = filename.toLowerCase().substring(filename.lastIndexOf('.'))
112
- const iconMap: Record<string, string> = {
113
- '.pdf': '📄',
114
- '.doc': '📝',
115
- '.docx': '📝',
116
- '.xls': '📊',
117
- '.xlsx': '📊',
118
- '.ppt': '📽️',
119
- '.pptx': '📽️',
120
- '.zip': '🗜️',
121
- '.rar': '🗜️',
122
- '.7z': '🗜️',
123
- '.jpg': '🖼️',
124
- '.jpeg': '🖼️',
125
- '.png': '🖼️',
126
- '.gif': '🖼️',
127
- '.webp': '🖼️',
128
- '.mp4': '🎥',
129
- '.avi': '🎥',
130
- '.mov': '🎥',
131
- '.mp3': '🎵',
132
- '.wav': '🎵',
133
- '.jar': '☕',
134
- '.java': '☕',
135
- '.js': '📜',
136
- '.ts': '📜',
137
- '.json': '📋',
138
- '.xml': '📋',
139
- '.txt': '📃',
140
- '.md': '📰'
141
- }
142
- return iconMap[ext] || '📎'
143
- }
144
-
145
- const isImageFile = (filename: string): boolean => {
146
- const ext = filename.toLowerCase().substring(filename.lastIndexOf('.'))
147
- return ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp'].includes(ext)
148
- }
149
-
150
- if (!connected) {
151
- return (
152
- <div className="p-6 bg-yellow-50 border border-yellow-200 rounded-lg">
153
- <p className="text-yellow-800">🔌 Connecting to Live Components...</p>
154
- </div>
155
- )
156
- }
157
-
158
- const remainingSlots = state.maxFiles - state.uploadedFiles.length
159
-
160
- return (
161
- <div className="max-w-4xl mx-auto p-6">
162
- <div className="bg-white rounded-lg shadow-lg">
163
- {/* Header */}
164
- <div className="p-6 border-b border-gray-200">
165
- <h2 className="text-2xl font-bold text-gray-900">
166
- 📤 Universal File Upload
167
- </h2>
168
- <p className="mt-2 text-gray-600">
169
- Upload any type of file with real-time progress tracking and adaptive chunking
170
- </p>
171
- </div>
172
-
173
- {/* Upload Section */}
174
- <div className="p-6 border-b border-gray-200">
175
- <div className="space-y-4">
176
- {/* File Input */}
177
- <div>
178
- <label className="block text-sm font-medium text-gray-700 mb-2">
179
- Select Any File
180
- </label>
181
- <input
182
- ref={fileInputRef}
183
- type="file"
184
- onChange={handleFileSelect}
185
- disabled={uploading || remainingSlots === 0}
186
- className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100 disabled:opacity-50"
187
- />
188
- <p className="mt-1 text-xs text-gray-500">
189
- Maximum file size: 500 MB • All file types supported
190
- </p>
191
- </div>
192
-
193
- {/* Selected File Info */}
194
- {selectedFile && !uploading && (
195
- <div className="p-4 bg-gray-50 rounded-lg">
196
- <p className="text-sm text-gray-700">
197
- <strong>Selected:</strong> {getFileIcon(selectedFile.name)} {selectedFile.name} ({formatBytes(selectedFile.size)})
198
- </p>
199
- </div>
200
- )}
201
-
202
- {/* Upload Progress */}
203
- {uploading && (
204
- <div className="space-y-2">
205
- <div className="flex justify-between text-sm text-gray-600">
206
- <span>Uploading {selectedFile?.name}...</span>
207
- <span>{progress.toFixed(1)}%</span>
208
- </div>
209
- <div className="w-full bg-gray-200 rounded-full h-2.5">
210
- <div
211
- className="bg-blue-600 h-2.5 rounded-full transition-all duration-300"
212
- style={{ width: `${progress}%` }}
213
- />
214
- </div>
215
- <p className="text-xs text-gray-500">
216
- {formatBytes(bytesUploaded)} / {formatBytes(totalBytes)}
217
- </p>
218
- </div>
219
- )}
220
-
221
- {/* Error Display */}
222
- {uploadError && (
223
- <div className="p-4 bg-red-50 border border-red-200 rounded-lg">
224
- <p className="text-sm text-red-800">❌ {uploadError}</p>
225
- </div>
226
- )}
227
-
228
- {/* Action Buttons */}
229
- <div className="flex gap-2">
230
- <button
231
- onClick={handleUpload}
232
- disabled={!selectedFile || uploading || remainingSlots === 0}
233
- className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed font-medium"
234
- >
235
- {uploading ? '⏳ Uploading...' : '📤 Upload'}
236
- </button>
237
-
238
- {uploading && (
239
- <button
240
- onClick={cancelUpload}
241
- className="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 font-medium"
242
- >
243
- ❌ Cancel
244
- </button>
245
- )}
246
-
247
- {state.uploadedFiles.length > 0 && (
248
- <button
249
- onClick={handleClearAll}
250
- disabled={uploading}
251
- className="px-4 py-2 bg-gray-600 text-white rounded-md hover:bg-gray-700 disabled:opacity-50 font-medium ml-auto"
252
- >
253
- 🗑️ Clear All
254
- </button>
255
- )}
256
- </div>
257
-
258
- {/* Slots Info */}
259
- <div className="text-sm text-gray-600">
260
- {remainingSlots > 0 ? (
261
- <span>✅ {remainingSlots} upload slot(s) remaining</span>
262
- ) : (
263
- <span className="text-red-600">⚠️ Maximum files reached</span>
264
- )}
265
- </div>
266
- </div>
267
- </div>
268
-
269
- {/* Uploaded Files Grid */}
270
- <div className="p-6">
271
- <h3 className="text-lg font-semibold text-gray-900 mb-4">
272
- Uploaded Files ({state.uploadedFiles.length}/{state.maxFiles})
273
- </h3>
274
-
275
- {state.uploadedFiles.length === 0 ? (
276
- <div className="text-center py-12 bg-gray-50 rounded-lg">
277
- <p className="text-gray-500">No files uploaded yet</p>
278
- </div>
279
- ) : (
280
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
281
- {state.uploadedFiles.map((file) => (
282
- <div
283
- key={file.id}
284
- className="relative bg-white border border-gray-200 rounded-lg overflow-hidden hover:shadow-lg transition-shadow"
285
- >
286
- {/* File Preview */}
287
- <div className="aspect-video bg-gray-100 flex items-center justify-center">
288
- {isImageFile(file.filename) ? (
289
- <img
290
- src={file.url}
291
- alt={file.filename}
292
- className="max-w-full max-h-full object-contain"
293
- onError={(e) => {
294
- const target = e.target as HTMLImageElement
295
- target.style.display = 'none'
296
- target.parentElement!.innerHTML = `<div class="text-6xl">${getFileIcon(file.filename)}</div>`
297
- }}
298
- />
299
- ) : (
300
- <div className="text-6xl">{getFileIcon(file.filename)}</div>
301
- )}
302
- </div>
303
-
304
- {/* Info */}
305
- <div className="p-3">
306
- <p className="text-sm font-medium text-gray-900 truncate" title={file.filename}>
307
- {file.filename}
308
- </p>
309
- <p className="text-xs text-gray-500">
310
- {new Date(file.uploadedAt).toLocaleString()}
311
- </p>
312
- <a
313
- href={file.url}
314
- target="_blank"
315
- rel="noopener noreferrer"
316
- className="text-xs text-blue-600 hover:underline mt-1 inline-block"
317
- >
318
- Download
319
- </a>
320
- </div>
321
-
322
- {/* Remove Button */}
323
- <button
324
- onClick={() => handleRemoveFile(file.id)}
325
- className="absolute top-2 right-2 p-2 bg-red-600 text-white rounded-full hover:bg-red-700 transition-colors shadow-lg"
326
- title="Remove file"
327
- >
328
- <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
329
- <path
330
- fillRule="evenodd"
331
- d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
332
- clipRule="evenodd"
333
- />
334
- </svg>
335
- </button>
336
- </div>
337
- ))}
338
- </div>
339
- )}
340
- </div>
341
- </div>
342
-
343
- {/* Technical Info */}
344
- <div className="mt-6 p-4 bg-gray-50 rounded-lg border border-gray-200">
345
- <h4 className="font-semibold text-gray-900 mb-2">📋 Technical Details</h4>
346
- <ul className="text-sm text-gray-600 space-y-1">
347
- <li>✅ <strong>Adaptive Chunking:</strong> Enabled (16KB - 512KB)</li>
348
- <li>✅ <strong>Initial Chunk Size:</strong> 64KB</li>
349
- <li>✅ <strong>Max File Size:</strong> 500MB</li>
350
- <li>✅ <strong>Allowed Types:</strong> All file types supported</li>
351
- <li>✅ <strong>Real-time Progress:</strong> Shows bytes uploaded and percentage</li>
352
- <li>✅ <strong>State Sync:</strong> Uploaded files synced via Live Component</li>
353
- <li>✅ <strong>Component ID:</strong> {componentId || 'Not connected'}</li>
354
- <li>🚀 <strong>Optimization:</strong> Chunk size adjusts based on connection speed</li>
355
- </ul>
356
- </div>
357
- </div>
358
- )
359
- }
@@ -1,47 +0,0 @@
1
- // 🔥 MinimalLiveClock - Live Component
2
- import { useTypedLiveComponent } from '@/core/client';
3
-
4
- // Import component type DIRECTLY from backend - full type inference!
5
- import type { LiveClockComponent } from '@/server/live/LiveClockComponent';
6
-
7
- export function MinimalLiveClock() {
8
- const { state, setValue } = useTypedLiveComponent<LiveClockComponent>(
9
- 'LiveClock',
10
- {
11
- currentTime: "Loading...",
12
- timeZone: "America/Sao_Paulo",
13
- format: "12h",
14
- showSeconds: true,
15
- showDate: true,
16
- lastSync: new Date(),
17
- serverUptime: 0,
18
- },
19
- {
20
- // Called when WebSocket connects (component not mounted yet - can't use setValue)
21
- onConnect: () => {
22
- console.log('onConnect called - WebSocket connected')
23
- },
24
- // Called after fresh mount (no prior state)
25
- onMount: () => {
26
- console.log('onMount called - changing format to 12h')
27
- setValue('format', '12h')
28
- },
29
- // Called after successful rehydration (restoring prior state)
30
- onRehydrate: () => {
31
- console.log('onRehydrate called - keeping format 24h')
32
- setValue('format', '24h')
33
- }
34
- }
35
- )
36
-
37
- return (
38
- <div className="bg-gradient-to-br from-blue-500/10 to-purple-500/10 rounded-xl p-4 border border-blue-400/20">
39
- <div className="text-4xl font-mono font-bold text-white text-center tracking-wider">
40
- {state.currentTime}
41
- </div>
42
- <div className="text-center mt-2">
43
- <span className="text-xs text-gray-400">{state.timeZone} ({state.format})</span>
44
- </div>
45
- </div>
46
- )
47
- }