create-fluxstack 1.7.5 → 1.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.dockerignore +82 -0
  2. package/.env.example +19 -0
  3. package/Dockerfile +70 -0
  4. package/README.md +6 -3
  5. package/app/client/SIMPLIFICATION.md +140 -0
  6. package/app/client/frontend-only.ts +1 -1
  7. package/app/client/src/App.tsx +148 -283
  8. package/app/client/src/index.css +5 -20
  9. package/app/client/src/lib/eden-api.ts +53 -220
  10. package/app/client/src/main.tsx +2 -3
  11. package/app/server/app.ts +20 -5
  12. package/app/server/backend-only.ts +15 -12
  13. package/app/server/controllers/users.controller.ts +57 -31
  14. package/app/server/index.ts +86 -96
  15. package/app/server/live/register-components.ts +18 -7
  16. package/app/server/routes/env-test.ts +110 -0
  17. package/app/server/routes/index.ts +1 -8
  18. package/app/server/routes/users.routes.ts +192 -91
  19. package/config/app.config.ts +2 -54
  20. package/config/client.config.ts +95 -0
  21. package/config/fluxstack.config.ts +2 -2
  22. package/config/index.ts +57 -22
  23. package/config/monitoring.config.ts +114 -0
  24. package/config/plugins.config.ts +80 -0
  25. package/config/runtime.config.ts +0 -17
  26. package/config/server.config.ts +50 -30
  27. package/core/build/bundler.ts +17 -16
  28. package/core/build/flux-plugins-generator.ts +34 -23
  29. package/core/build/index.ts +32 -31
  30. package/core/build/live-components-generator.ts +44 -30
  31. package/core/build/optimizer.ts +37 -17
  32. package/core/cli/command-registry.ts +4 -14
  33. package/core/cli/commands/plugin-deps.ts +8 -8
  34. package/core/cli/generators/component.ts +3 -3
  35. package/core/cli/generators/controller.ts +4 -4
  36. package/core/cli/generators/index.ts +8 -8
  37. package/core/cli/generators/interactive.ts +4 -4
  38. package/core/cli/generators/plugin.ts +3 -3
  39. package/core/cli/generators/prompts.ts +1 -1
  40. package/core/cli/generators/route.ts +27 -11
  41. package/core/cli/generators/service.ts +5 -5
  42. package/core/cli/generators/template-engine.ts +1 -1
  43. package/core/cli/generators/types.ts +1 -1
  44. package/core/cli/index.ts +158 -189
  45. package/core/cli/plugin-discovery.ts +3 -3
  46. package/core/client/hooks/index.ts +2 -2
  47. package/core/client/hooks/state-validator.ts +1 -1
  48. package/core/client/hooks/useAuth.ts +1 -1
  49. package/core/client/hooks/useChunkedUpload.ts +1 -1
  50. package/core/client/hooks/useHybridLiveComponent.ts +1 -1
  51. package/core/client/hooks/useWebSocket.ts +1 -1
  52. package/core/config/env.ts +5 -1
  53. package/core/config/runtime-config.ts +12 -10
  54. package/core/config/schema.ts +33 -2
  55. package/core/framework/server.ts +30 -14
  56. package/core/framework/types.ts +2 -2
  57. package/core/index.ts +31 -23
  58. package/core/live/ComponentRegistry.ts +1 -1
  59. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
  60. package/core/plugins/built-in/live-components/index.ts +1 -1
  61. package/core/plugins/built-in/monitoring/index.ts +65 -161
  62. package/core/plugins/built-in/static/index.ts +75 -277
  63. package/core/plugins/built-in/swagger/index.ts +301 -231
  64. package/core/plugins/built-in/vite/index.ts +342 -377
  65. package/core/plugins/config.ts +2 -2
  66. package/core/plugins/dependency-manager.ts +2 -2
  67. package/core/plugins/discovery.ts +1 -1
  68. package/core/plugins/executor.ts +2 -2
  69. package/core/plugins/manager.ts +19 -4
  70. package/core/plugins/module-resolver.ts +1 -1
  71. package/core/plugins/registry.ts +25 -21
  72. package/core/plugins/types.ts +147 -5
  73. package/core/server/backend-entry.ts +51 -0
  74. package/core/server/framework.ts +2 -2
  75. package/core/server/live/ComponentRegistry.ts +9 -26
  76. package/core/server/live/FileUploadManager.ts +1 -1
  77. package/core/server/live/auto-generated-components.ts +26 -0
  78. package/core/server/live/websocket-plugin.ts +211 -19
  79. package/core/server/middleware/errorHandling.ts +1 -1
  80. package/core/server/middleware/index.ts +4 -4
  81. package/core/server/plugins/database.ts +1 -2
  82. package/core/server/plugins/static-files-plugin.ts +259 -231
  83. package/core/server/plugins/swagger.ts +1 -1
  84. package/core/server/services/BaseService.ts +1 -1
  85. package/core/server/services/ServiceContainer.ts +1 -1
  86. package/core/server/services/index.ts +4 -4
  87. package/core/server/standalone.ts +16 -1
  88. package/core/testing/index.ts +1 -1
  89. package/core/testing/setup.ts +1 -1
  90. package/core/types/plugin.ts +6 -0
  91. package/core/utils/build-logger.ts +324 -0
  92. package/core/utils/config-schema.ts +2 -6
  93. package/core/utils/helpers.ts +14 -9
  94. package/core/utils/logger/startup-banner.ts +7 -33
  95. package/core/utils/regenerate-files.ts +69 -0
  96. package/core/utils/version.ts +6 -6
  97. package/create-fluxstack.ts +68 -25
  98. package/fluxstack.config.ts +138 -252
  99. package/package.json +3 -18
  100. package/plugins/crypto-auth/index.ts +52 -47
  101. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  102. package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
  103. package/vitest.config.ts +17 -26
  104. package/app/client/src/App.css +0 -883
  105. package/app/client/src/components/ErrorBoundary.tsx +0 -107
  106. package/app/client/src/components/ErrorDisplay.css +0 -365
  107. package/app/client/src/components/ErrorDisplay.tsx +0 -258
  108. package/app/client/src/components/FluxStackConfig.tsx +0 -1321
  109. package/app/client/src/components/HybridLiveCounter.tsx +0 -140
  110. package/app/client/src/components/LiveClock.tsx +0 -286
  111. package/app/client/src/components/MainLayout.tsx +0 -388
  112. package/app/client/src/components/SidebarNavigation.tsx +0 -391
  113. package/app/client/src/components/StateDemo.tsx +0 -178
  114. package/app/client/src/components/SystemMonitor.tsx +0 -1044
  115. package/app/client/src/components/UserProfile.tsx +0 -809
  116. package/app/client/src/hooks/useAuth.ts +0 -39
  117. package/app/client/src/hooks/useNotifications.ts +0 -56
  118. package/app/client/src/lib/errors.ts +0 -340
  119. package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
  120. package/app/client/src/lib/index.ts +0 -45
  121. package/app/client/src/pages/ApiDocs.tsx +0 -182
  122. package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
  123. package/app/client/src/pages/Demo.tsx +0 -174
  124. package/app/client/src/pages/HybridLive.tsx +0 -263
  125. package/app/client/src/pages/Overview.tsx +0 -155
  126. package/app/client/src/store/README.md +0 -43
  127. package/app/client/src/store/index.ts +0 -16
  128. package/app/client/src/store/slices/uiSlice.ts +0 -151
  129. package/app/client/src/store/slices/userSlice.ts +0 -161
  130. package/app/client/src/test/README.md +0 -257
  131. package/app/client/src/test/setup.ts +0 -70
  132. package/app/client/src/test/types.ts +0 -12
  133. package/app/server/live/CounterComponent.ts +0 -191
  134. package/app/server/live/FluxStackConfig.ts +0 -534
  135. package/app/server/live/SidebarNavigation.ts +0 -157
  136. package/app/server/live/SystemMonitor.ts +0 -595
  137. package/app/server/live/SystemMonitorIntegration.ts +0 -151
  138. package/app/server/live/UserProfileComponent.ts +0 -141
  139. package/app/server/middleware/auth.ts +0 -136
  140. package/app/server/middleware/errorHandling.ts +0 -252
  141. package/app/server/middleware/index.ts +0 -10
  142. package/app/server/middleware/rateLimit.ts +0 -193
  143. package/app/server/middleware/requestLogging.ts +0 -215
  144. package/app/server/middleware/validation.ts +0 -270
  145. package/app/server/routes/config.ts +0 -145
  146. package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
  147. package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
  148. package/app/server/routes/exemplo-posts.routes.ts +0 -161
  149. package/app/server/routes/upload.ts +0 -92
  150. package/app/server/services/NotificationService.ts +0 -302
  151. package/app/server/services/UserService.ts +0 -222
  152. package/app/server/services/index.ts +0 -46
  153. package/app/server/types/index.ts +0 -1
  154. package/config/build.config.ts +0 -24
