create-fluxstack 1.9.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 (259) hide show
  1. package/.dockerignore +1 -2
  2. package/Dockerfile +8 -8
  3. package/LIVE_COMPONENTS_REVIEW.md +781 -0
  4. package/LLMD/INDEX.md +64 -0
  5. package/LLMD/MAINTENANCE.md +197 -0
  6. package/LLMD/MIGRATION.md +156 -0
  7. package/LLMD/config/.gitkeep +1 -0
  8. package/LLMD/config/declarative-system.md +268 -0
  9. package/LLMD/config/environment-vars.md +327 -0
  10. package/LLMD/config/runtime-reload.md +401 -0
  11. package/LLMD/core/.gitkeep +1 -0
  12. package/LLMD/core/build-system.md +599 -0
  13. package/LLMD/core/framework-lifecycle.md +229 -0
  14. package/LLMD/core/plugin-system.md +451 -0
  15. package/LLMD/patterns/.gitkeep +1 -0
  16. package/LLMD/patterns/anti-patterns.md +297 -0
  17. package/LLMD/patterns/project-structure.md +264 -0
  18. package/LLMD/patterns/type-safety.md +440 -0
  19. package/LLMD/reference/.gitkeep +1 -0
  20. package/LLMD/reference/cli-commands.md +250 -0
  21. package/LLMD/reference/plugin-hooks.md +357 -0
  22. package/LLMD/reference/routing.md +39 -0
  23. package/LLMD/reference/troubleshooting.md +364 -0
  24. package/LLMD/resources/.gitkeep +1 -0
  25. package/LLMD/resources/controllers.md +465 -0
  26. package/LLMD/resources/live-components.md +703 -0
  27. package/LLMD/resources/live-rooms.md +482 -0
  28. package/LLMD/resources/live-upload.md +130 -0
  29. package/LLMD/resources/plugins-external.md +617 -0
  30. package/LLMD/resources/routes-eden.md +254 -0
  31. package/README.md +37 -17
  32. package/app/client/index.html +0 -1
  33. package/app/client/src/App.tsx +109 -156
  34. package/app/client/src/components/AppLayout.tsx +68 -0
  35. package/app/client/src/components/BackButton.tsx +13 -0
  36. package/app/client/src/components/DemoPage.tsx +20 -0
  37. package/app/client/src/components/LiveUploadWidget.tsx +204 -0
  38. package/app/client/src/lib/eden-api.ts +85 -65
  39. package/app/client/src/live/ChatDemo.tsx +107 -0
  40. package/app/client/src/live/CounterDemo.tsx +206 -0
  41. package/app/client/src/live/FormDemo.tsx +119 -0
  42. package/app/client/src/live/RoomChatDemo.tsx +242 -0
  43. package/app/client/src/live/UploadDemo.tsx +21 -0
  44. package/app/client/src/main.tsx +13 -10
  45. package/app/client/src/pages/ApiTestPage.tsx +108 -0
  46. package/app/client/src/pages/HomePage.tsx +76 -0
  47. package/app/client/src/vite-env.d.ts +1 -1
  48. package/app/server/app.ts +1 -4
  49. package/app/server/controllers/users.controller.ts +36 -44
  50. package/app/server/index.ts +24 -107
  51. package/app/server/live/LiveChat.ts +77 -0
  52. package/app/server/live/LiveCounter.ts +67 -0
  53. package/app/server/live/LiveForm.ts +63 -0
  54. package/app/server/live/LiveLocalCounter.ts +32 -0
  55. package/app/server/live/LiveRoomChat.ts +285 -0
  56. package/app/server/live/LiveUpload.ts +81 -0
  57. package/app/server/live/register-components.ts +19 -19
  58. package/app/server/routes/index.ts +3 -1
  59. package/app/server/routes/room.routes.ts +117 -0
  60. package/app/server/routes/users.routes.ts +35 -27
  61. package/app/shared/types/index.ts +14 -2
  62. package/config/app.config.ts +2 -62
  63. package/config/client.config.ts +2 -95
  64. package/config/database.config.ts +2 -99
  65. package/config/fluxstack.config.ts +25 -45
  66. package/config/index.ts +57 -38
  67. package/config/monitoring.config.ts +2 -114
  68. package/config/plugins.config.ts +2 -80
  69. package/config/server.config.ts +2 -68
  70. package/config/services.config.ts +2 -130
  71. package/config/system/app.config.ts +29 -0
  72. package/config/system/build.config.ts +49 -0
  73. package/config/system/client.config.ts +68 -0
  74. package/config/system/database.config.ts +17 -0
  75. package/config/system/fluxstack.config.ts +114 -0
  76. package/config/{logger.config.ts → system/logger.config.ts} +3 -1
  77. package/config/system/monitoring.config.ts +114 -0
  78. package/config/system/plugins.config.ts +84 -0
  79. package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
  80. package/config/system/server.config.ts +68 -0
  81. package/config/system/services.config.ts +46 -0
  82. package/config/{system.config.ts → system/system.config.ts} +1 -1
  83. package/core/build/bundler.ts +4 -1
  84. package/core/build/flux-plugins-generator.ts +325 -325
  85. package/core/build/index.ts +159 -27
  86. package/core/build/live-components-generator.ts +70 -3
  87. package/core/build/optimizer.ts +235 -235
  88. package/core/cli/command-registry.ts +6 -4
  89. package/core/cli/commands/build.ts +79 -0
  90. package/core/cli/commands/create.ts +54 -0
  91. package/core/cli/commands/dev.ts +101 -0
  92. package/core/cli/commands/help.ts +34 -0
  93. package/core/cli/commands/index.ts +34 -0
  94. package/core/cli/commands/make-plugin.ts +90 -0
  95. package/core/cli/commands/plugin-add.ts +197 -0
  96. package/core/cli/commands/plugin-deps.ts +2 -2
  97. package/core/cli/commands/plugin-list.ts +208 -0
  98. package/core/cli/commands/plugin-remove.ts +170 -0
  99. package/core/cli/generators/component.ts +769 -769
  100. package/core/cli/generators/controller.ts +1 -1
  101. package/core/cli/generators/index.ts +146 -146
  102. package/core/cli/generators/interactive.ts +227 -227
  103. package/core/cli/generators/plugin.ts +2 -2
  104. package/core/cli/generators/prompts.ts +82 -82
  105. package/core/cli/generators/route.ts +6 -6
  106. package/core/cli/generators/service.ts +2 -2
  107. package/core/cli/generators/template-engine.ts +4 -3
  108. package/core/cli/generators/types.ts +2 -2
  109. package/core/cli/generators/utils.ts +191 -191
  110. package/core/cli/index.ts +115 -558
  111. package/core/cli/plugin-discovery.ts +2 -2
  112. package/core/client/LiveComponentsProvider.tsx +63 -17
  113. package/core/client/api/eden.ts +183 -0
  114. package/core/client/api/index.ts +11 -0
  115. package/core/client/components/Live.tsx +104 -0
  116. package/core/client/fluxstack.ts +1 -9
  117. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -0
  118. package/core/client/hooks/state-validator.ts +1 -1
  119. package/core/client/hooks/useAuth.ts +48 -48
  120. package/core/client/hooks/useChunkedUpload.ts +170 -69
  121. package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
  122. package/core/client/hooks/useLiveComponent.ts +800 -0
  123. package/core/client/hooks/useLiveUpload.ts +71 -0
  124. package/core/client/hooks/useRoom.ts +409 -0
  125. package/core/client/hooks/useRoomProxy.ts +382 -0
  126. package/core/client/index.ts +18 -51
  127. package/core/client/standalone-entry.ts +8 -0
  128. package/core/client/standalone.ts +74 -53
  129. package/core/client/state/createStore.ts +192 -192
  130. package/core/client/state/index.ts +14 -14
  131. package/core/config/index.ts +70 -291
  132. package/core/config/schema.ts +42 -723
  133. package/core/framework/client.ts +131 -131
  134. package/core/framework/index.ts +7 -7
  135. package/core/framework/server.ts +227 -47
  136. package/core/framework/types.ts +2 -2
  137. package/core/index.ts +23 -4
  138. package/core/live/ComponentRegistry.ts +7 -3
  139. package/core/live/types.ts +77 -0
  140. package/core/plugins/built-in/index.ts +134 -131
  141. package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1074
  142. package/core/plugins/built-in/live-components/index.ts +1 -1
  143. package/core/plugins/built-in/monitoring/index.ts +111 -47
  144. package/core/plugins/built-in/static/index.ts +1 -1
  145. package/core/plugins/built-in/swagger/index.ts +68 -265
  146. package/core/plugins/built-in/vite/index.ts +94 -306
  147. package/core/plugins/built-in/vite/vite-dev.ts +82 -0
  148. package/core/plugins/config.ts +9 -7
  149. package/core/plugins/dependency-manager.ts +31 -1
  150. package/core/plugins/discovery.ts +19 -7
  151. package/core/plugins/executor.ts +2 -2
  152. package/core/plugins/index.ts +203 -203
  153. package/core/plugins/manager.ts +27 -39
  154. package/core/plugins/module-resolver.ts +19 -8
  155. package/core/plugins/registry.ts +309 -21
  156. package/core/plugins/types.ts +106 -55
  157. package/core/server/framework.ts +66 -43
  158. package/core/server/index.ts +15 -16
  159. package/core/server/live/ComponentRegistry.ts +91 -75
  160. package/core/server/live/FileUploadManager.ts +41 -31
  161. package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
  162. package/core/server/live/LiveRoomManager.ts +261 -0
  163. package/core/server/live/RoomEventBus.ts +234 -0
  164. package/core/server/live/RoomStateManager.ts +172 -0
  165. package/core/server/live/StateSignature.ts +643 -643
  166. package/core/server/live/WebSocketConnectionManager.ts +30 -19
  167. package/core/server/live/auto-generated-components.ts +41 -26
  168. package/core/server/live/index.ts +14 -0
  169. package/core/server/live/websocket-plugin.ts +233 -72
  170. package/core/server/middleware/elysia-helpers.ts +7 -2
  171. package/core/server/middleware/errorHandling.ts +1 -1
  172. package/core/server/middleware/index.ts +31 -31
  173. package/core/server/plugins/database.ts +180 -180
  174. package/core/server/plugins/static-files-plugin.ts +69 -260
  175. package/core/server/plugins/swagger.ts +33 -33
  176. package/core/server/rooms/RoomBroadcaster.ts +357 -0
  177. package/core/server/rooms/RoomSystem.ts +463 -0
  178. package/core/server/rooms/index.ts +13 -0
  179. package/core/server/services/BaseService.ts +1 -1
  180. package/core/server/services/ServiceContainer.ts +1 -1
  181. package/core/server/services/index.ts +8 -8
  182. package/core/templates/create-project.ts +12 -12
  183. package/core/testing/index.ts +9 -9
  184. package/core/testing/setup.ts +73 -73
  185. package/core/types/api.ts +168 -168
  186. package/core/types/build.ts +219 -218
  187. package/core/types/config.ts +56 -26
  188. package/core/types/index.ts +4 -4
  189. package/core/types/plugin.ts +107 -99
  190. package/core/types/types.ts +490 -14
  191. package/core/utils/build-logger.ts +324 -324
  192. package/core/utils/config-schema.ts +480 -480
  193. package/core/utils/env.ts +2 -8
  194. package/core/utils/errors/codes.ts +114 -114
  195. package/core/utils/errors/handlers.ts +36 -1
  196. package/core/utils/errors/index.ts +49 -5
  197. package/core/utils/errors/middleware.ts +113 -113
  198. package/core/utils/helpers.ts +6 -16
  199. package/core/utils/index.ts +17 -17
  200. package/core/utils/logger/colors.ts +114 -114
  201. package/core/utils/logger/config.ts +13 -9
  202. package/core/utils/logger/formatter.ts +82 -82
  203. package/core/utils/logger/group-logger.ts +101 -101
  204. package/core/utils/logger/index.ts +6 -1
  205. package/core/utils/logger/stack-trace.ts +3 -1
  206. package/core/utils/logger/startup-banner.ts +82 -66
  207. package/core/utils/logger/winston-logger.ts +152 -152
  208. package/core/utils/monitoring/index.ts +211 -211
  209. package/core/utils/sync-version.ts +66 -66
  210. package/core/utils/version.ts +1 -1
  211. package/create-fluxstack.ts +8 -7
  212. package/eslint.config.js +23 -23
  213. package/package.json +14 -15
  214. package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
  215. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  216. package/plugins/crypto-auth/client/components/index.ts +11 -11
  217. package/plugins/crypto-auth/client/index.ts +11 -11
  218. package/plugins/crypto-auth/config/index.ts +1 -1
  219. package/plugins/crypto-auth/index.ts +4 -4
  220. package/plugins/crypto-auth/package.json +65 -65
  221. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  222. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  223. package/plugins/crypto-auth/server/index.ts +21 -21
  224. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
  225. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
  226. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
  227. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
  228. package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
  229. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  230. package/plugins/crypto-auth/server/middlewares.ts +19 -19
  231. package/tsconfig.api-strict.json +16 -0
  232. package/tsconfig.json +10 -14
  233. package/{app/client/tsconfig.node.json → tsconfig.node.json} +1 -1
  234. package/types/global.d.ts +29 -29
  235. package/types/vitest.d.ts +8 -8
  236. package/vite.config.ts +38 -62
  237. package/vitest.config.live.ts +10 -9
  238. package/vitest.config.ts +29 -17
  239. package/workspace.json +5 -5
  240. package/app/client/README.md +0 -69
  241. package/app/client/SIMPLIFICATION.md +0 -140
  242. package/app/client/frontend-only.ts +0 -12
  243. package/app/client/tsconfig.app.json +0 -44
  244. package/app/client/tsconfig.json +0 -7
  245. package/app/client/zustand-setup.md +0 -65
  246. package/app/server/backend-only.ts +0 -18
  247. package/app/server/live/LiveClockComponent.ts +0 -215
  248. package/app/server/routes/env-test.ts +0 -110
  249. package/core/client/hooks/index.ts +0 -7
  250. package/core/client/hooks/useHybridLiveComponent.ts +0 -631
  251. package/core/client/hooks/useWebSocket.ts +0 -373
  252. package/core/config/env.ts +0 -546
  253. package/core/config/loader.ts +0 -522
  254. package/core/config/runtime-config.ts +0 -327
  255. package/core/config/validator.ts +0 -540
  256. package/core/server/backend-entry.ts +0 -51
  257. package/core/server/standalone.ts +0 -106
  258. package/core/utils/regenerate-files.ts +0 -69
  259. package/fluxstack.config.ts +0 -354
