create-fluxstack 1.10.1 → 1.12.0

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 +242 -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 +285 -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
@@ -0,0 +1,108 @@
1
+ import type { ReactNode } from 'react'
2
+ import { BackButton } from '../components/BackButton'
3
+
4
+ export function ApiTestPage({
5
+ apiResponse,
6
+ isLoading,
7
+ onHealth,
8
+ onGetUsers,
9
+ onCreateUser
10
+ }: {
11
+ apiResponse: string
12
+ isLoading: boolean
13
+ onHealth: () => void
14
+ onGetUsers: () => void
15
+ onCreateUser: () => void
16
+ }) {
17
+ return (
18
+ <div className="container mx-auto px-4 py-8 max-w-4xl">
19
+ <div className="flex items-center gap-4 mb-8">
20
+ <BackButton />
21
+ <h1 className="text-3xl font-bold bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">
22
+ Eden Treaty API Test
23
+ </h1>
24
+ </div>
25
+
26
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
27
+ <ActionCard
28
+ icon="🏥"
29
+ title="GET /api/health"
30
+ subtitle="Health Check"
31
+ onClick={onHealth}
32
+ disabled={isLoading}
33
+ className="bg-emerald-500/20 border-emerald-500/30 text-emerald-300 hover:bg-emerald-500/30"
34
+ />
35
+ <ActionCard
36
+ icon="👥"
37
+ title="GET /api/users"
38
+ subtitle="List Users"
39
+ onClick={onGetUsers}
40
+ disabled={isLoading}
41
+ className="bg-blue-500/20 border-blue-500/30 text-blue-300 hover:bg-blue-500/30"
42
+ />
43
+ <ActionCard
44
+ icon="➕"
45
+ title="POST /api/users"
46
+ subtitle="Create User"
47
+ onClick={onCreateUser}
48
+ disabled={isLoading}
49
+ className="bg-purple-500/20 border-purple-500/30 text-purple-300 hover:bg-purple-500/30"
50
+ />
51
+ </div>
52
+
53
+ <div className="bg-black/40 backdrop-blur-sm border border-white/10 rounded-2xl p-6">
54
+ <div className="flex items-center justify-between mb-4">
55
+ <h2 className="text-lg font-semibold text-white">Response</h2>
56
+ {isLoading && (
57
+ <div className="flex items-center gap-2 text-yellow-400">
58
+ <div className="w-4 h-4 border-2 border-yellow-400 border-t-transparent rounded-full animate-spin"></div>
59
+ Loading...
60
+ </div>
61
+ )}
62
+ </div>
63
+ <pre className="bg-black/60 rounded-xl p-4 overflow-auto max-h-96 text-sm font-mono">
64
+ <code className="text-green-400">
65
+ {apiResponse || '// Click a button above to test the API\\n// Type inference works automatically!'}
66
+ </code>
67
+ </pre>
68
+ </div>
69
+
70
+ <div className="mt-8 bg-white/5 border border-white/10 rounded-xl p-6">
71
+ <h3 className="text-lg font-semibold text-white mb-3">How it works</h3>
72
+ <div className="text-gray-400 text-sm space-y-2">
73
+ <p>OK <code className="text-purple-400">api.health.get()</code> - Full type inference from server</p>
74
+ <p>OK <code className="text-purple-400">api.users.post({'{ name, email }'})</code> - Request body is typed</p>
75
+ <p>OK <code className="text-purple-400">{'{ data, error }'}</code> - Response is typed automatically</p>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ )
80
+ }
81
+
82
+ function ActionCard({
83
+ icon,
84
+ title,
85
+ subtitle,
86
+ onClick,
87
+ disabled,
88
+ className
89
+ }: {
90
+ icon: ReactNode
91
+ title: string
92
+ subtitle: string
93
+ onClick: () => void
94
+ disabled: boolean
95
+ className: string
96
+ }) {
97
+ return (
98
+ <button
99
+ onClick={onClick}
100
+ disabled={disabled}
101
+ className={`px-6 py-4 border rounded-xl font-medium transition-all disabled:opacity-50 ${className}`}
102
+ >
103
+ <div className="text-2xl mb-2">{icon}</div>
104
+ <div>{title}</div>
105
+ <div className="text-xs opacity-70 mt-1">{subtitle}</div>
106
+ </button>
107
+ )
108
+ }
@@ -0,0 +1,76 @@
1
+ import { Link } from 'react-router'
2
+ import { FaFire } from 'react-icons/fa'
3
+
4
+ export function HomePage({ apiStatus }: { apiStatus: 'checking' | 'online' | 'offline' }) {
5
+ return (
6
+ <div className="flex flex-col items-center justify-center min-h-[calc(100vh-72px)] px-6 text-center">
7
+ <div className="mb-8 animate-pulse-slow">
8
+ <FaFire className="text-8xl text-orange-500 drop-shadow-2xl" />
9
+ </div>
10
+
11
+ <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">
12
+ FluxStack
13
+ </h1>
14
+
15
+ <p className="text-xl md:text-2xl text-gray-300 mb-8 max-w-2xl">
16
+ Full-stack TypeScript framework with{' '}
17
+ <span className="text-purple-400 font-semibold">Bun</span>,{' '}
18
+ <span className="text-blue-400 font-semibold">Elysia</span>, and{' '}
19
+ <span className="text-cyan-400 font-semibold">React</span>
20
+ </p>
21
+
22
+ <div className="mb-12">
23
+ <div className={`inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium transition-all ${
24
+ apiStatus === 'online'
25
+ ? 'bg-emerald-500/20 text-emerald-300 border border-emerald-500/30'
26
+ : apiStatus === 'offline'
27
+ ? 'bg-red-500/20 text-red-300 border border-red-500/30'
28
+ : 'bg-yellow-500/20 text-yellow-300 border border-yellow-500/30'
29
+ }`}>
30
+ <div className={`w-2 h-2 rounded-full ${
31
+ apiStatus === 'online' ? 'bg-emerald-400' : apiStatus === 'offline' ? 'bg-red-400' : 'bg-yellow-400'
32
+ }`}></div>
33
+ <span>{apiStatus === 'checking' ? 'Checking API...' : apiStatus === 'online' ? 'API Online' : 'API Offline'}</span>
34
+ </div>
35
+ </div>
36
+
37
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12 max-w-4xl">
38
+ <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
39
+ <div className="text-3xl mb-3">⚡</div>
40
+ <h3 className="text-lg font-semibold text-white mb-2">Ultra Rápido</h3>
41
+ <p className="text-gray-400 text-sm">Bun runtime 3x mais rápido que Node.js</p>
42
+ </div>
43
+
44
+ <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
45
+ <div className="text-3xl mb-3">🔒</div>
46
+ <h3 className="text-lg font-semibold text-white mb-2">Type Safe</h3>
47
+ <p className="text-gray-400 text-sm">Eden Treaty com inferência automática</p>
48
+ </div>
49
+
50
+ <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-all">
51
+ <div className="text-3xl mb-3">🔥</div>
52
+ <h3 className="text-lg font-semibold text-white mb-2">Live Components</h3>
53
+ <p className="text-gray-400 text-sm">Estado reativo no servidor estilo Livewire</p>
54
+ </div>
55
+ </div>
56
+
57
+ <div className="mt-4 text-gray-500 text-sm">
58
+ Use a navegação no topo para acessar as demos.
59
+ </div>
60
+
61
+ <div className="mt-16 text-gray-500 text-sm">
62
+ <p>Desenvolvido com ❤️ usando TypeScript</p>
63
+ </div>
64
+
65
+ <style>{`
66
+ @keyframes pulse-slow {
67
+ 0%, 100% { opacity: 1; }
68
+ 50% { opacity: 0.8; }
69
+ }
70
+ .animate-pulse-slow {
71
+ animation: pulse-slow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
72
+ }
73
+ `}</style>
74
+ </div>
75
+ )
76
+ }
package/app/server/app.ts CHANGED
@@ -2,8 +2,7 @@
2
2
  * 🎯 Application Instance - Single Source of Truth