@@ -1,305 +1,103 @@
1
- import { join, extname } from "path"
2
- import { existsSync, statSync } from "fs"
3
- import type { FluxStack, PluginContext } from "../../types"
1
+ import { join } from "path"
2
+ import { statSync, existsSync } from "fs"
3
+ import type { Plugin, PluginContext } from "@/core/plugins"
4
4
 
5
- type Plugin = FluxStack.Plugin
5
+ // Default configuration values
6
+ const DEFAULTS = {
7
+ enabled: true,
8
+ publicDir: "./dist/client",
9
+ indexFile: "index.html"
10
+ }
6
11
 
7
12
  export const staticPlugin: Plugin = {
8
13
  name: "static",
9
- version: "1.0.0",
10
- description: "Enhanced static file serving plugin for FluxStack with caching and compression",
14
+ version: "2.0.0",
15
+ description: "Simple and efficient static file serving plugin for FluxStack",
11
16
  author: "FluxStack Team",
12
- priority: 100, // Should run after other plugins
17
+ priority: 200, // Run after all other plugins
13
18
  category: "core",
14
19
  tags: ["static", "files", "spa"],
15
- dependencies: [], // No hard dependencies, but works with vite plugin
16
-
17
- configSchema: {
18
- type: "object",
19
- properties: {
20
- enabled: {
21
- type: "boolean",
22
- description: "Enable static file serving"
23
- },
24
- publicDir: {
25
- type: "string",
26
- description: "Public directory for static files"
27
- },
28
- distDir: {
29
- type: "string",
30
- description: "Distribution directory for built files"
31
- },
32
- indexFile: {
33
- type: "string",
34
- description: "Index file for SPA routing"
35
- },
36
- cacheControl: {
37
- type: "object",
38
- properties: {
39
- enabled: { type: "boolean" },
40
- maxAge: { type: "number" },
41
- immutable: { type: "boolean" }
42
- },
43
- description: "Cache control settings"
44
- },
45
- compression: {
46
- type: "object",
47
- properties: {
48
- enabled: { type: "boolean" },
49
- types: {
50
- type: "array",
51
- items: { type: "string" }
52
- }
53
- },
54
- description: "Compression settings"
55
- },
56
- spa: {
57
- type: "object",
58
- properties: {
59
- enabled: { type: "boolean" },
60
- fallback: { type: "string" }
61
- },
62
- description: "Single Page Application settings"
63
- },
64
- excludePaths: {
65
- type: "array",
66
- items: { type: "string" },
67
- description: "Paths to exclude from static serving"
68
- }
69
- },
70
- additionalProperties: false
71
- },
72
-
73
- defaultConfig: {
74
- enabled: true,
75
- publicDir: "public",
76
- distDir: "dist/client",
77
- indexFile: "index.html",
78
- cacheControl: {
79
- enabled: true,
80
- maxAge: 31536000, // 1 year for assets
81
- immutable: true
82
- },
83
- compression: {
84
- enabled: true,
85
- types: [".js", ".css", ".html", ".json", ".svg"]
86
- },
87
- spa: {
88
- enabled: true,
89
- fallback: "index.html"
90
- },
91
- excludePaths: []
92
- },
20
+ dependencies: [],
93
21
 
94
22
  setup: async (context: PluginContext) => {
95
- const config = getPluginConfig(context)
96
-
97
- if (!config.enabled) {
98
- context.logger.info('Static files plugin disabled by configuration')
23
+ if (!DEFAULTS.enabled) {
24
+ context.logger.info('Static files plugin disabled')
99
25
  return
100
26
  }
101
27
 
102
- context.logger.info("Enhanced static files plugin activated", {
103
- publicDir: config.publicDir,
104
- distDir: config.distDir,
105
- spa: config.spa.enabled,
106
- compression: config.compression.enabled
28
+ context.logger.info("Static files plugin activated", {
29
+ publicDir: DEFAULTS.publicDir
107
30
  })
108
-
109
- // Helper function for handling both GET and HEAD requests
110
- const handleStaticRequest = async ({ request, set }: { request: Request, set: any }) => {
111
- const url = new URL(request.url)
112
-
113
- // Skip API routes
114
- if (url.pathname.startsWith(context.config.server.apiPrefix)) {
115
- return
31
+
32
+ // Static fallback handler (runs last)
33
+ const staticFallback = (c: any) => {
34
+ const req = c.request
35
+ if (!req) return
36
+
37
+ const url = new URL(req.url)
38
+ let pathname = decodeURIComponent(url.pathname)
39
+
40
+ // Determine base directory using path discovery
41
+ const isDev = context.utils.isDevelopment()
42
+ let baseDir: string
43
+
44
+ if (isDev && existsSync(DEFAULTS.publicDir)) {
45
+ // Development: use public directory
46
+ baseDir = DEFAULTS.publicDir
47
+ } else {
48
+ // Production: try paths in order of preference
49
+ if (existsSync('client')) {
50
+ // Found client/ in current directory (running from dist/)
51
+ baseDir = 'client'
52
+ } else if (existsSync('dist/client')) {
53
+ // Found dist/client/ (running from project root)
54
+ baseDir = 'dist/client'
55
+ } else {
56
+ // Fallback to configured path
57
+ baseDir = DEFAULTS.publicDir
58
+ }
59
+ }
60
+
61
+ // Root or empty path → index.html
62
+ if (pathname === '/' || pathname === '') {
63
+ pathname = `/${DEFAULTS.indexFile}`
116
64
  }
117
-
118
- // Skip excluded paths
119
- if (config.excludePaths.some((path: string) => url.pathname.startsWith(path))) {
120
- return
65
+
66
+ const filePath = join(baseDir, pathname)
67
+
68
+ try {
69
+ const info = statSync(filePath)
70
+
71
+ // File exists → serve it
72
+ if (info.isFile()) {
73
+ return new Response(Bun.file(filePath))
74
+ }
75
+ } catch (_) {
76
+ // File not found → continue
121
77
  }
122
-
78
+
79
+ // SPA fallback: serve index.html for non-file routes
80
+ const indexPath = join(baseDir, DEFAULTS.indexFile)
123
81
  try {
124
- // Note: Vite proxy is now handled by the Vite plugin via onBeforeRoute hook
125
- // This plugin only handles static files serving in production or fallback
126
-
127
- // Serve static files
128
- return await serveStaticFile(url.pathname, config, context, set, request.method === 'HEAD')
129
-
130
- } catch (error) {
131
- context.logger.error("Error serving static file", {
132
- path: url.pathname,
133
- error: error instanceof Error ? error.message : String(error)
134
- })
135
-
136
- set.status = 500
137
- return "Internal Server Error"
82
+ statSync(indexPath) // Ensure index exists
83
+ return new Response(Bun.file(indexPath))
84
+ } catch (_) {
85
+ // Index not found → let request continue (404)
138
86
  }
139
87
  }
140
88
 
141
- // Setup static file handling in Elysia - handle both GET and HEAD
142
- context.app.get("/*", handleStaticRequest)
143
- context.app.head("/*", handleStaticRequest)
89
+ // Register as catch-all fallback (runs after all other routes)
90
+ context.app.all('*', staticFallback)
144
91
  },
145
92
 
146
93
  onServerStart: async (context: PluginContext) => {
147
- const config = getPluginConfig(context)
148
-
149
- if (config.enabled) {
150
- const mode = context.utils.isDevelopment() ? 'development' : 'production'
151
- context.logger.info(`Static files plugin ready in ${mode} mode`, {
152
- publicDir: config.publicDir,
153
- distDir: config.distDir,
154
- spa: config.spa.enabled
94
+ if (DEFAULTS.enabled) {
95
+ context.logger.info(`Static files plugin ready`, {
96
+ publicDir: DEFAULTS.publicDir,
97
+ indexFile: DEFAULTS.indexFile
155
98
  })
156
99
  }
157
100
  }
158
101
  }
159
102
 
160
- // Helper function to get plugin config
161
- function getPluginConfig(context: PluginContext) {
162
- const pluginConfig = context.config.plugins.config?.static || {}
163
- return { ...staticPlugin.defaultConfig, ...pluginConfig }
164
- }
165
-
166
- // Serve static file
167
- async function serveStaticFile(
168
- pathname: string,
169
- config: any,
170
- context: PluginContext,
171
- set: any,
172
- isHead: boolean = false
173
- ): Promise<any> {
174
- const isDev = context.utils.isDevelopment()
175
-
176
- // Determine base directory using path discovery (no hardcoded detection)
177
- let baseDir: string
178
-
179
- if (isDev && existsSync(config.publicDir)) {
180
- // Development: use public directory
181
- baseDir = config.publicDir
182
- } else {
183
- // Production: try paths in order of preference
184
- if (existsSync('client')) {
185
- // Found client/ in current directory (running from dist/)
186
- baseDir = 'client'
187
- } else if (existsSync('dist/client')) {
188
- // Found dist/client/ (running from project root)
189
- baseDir = 'dist/client'
190
- } else {
191
- // Fallback to configured path
192
- baseDir = config.distDir
193
- }
194
- }
195
-
196
- if (!existsSync(baseDir)) {
197
- context.logger.warn(`Static directory not found: ${baseDir}`)
198
- set.status = 404
199
- return "Not Found"
200
- }
201
-
202
- // Clean pathname
203
- const cleanPath = pathname === '/' ? `/${config.indexFile}` : pathname
204
- const filePath = join(process.cwd(), baseDir, cleanPath)
205
-
206
- // Security check - prevent directory traversal
207
- const resolvedPath = join(process.cwd(), baseDir)
208
- if (!filePath.startsWith(resolvedPath)) {
209
- set.status = 403
210
- return "Forbidden"
211
- }
212
-
213
- // Check if file exists
214
- if (!existsSync(filePath)) {
215
- // For SPA, serve index.html for non-file routes
216
- if (config.spa.enabled && !pathname.includes('.')) {
217
- const indexPath = join(process.cwd(), baseDir, config.spa.fallback)
218
- if (existsSync(indexPath)) {
219
- return serveFile(indexPath, config, set, context, isHead)
220
- }
221
- }
222
-
223
- set.status = 404
224
- return "Not Found"
225
- }
226
-
227
- // Check if it's a directory
228
- const stats = statSync(filePath)
229
- if (stats.isDirectory()) {
230
- const indexPath = join(filePath, config.indexFile)
231
- if (existsSync(indexPath)) {
232
- return serveFile(indexPath, config, set, context, isHead)
233
- }
234
-
235
- set.status = 404
236
- return "Not Found"
237
- }
238
-
239
- return serveFile(filePath, config, set, context, isHead)
240
- }
241
-
242
- // Serve individual file
243
- function serveFile(filePath: string, config: any, set: any, context: PluginContext, isHead: boolean = false) {
244
- const ext = extname(filePath)
245
- const file = Bun.file(filePath)
246
-
247
- // Set content type
248
- const mimeTypes: Record<string, string> = {
249
- '.html': 'text/html',
250
- '.css': 'text/css',
251
- '.js': 'application/javascript',
252
- '.json': 'application/json',
253
- '.png': 'image/png',
254
- '.jpg': 'image/jpeg',
255
- '.jpeg': 'image/jpeg',
256
- '.gif': 'image/gif',
257
- '.svg': 'image/svg+xml',
258
- '.ico': 'image/x-icon',
259
- '.woff': 'font/woff',
260
- '.woff2': 'font/woff2',
261
- '.ttf': 'font/ttf',
262
- '.eot': 'application/vnd.ms-fontobject'
263
- }
264
-
265
- const contentType = mimeTypes[ext] || 'application/octet-stream'
266
- set.headers['Content-Type'] = contentType
267
-
268
- // Set content-length for both GET and HEAD requests
269
- set.headers['Content-Length'] = file.size.toString()
270
-
271
- // Set cache headers
272
- if (config.cacheControl.enabled) {
273
- if (ext === '.html') {
274
- // Don't cache HTML files aggressively
275
- set.headers['Cache-Control'] = 'no-cache'
276
- } else {
277
- // Cache assets aggressively
278
- const maxAge = config.cacheControl.maxAge
279
- const cacheControl = config.cacheControl.immutable
280
- ? `public, max-age=${maxAge}, immutable`
281
- : `public, max-age=${maxAge}`
282
- set.headers['Cache-Control'] = cacheControl
283
- }
284
- }
285
-
286
- // Add compression hint if enabled
287
- if (config.compression.enabled && config.compression.types.includes(ext)) {
288
- set.headers['Vary'] = 'Accept-Encoding'
289
- }
290
-
291
- context.logger.debug(`Serving static file: ${filePath}`, {
292
- contentType,
293
- size: file.size,
294
- method: isHead ? 'HEAD' : 'GET'
295
- })
296
-
297
- // For HEAD requests, return empty body but keep all headers
298
- if (isHead) {
299
- return ""
300
- }
301
-
302
- return file
303
- }
304
-
305
103
  export default staticPlugin