@@ -1,260 +1,69 @@
1
- // 🔥 FluxStack Static Files Plugin - Serve Public Files
2
-
3
- import { existsSync, statSync } from 'fs'
4
- import { join, extname, resolve } from 'path'
5
- import type { FluxStack, PluginContext, Plugin } from '../../plugins/types'
6
- import { t } from 'elysia'
7
-
8
- // Response schema for static files info endpoint
9
- const StaticFilesInfoSchema = t.Object({
10
- success: t.Boolean(),
11
- config: t.Object({
12
- publicDir: t.String(),
13
- uploadsDir: t.String(),
14
- enablePublic: t.Boolean(),
15
- enableUploads: t.Boolean(),
16
- cacheMaxAge: t.Number()
17
- }),
18
- paths: t.Object({
19
- publicPath: t.String(),
20
- uploadsPath: t.String(),
21
- publicUrl: t.String(),
22
- uploadsUrl: t.String()
23
- }),
24
- timestamp: t.String()
25
- }, {
26
- description: 'Static files configuration and paths information'
27
- })
28
-
29
- export interface StaticFilesConfig {
30
- publicDir?: string // Default: 'public'
31
- uploadsDir?: string // Default: 'uploads'
32
- cacheMaxAge?: number // Default: 1 year in seconds
33
- enableUploads?: boolean // Default: true
34
- enablePublic?: boolean // Default: true
35
- publicRoute?: string // Default: '/public' (can be '/static' in dev)
36
- uploadsRoute?: string // Default: '/uploads'
37
- }
38
-
39
- export const staticFilesPlugin: Plugin = {
40
- name: 'static-files',
41
- description: 'Serve static files and uploads with proper caching and security',
42
- author: 'FluxStack Team',
43
- priority: 'normal',
44
- category: 'core',
45
- tags: ['static', 'files', 'uploads', 'public'],
46
-
47
- setup: async (context: PluginContext) => {
48
- context.logger.debug('📁 Setting up Static Files plugin...')
49
-
50
- const config: StaticFilesConfig = {
51
- publicDir: 'public',
52
- uploadsDir: 'uploads',
53
- cacheMaxAge: 31536000, // 1 year
54
- enableUploads: true,
55
- enablePublic: true,
56
- publicRoute: '/api/static', // Use /api/static in dev to avoid Vite conflicts
57
- uploadsRoute: '/api/uploads',
58
- ...context.config.staticFiles
59
- }
60
-
61
- const projectRoot = process.cwd()
62
- const publicPath = resolve(projectRoot, config.publicDir!)
63
- const uploadsPath = resolve(projectRoot, config.uploadsDir!)
64
-
65
- // MIME types mapping
66
- const getMimeType = (extension: string): string => {
67
- const mimeTypes: Record<string, string> = {
68
- // Images
69
- '.jpg': 'image/jpeg',
70
- '.jpeg': 'image/jpeg',
71
- '.png': 'image/png',
72
- '.gif': 'image/gif',
73
- '.webp': 'image/webp',
74
- '.svg': 'image/svg+xml',
75
- '.ico': 'image/x-icon',
76
-
77
- // Documents
78
- '.pdf': 'application/pdf',
79
- '.txt': 'text/plain',
80
- '.json': 'application/json',
81
- '.xml': 'application/xml',
82
-
83
- // Web assets
84
- '.css': 'text/css',
85
- '.js': 'application/javascript',
86
- '.html': 'text/html',
87
- '.htm': 'text/html',
88
-
89
- // Fonts
90
- '.woff': 'font/woff',
91
- '.woff2': 'font/woff2',
92
- '.ttf': 'font/ttf',
93
- '.otf': 'font/otf',
94
-
95
- // Audio/Video
96
- '.mp3': 'audio/mpeg',
97
- '.mp4': 'video/mp4',
98
- '.webm': 'video/webm',
99
- '.ogg': 'audio/ogg'
100
- }
101
-
102
- return mimeTypes[extension.toLowerCase()] || 'application/octet-stream'
103
- }
104
-
105
- // Security check for path traversal
106
- const isPathSafe = (filePath: string, basePath: string): boolean => {
107
- const resolvedPath = resolve(basePath, filePath)
108
- return resolvedPath.startsWith(basePath)
109
- }
110
-
111
- // Generic file serving function
112
- const serveFile = async (filePath: string, set: any) => {
113
- try {
114
- if (!existsSync(filePath)) {
115
- set.status = 404
116
- return {
117
- error: 'File not found',
118
- path: filePath.replace(projectRoot, ''),
119
- timestamp: new Date().toISOString()
120
- }
121
- }
122
-
123
- const stats = statSync(filePath)
124
- if (!stats.isFile()) {
125
- set.status = 404
126
- return { error: 'Not a file' }
127
- }
128
-
129
- // Set appropriate headers
130
- const extension = extname(filePath).toLowerCase()
131
- const mimeType = getMimeType(extension)
132
-
133
- set.headers['content-type'] = mimeType
134
- set.headers['content-length'] = stats.size.toString()
135
- set.headers['last-modified'] = stats.mtime.toUTCString()
136
- set.headers['cache-control'] = `public, max-age=${config.cacheMaxAge}`
137
- set.headers['etag'] = `"${stats.mtime.getTime()}-${stats.size}"`
138
-
139
- // Security headers for images
140
- if (mimeType.startsWith('image/')) {
141
- set.headers['x-content-type-options'] = 'nosniff'
142
- }
143
-
144
- context.logger.debug(`📁 Serving file: ${filePath.replace(projectRoot, '')}`, {
145
- size: stats.size,
146
- mimeType,
147
- lastModified: stats.mtime
148
- })
149
-
150
- return Bun.file(filePath)
151
-
152
- } catch (error: any) {
153
- context.logger.error('❌ File serving error:', error.message)
154
- set.status = 500
155
- return { error: 'Failed to serve file' }
156
- }
157
- }
158
-
159
- // Add static file routes
160
- if (config.enablePublic) {
161
- const publicRoutePattern = `${config.publicRoute}/*`
162
- context.app.get(publicRoutePattern, ({ params, set }) => {
163
- const filePath = params['*'] || ''
164
-
165
- if (!isPathSafe(filePath, publicPath)) {
166
- set.status = 400
167
- return { error: 'Invalid file path' }
168
- }
169
-
170
- const fullPath = join(publicPath, filePath)
171
- return serveFile(fullPath, set)
172
- })
173
-
174
- context.logger.debug(`📁 Public files route enabled: ${publicRoutePattern} → ${config.publicDir}`)
175
- }
176
-
177
- if (config.enableUploads) {
178
- const uploadsRoutePattern = `${config.uploadsRoute}/*`
179
- context.app.get(uploadsRoutePattern, ({ params, set }) => {
180
- const filePath = params['*'] || ''
181
-
182
- if (!isPathSafe(filePath, uploadsPath)) {
183
- set.status = 400
184
- return { error: 'Invalid file path' }
185
- }
186
-
187
- const fullPath = join(uploadsPath, filePath)
188
- return serveFile(fullPath, set)
189
- })
190
-
191
- context.logger.debug(`📁 Uploads route enabled: ${uploadsRoutePattern} → ${config.uploadsDir}`)
192
- }
193
-
194
- // Static files info endpoint
195
- context.app.get('/api/static/info', () => {
196
- return {
197
- success: true,
198
- config: {
199
- publicDir: config.publicDir,
200
- uploadsDir: config.uploadsDir,
201
- enablePublic: config.enablePublic,
202
- enableUploads: config.enableUploads,
203
- cacheMaxAge: config.cacheMaxAge
204
- },
205
- paths: {
206
- publicPath,
207
- uploadsPath,
208
- publicUrl: config.publicRoute,
209
- uploadsUrl: config.uploadsRoute
210
- },
211
- timestamp: new Date().toISOString()
212
- }
213
- }, {
214
- detail: {
215
- summary: 'Static Files Configuration',
216
- description: 'Returns configuration and paths for static files and uploads serving',
217
- tags: ['Static Files', 'Configuration']
218
- },
219
- response: StaticFilesInfoSchema
220
- })
221
-
222
- // Create directories if they don't exist
223
- const { mkdir } = await import('fs/promises')
224
-
225
- if (config.enablePublic && !existsSync(publicPath)) {
226
- await mkdir(publicPath, { recursive: true })
227
- context.logger.debug(`📁 Created public directory: ${publicPath}`)
228
- }
229
-
230
- if (config.enableUploads && !existsSync(uploadsPath)) {
231
- await mkdir(uploadsPath, { recursive: true })
232
- await mkdir(join(uploadsPath, 'avatars'), { recursive: true })
233
- context.logger.debug(`📁 Created uploads directory: ${uploadsPath}`)
234
- }
235
-
236
- context.logger.debug('📁 Static Files plugin setup complete', {
237
- publicEnabled: config.enablePublic,
238
- uploadsEnabled: config.enableUploads,
239
- publicPath: config.enablePublic ? publicPath : 'disabled',
240
- uploadsPath: config.enableUploads ? uploadsPath : 'disabled'
241
- })
242
- },
243
-
244
- onServerStart: async (context: PluginContext) => {
245
- const config = {
246
- enablePublic: true,
247
- enableUploads: true,
248
- publicRoute: '/api/static',
249
- uploadsRoute: '/api/uploads',
250
- ...context.config.staticFiles
251
- }
252
- context.logger.debug('📁 Static Files plugin ready', {
253
- routes: [
254
- config.enablePublic ? `${config.publicRoute}/*` : null,
255
- config.enableUploads ? `${config.uploadsRoute}/*` : null,
256
- '/api/static/info'
257
- ].filter(Boolean)
258
- })
259
- }
260
- }
1
+ // 🔥 FluxStack Static Files Plugin - Serve Public Files & Uploads
2
+
3
+ import { existsSync, statSync } from 'fs'
4
+ import { mkdir } from 'fs/promises'
5
+ import { resolve } from 'path'
6
+ import type { Plugin, PluginContext } from '../../plugins/types'
7
+
8
+ export const staticFilesPlugin: Plugin = {
9
+ name: 'static-files',
10
+ description: 'Serve static files and uploads',
11
+ author: 'FluxStack Team',
12
+ priority: 'normal',
13
+ category: 'core',
14
+ tags: ['static', 'files', 'uploads'],
15
+
16
+ setup: async (context: PluginContext) => {
17
+ const projectRoot = process.cwd()
18
+ const publicDir = resolve(projectRoot, 'public')
19
+ const uploadsDir = resolve(projectRoot, 'uploads')
20
+
21
+ // Create directories if they don't exist
22
+ await mkdir(publicDir, { recursive: true })
23
+ await mkdir(uploadsDir, { recursive: true })
24
+ await mkdir(resolve(uploadsDir, 'avatars'), { recursive: true })
25
+
26
+ // Helper to serve files from a directory
27
+ const serveFile = (baseDir: string) => ({ params, set }: any) => {
28
+ const requestedPath = params['*'] || ''
29
+ const filePath = resolve(baseDir, requestedPath)
30
+
31
+ // Path traversal protection
32
+ if (!filePath.startsWith(baseDir)) {
33
+ set.status = 400
34
+ return { error: 'Invalid path' }
35
+ }
36
+
37
+ // Check if file exists
38
+ if (!existsSync(filePath)) {
39
+ set.status = 404
40
+ return { error: 'File not found' }
41
+ }
42
+
43
+ // Check if it's a file (not directory)
44
+ try {
45
+ if (!statSync(filePath).isFile()) {
46
+ set.status = 404
47
+ return { error: 'Not a file' }
48
+ }
49
+ } catch {
50
+ set.status = 404
51
+ return { error: 'File not found' }
52
+ }
53
+
54
+ // Set cache header (1 year)
55
+ set.headers['cache-control'] = 'public, max-age=31536000'
56
+
57
+ // Bun.file() handles: content-type, content-length, streaming
58
+ return Bun.file(filePath)
59
+ }
60
+
61
+ // Register routes
62
+ context.app.get('/api/static/*', serveFile(publicDir))
63
+ context.app.get('/api/uploads/*', serveFile(uploadsDir))
64
+
65
+ context.logger.debug('📁 Static files plugin ready', {
66
+ routes: ['/api/static/*', '/api/uploads/*']
67
+ })
68
+ }
69
+ }
@@ -1,34 +1,34 @@
1
- import { swagger } from '@elysiajs/swagger'
2
- import type { Plugin, PluginContext } from '@/core/plugins/types'
3
-
4
- export const swaggerPlugin: Plugin = {
5
- name: 'swagger',
6
- setup(context: PluginContext) {
7
- context.app.use(swagger({
8
- path: '/swagger',
9
- documentation: {
10
- info: {
11
- title: 'FluxStack API',
12
- version: '1.7.4',
13
- description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
14
- },
15
- tags: [
16
- {
17
- name: 'Health',
18
- description: 'Health check endpoints'
19
- },
20
- {
21
- name: 'Users',
22
- description: 'User management endpoints'
23
- }
24
- ],
25
- servers: [
26
- {
27
- url: `http://localhost:${context.config.server?.port || 3000}`,
28
- description: 'Development server'
29
- }
30
- ]
31
- }
32
- }))
33
- }
1
+ import { swagger } from '@elysiajs/swagger'
2
+ import type { Plugin, PluginContext } from '@core/plugins/types'
3
+
4
+ export const swaggerPlugin: Plugin = {
5
+ name: 'swagger',
6
+ setup(context: PluginContext) {
7
+ context.app.use(swagger({
8
+ path: '/swagger',
9
+ documentation: {
10
+ info: {
11
+ title: 'FluxStack API',
12
+ version: '1.7.4',
13
+ description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
14
+ },
15
+ tags: [
16
+ {
17
+ name: 'Health',
18
+ description: 'Health check endpoints'
19
+ },
20
+ {
21
+ name: 'Users',
22
+ description: 'User management endpoints'
23
+ }
24
+ ],
25
+ servers: [
26
+ {
27
+ url: `http://localhost:${context.config.server?.port || 3000}`,
28
+ description: 'Development server'
29
+ }
30
+ ]
31
+ }
32
+ }))
33
+ }
34
34
  }