3
3
  *
4
4
  * This instance is used by:
5
- * - index.ts (full-stack mode)
6
- * - backend-only.ts (backend standalone mode)
5
+ * - index.ts (full-stack & backend-only modes via FLUXSTACK_MODE env)
7
6
  * - Eden Treaty client (type inference)
8
7
  *
9
8
  * This ensures that the type exported for Eden Treaty is exactly
@@ -12,13 +11,11 @@
12
11
 
13
12
  import { Elysia } from "elysia"
14
13
  import { apiRoutes } from "./routes"
15
- import { envTestRoute } from "./routes/env-test"
16
14
 
17
15
  /**
18
16
  * Main application instance with all routes registered
19
17
  */
20
18
  export const appInstance = new Elysia()
21
- .use(envTestRoute) // Environment test/debug endpoint
22
19
  .use(apiRoutes) // Main application routes
23
20
 
24
21
  // Export the type correctly for Eden Treaty
@@ -1,6 +1,5 @@
1
- import type { CreateUserRequest } from '@/app/shared/types'
1
+ import type { CreateUserRequest } from '@app/shared/types'
2
2
 
3
- // User type
4
3
  export interface User {
5
4
  id: number
6
5
  name: string
@@ -8,88 +7,81 @@ export interface User {
8
7
  createdAt: Date
9
8
  }
10
9
 
11
- // In-memory storage for users (for testing purposes)
12
- let users: User[] = []
13
- let nextId = 1
14
-
10
+ /**
11
+ * In-memory user store for demonstration purposes.
12
+ * Replace with a real database (e.g. Drizzle, Prisma) for production use.
13
+ */
15
14
  export class UsersController {
16
- /**
17
- * Get all users
18
- */
15
+ private static users: User[] = []
16
+ private static nextId = 1
17
+
19
18
  static async getUsers() {
20
19
  return {
21
- users
20
+ success: true as const,
21
+ users: this.users,
22
+ count: this.users.length
22
23
  }
23
24
  }
24
25
 
25
- /**
26
- * Get user by ID
27
- */
28
26
  static async getUserById(id: number) {
29
- const user = users.find(u => u.id === id)
27
+ const user = this.users.find(u => u.id === id)
30
28
  if (!user) {
31
- return null
29
+ return {
30
+ success: false as const,
31
+ error: 'Usuario nao encontrado'
32
+ }
33
+ }
34
+ return {
35
+ success: true as const,
36
+ user
32
37
  }
33
- return { user }
34
38
  }
35
39
 
36
- /**
37
- * Create a new user
38
- */
39
40
  static async createUser(data: CreateUserRequest) {
40
- // Check for duplicate email
41
- const existingUser = users.find(u => u.email === data.email)
41
+ const existingUser = this.users.find(u => u.email === data.email)
42
42
  if (existingUser) {
43
43
  return {
44
- success: false,
45
- message: 'Email está em uso'
44
+ success: false as const,
45
+ error: 'Email ja esta em uso'
46
46
  }
47
47
  }
48
48
 
49
- // Create new user
50
49
  const newUser: User = {
51
- id: nextId++,
50
+ id: this.nextId++,
52
51
  name: data.name,
53
52
  email: data.email,
54
53
  createdAt: new Date()
55
54
  }
56
55
 
57
- users.push(newUser)
56
+ this.users.push(newUser)
58
57
 
59
58
  return {
60
- success: true,
61
- user: newUser
59
+ success: true as const,
60
+ user: newUser,
61
+ message: 'Usuario criado com sucesso'
62
62
  }
63
63
  }
64
64
 
65
- /**
66
- * Delete user by ID
67
- */
68
65
  static async deleteUser(id: number) {
69
- const userIndex = users.findIndex(u => u.id === id)
66
+ const userIndex = this.users.findIndex(u => u.id === id)
70
67
 
71
68
  if (userIndex === -1) {
72
69
  return {
73
- success: false,
74
- message: 'Usuário não encontrado'
70
+ success: false as const,
71
+ message: 'Usuario nao encontrado'
75
72
  }
76
73
  }
77
74
 
78
- const deletedUser = users[userIndex]
79
- users.splice(userIndex, 1)
75
+ this.users.splice(userIndex, 1)
80
76
 
81
77
  return {
82
- success: true,
83
- user: deletedUser,
84
- message: 'Usuário deletado com sucesso'
78
+ success: true as const,
79
+ message: 'Usuario deletado com sucesso'
85
80
  }
86
81
  }
87
82
 
88
- /**
89
- * Reset users array for testing purposes
90
- */
91
83
  static resetForTesting() {
92
- users = []
93
- nextId = 1
84
+ this.users = []
85
+ this.nextId = 1
94
86
  }
95
87
  }
@@ -1,42 +1,32 @@
1
1
  /**
2
2
  * FluxStack Application Server Entry Point
3
+ *
4
+ * Modos (via FLUXSTACK_MODE ou appConfig.mode):
5
+ * - full-stack: Backend + Vite + LiveComponents (padrão)
6
+ * - backend-only: Backend + LiveComponents (sem Vite)
7
+ *
8
+ * Frontend-only roda direto do core (core/client/standalone-entry.ts)
9
+ *
10
+ * 📖 Docs: ai-context/reference/plugin-security.md
3
11
  */
4
12
 
5
- // Core
6
- import { FluxStackFramework } from "@/core/server"
7
- import { helpers } from "@/core/utils/env"
8
- import { appConfig } from "@/config/app.config"
9
- import { serverConfig } from "@/config/server.config"
13
+ import { FluxStackFramework } from "@core/server"
14
+ import { vitePlugin } from "@core/plugins/built-in/vite"
15
+ import { swaggerPlugin } from "@core/plugins/built-in/swagger"
16
+ import { liveComponentsPlugin } from "@core/server/live/websocket-plugin"
17
+ import { appInstance } from "@server/app"
18
+ import { appConfig } from "@config"
10
19
 
11
- // Plugins
12
- import { vitePlugin, swaggerPlugin, liveComponentsPlugin, staticFilesPlugin } from "@/core/server"
13
- import cryptoAuthPlugin from "@/plugins/crypto-auth"
14
- // Routes & Components
15
- import { appInstance } from "./app"
16
-
17
- // Server
18
- const app = new FluxStackFramework({
19
- server: {
20
- ...serverConfig.server,
21
- cors: serverConfig.cors,
22
- middleware: []
23
- },
24
- app: {
25
- name: appConfig.name,
26
- version: appConfig.version
27
- },
28
- client: {
29
- port: serverConfig.server.backendPort,
30
- proxy: { target: helpers.getServerUrl() },
31
- build: { sourceMaps: false, minify: false, target: 'es2020', outDir: 'dist' }
32
- }
33
- })
34
- .use(cryptoAuthPlugin)
35
- .use(vitePlugin)
36
- .use(staticFilesPlugin)
37
- .use(liveComponentsPlugin)
38
- .routes(appInstance)
20
+ const framework = new FluxStackFramework()
39
21
  .use(swaggerPlugin)
40
- .listen()
22
+ .use(liveComponentsPlugin)
23
+
24
+ // Vite apenas em full-stack
25
+ if (appConfig.mode !== 'backend-only') {
26
+ framework.use(vitePlugin)
27
+ }
28
+
29
+ framework.routes(appInstance)
30
+ await framework.listen()
41
31
 
42
- export type App = typeof app
32
+ export const app = framework
@@ -0,0 +1,77 @@
1
+ // LiveChat - Chat compartilhado por sala
2
+
3
+ import { LiveComponent, type FluxStackWebSocket } from '@core/types/types'
4
+
5
+ // Componente Cliente (Ctrl+Click para navegar)
6
+ import type { ChatDemo as _Client } from '@client/src/live/ChatDemo'
7
+
8
+ export type ChatMessage = {
9
+ id: string
10
+ user: string
11
+ text: string
12
+ timestamp: number
13
+ }
14
+
15
+ export class LiveChat extends LiveComponent<typeof LiveChat.defaultState> {
16
+ static componentName = 'LiveChat'
17
+ static defaultState = {
18
+ messages: [] as ChatMessage[]
19
+ }
20
+ protected roomType = 'chat'
21
+ private maxMessages = 50
22
+ private static roomHistory = new Map<string, ChatMessage[]>()
23
+
24
+ constructor(initialState: Partial<typeof LiveChat.defaultState> = {}, ws: FluxStackWebSocket, options?: { room?: string; userId?: string }) {
25
+ super(initialState, ws, options)
26
+
27
+ this.onRoomEvent<ChatMessage>('NEW_MESSAGE', (message) => {
28
+ this.addMessage(message)
29
+ })
30
+
31
+ if (this.room) {
32
+ const history = LiveChat.roomHistory.get(this.room) || []
33
+ if (history.length > 0) {
34
+ this.setState({ messages: history })
35
+ }
36
+ }
37
+ }
38
+
39
+ private addMessage(message: ChatMessage) {
40
+ const next = [...this.state.messages, message].slice(-this.maxMessages)
41
+ if (this.room) {
42
+ LiveChat.roomHistory.set(this.room, next)
43
+ }
44
+ this.setState({ messages: next })
45
+ }
46
+
47
+ async sendMessage(payload: { user: string; text: string }) {
48
+ const text = payload.text?.trim()
49
+ const user = payload.user?.trim() || 'anonymous'
50
+
51
+ if (!text) {
52
+ throw new Error('Message cannot be empty')
53
+ }
54
+
55
+ if (text.length > 500) {
56
+ throw new Error('Message too long')
57
+ }
58
+
59
+ const message: ChatMessage = {
60
+ id: `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
61
+ user,
62
+ text,
63
+ timestamp: Date.now()
64
+ }
65
+
66
+ const next = [...this.state.messages, message].slice(-this.maxMessages)
67
+ if (this.room) {
68
+ LiveChat.roomHistory.set(this.room, next)
69
+ }
70
+
71
+ this.emitRoomEventWithState('NEW_MESSAGE', message, {
72
+ messages: next
73
+ })
74
+
75
+ return { success: true }
76
+ }
77
+ }
@@ -0,0 +1,67 @@
1
+ // LiveCounter - Contador compartilhado usando Room Events
2
+
3
+ import { LiveComponent, type FluxStackWebSocket } from '@core/types/types'
4
+
5
+ // Componente Cliente (Ctrl+Click para navegar)
6
+ import type { CounterDemo as _Client } from '@client/src/live/CounterDemo'
7
+
8
+ export class LiveCounter extends LiveComponent<typeof LiveCounter.defaultState> {
9
+ static componentName = 'LiveCounter'
10
+ static defaultState = {
11
+ count: 0,
12
+ lastUpdatedBy: null as string | null,
13
+ connectedUsers: 0
14
+ }
15
+ protected roomType = 'counter'
16
+
17
+ constructor(initialState: Partial<typeof LiveCounter.defaultState> = {}, ws: FluxStackWebSocket, options?: { room?: string; userId?: string }) {
18
+ super(initialState, ws, options)
19
+
20
+ this.onRoomEvent<{ count: number; userId: string }>('COUNT_CHANGED', (data) => {
21
+ this.setState({ count: data.count, lastUpdatedBy: data.userId })
22
+ })
23
+
24
+ this.onRoomEvent<{ connectedUsers: number }>('USER_COUNT_CHANGED', (data) => {
25
+ this.setState({ connectedUsers: data.connectedUsers })
26
+ })
27
+
28
+ this.notifyUserJoined()
29
+ }
30
+
31
+ private notifyUserJoined() {
32
+ const newCount = this.state.connectedUsers + 1
33
+ this.emitRoomEventWithState('USER_COUNT_CHANGED', { connectedUsers: newCount }, { connectedUsers: newCount })
34
+ }
35
+
36
+ async increment() {
37
+ const newCount = this.state.count + 1
38
+ this.emitRoomEventWithState('COUNT_CHANGED', { count: newCount, userId: this.userId || 'anonymous' }, {
39
+ count: newCount,
40
+ lastUpdatedBy: this.userId || 'anonymous'
41
+ })
42
+ return { success: true, count: newCount }
43
+ }
44
+
45
+ async decrement() {
46
+ const newCount = this.state.count - 1
47
+ this.emitRoomEventWithState('COUNT_CHANGED', { count: newCount, userId: this.userId || 'anonymous' }, {
48
+ count: newCount,
49
+ lastUpdatedBy: this.userId || 'anonymous'
50
+ })
51
+ return { success: true, count: newCount }
52
+ }
53
+
54
+ async reset() {
55
+ this.emitRoomEventWithState('COUNT_CHANGED', { count: 0, userId: this.userId || 'anonymous' }, {
56
+ count: 0,
57
+ lastUpdatedBy: this.userId || 'anonymous'
58
+ })
59
+ return { success: true, count: 0 }
60
+ }
61
+
62
+ destroy() {
63
+ const newCount = Math.max(0, this.state.connectedUsers - 1)
64
+ this.emitRoomEvent('USER_COUNT_CHANGED', { connectedUsers: newCount })
65
+ super.destroy()
66
+ }
67
+ }
@@ -0,0 +1,63 @@
1
+ // LiveForm - Formulário reativo com estado no servidor
2
+
3
+ import { LiveComponent } from "@core/types/types"
4
+
5
+ // Componente Cliente (Ctrl+Click para navegar)
6
+ import type { FormDemo as _Client } from '@client/src/live/FormDemo'
7
+
8
+ export class LiveForm extends LiveComponent<typeof LiveForm.defaultState> {
9
+ static componentName = 'LiveForm'
10
+ static defaultState = {
11
+ name: '',
12
+ email: '',
13
+ message: '',
14
+ submitted: false,
15
+ submittedAt: null as string | null
16
+ }
17
+
18
+ async submit() {
19
+ const { name, email, message } = this.state
20
+
21
+ if (!name || !email) {
22
+ throw new Error('Nome e email são obrigatórios')
23
+ }
24
+
25
+ console.log(`📝 Form submitted:`, { name, email, message })
26
+
27
+ this.setState({
28
+ submitted: true,
29
+ submittedAt: new Date().toISOString()
30
+ })
31
+
32
+ return {
33
+ success: true,
34
+ data: { name, email, message },
35
+ submittedAt: this.state.submittedAt
36
+ }
37
+ }
38
+
39
+ async reset() {
40
+ this.setState({
41
+ name: '',
42
+ email: '',
43
+ message: '',
44
+ submitted: false,
45
+ submittedAt: null
46
+ })
47
+
48
+ return { success: true }
49
+ }
50
+
51
+ async validate() {
52
+ const errors: Record<string, string> = {}
53
+
54
+ if (!this.state.name) errors.name = 'Nome é obrigatório'
55
+ if (!this.state.email) errors.email = 'Email é obrigatório'
56
+ else if (!this.state.email.includes('@')) errors.email = 'Email inválido'
57
+
58
+ return {
59
+ valid: Object.keys(errors).length === 0,
60
+ errors
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,32 @@
1
+ // LiveLocalCounter - Contador sem eventos de sala
2
+
3
+ import { LiveComponent } from '@core/types/types'
4
+
5
+ // Componente Cliente (Ctrl+Click para navegar)
6
+ import type { CounterDemo as _Client } from '@client/src/live/CounterDemo'
7
+
8
+ export class LiveLocalCounter extends LiveComponent<typeof LiveLocalCounter.defaultState> {
9
+ static componentName = 'LiveLocalCounter'
10
+ static defaultState = {
11
+ count: 0,
12
+ clicks: 0
13
+ }
14
+
15
+ async increment() {
16
+ this.state.count++
17
+ this.state.clicks++
18
+ return { success: true, count: this.state.count }
19
+ }
20
+
21
+ async decrement() {
22
+ this.state.count--
23
+ this.state.clicks++
24
+ return { success: true, count: this.state.count }
25
+ }
26
+
27
+ async reset() {
28
+ this.state.count = 0
29
+ this.state.clicks++
30
+ return { success: true, count: 0 }
31
+ }
32
+ }