create-fluxstack 1.13.0 → 1.15.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 (96) hide show
  1. package/LLMD/patterns/anti-patterns.md +100 -0
  2. package/LLMD/reference/routing.md +39 -39
  3. package/LLMD/resources/live-auth.md +20 -2
  4. package/LLMD/resources/live-components.md +300 -21
  5. package/LLMD/resources/live-logging.md +95 -33
  6. package/LLMD/resources/live-upload.md +59 -8
  7. package/app/client/.live-stubs/LiveAdminPanel.js +5 -0
  8. package/app/client/.live-stubs/LiveChat.js +7 -0
  9. package/app/client/.live-stubs/LiveCounter.js +9 -0
  10. package/app/client/.live-stubs/LiveForm.js +11 -0
  11. package/app/client/.live-stubs/LiveLocalCounter.js +8 -0
  12. package/app/client/.live-stubs/LiveRoomChat.js +10 -0
  13. package/app/client/.live-stubs/LiveTodoList.js +9 -0
  14. package/app/client/.live-stubs/LiveUpload.js +15 -0
  15. package/app/client/index.html +2 -2
  16. package/app/client/public/favicon.svg +46 -0
  17. package/app/client/src/App.tsx +13 -1
  18. package/app/client/src/assets/fluxstack-static.svg +46 -0
  19. package/app/client/src/assets/fluxstack.svg +183 -0
  20. package/app/client/src/components/AppLayout.tsx +146 -9
  21. package/app/client/src/components/BackButton.tsx +13 -13
  22. package/app/client/src/components/DemoPage.tsx +4 -4
  23. package/app/client/src/live/AuthDemo.tsx +23 -21
  24. package/app/client/src/live/ChatDemo.tsx +2 -2
  25. package/app/client/src/live/CounterDemo.tsx +12 -12
  26. package/app/client/src/live/FormDemo.tsx +2 -2
  27. package/app/client/src/live/LiveDebuggerPanel.tsx +779 -0
  28. package/app/client/src/live/RoomChatDemo.tsx +24 -16
  29. package/app/client/src/live/TodoListDemo.tsx +158 -0
  30. package/app/client/src/main.tsx +13 -13
  31. package/app/client/src/pages/ApiTestPage.tsx +6 -6
  32. package/app/client/src/pages/HomePage.tsx +80 -52
  33. package/app/server/auth/DevAuthProvider.ts +2 -2
  34. package/app/server/auth/JWTAuthProvider.example.ts +2 -2
  35. package/app/server/index.ts +2 -2
  36. package/app/server/live/LiveAdminPanel.ts +2 -1
  37. package/app/server/live/LiveChat.ts +78 -77
  38. package/app/server/live/LiveCounter.ts +1 -1
  39. package/app/server/live/LiveForm.ts +1 -0
  40. package/app/server/live/LiveLocalCounter.ts +38 -37
  41. package/app/server/live/LiveProtectedChat.ts +2 -1
  42. package/app/server/live/LiveRoomChat.ts +1 -0
  43. package/app/server/live/LiveTodoList.ts +110 -0
  44. package/app/server/live/LiveUpload.ts +1 -0
  45. package/app/server/live/register-components.ts +19 -19
  46. package/app/server/routes/room.routes.ts +1 -2
  47. package/config/system/runtime.config.ts +4 -0
  48. package/core/build/live-components-generator.ts +1 -1
  49. package/core/build/optimizer.ts +235 -235
  50. package/core/build/vite-plugins.ts +28 -0
  51. package/core/client/components/LiveDebugger.tsx +1324 -0
  52. package/core/client/hooks/useLiveUpload.ts +3 -4
  53. package/core/client/index.ts +41 -21
  54. package/core/framework/server.ts +1 -1
  55. package/core/plugins/built-in/index.ts +134 -134
  56. package/core/plugins/built-in/live-components/commands/create-live-component.ts +4 -0
  57. package/core/plugins/built-in/vite/index.ts +75 -21
  58. package/core/server/index.ts +14 -15
  59. package/core/server/live/auto-generated-components.ts +6 -3
  60. package/core/server/live/index.ts +95 -21
  61. package/core/server/live/websocket-plugin.ts +27 -862
  62. package/core/server/plugins/static-files-plugin.ts +179 -69
  63. package/core/types/build.ts +219 -219
  64. package/core/types/plugin.ts +107 -107
  65. package/core/types/types.ts +77 -890
  66. package/core/utils/logger/startup-banner.ts +82 -82
  67. package/core/utils/version.ts +6 -6
  68. package/create-fluxstack.ts +1 -1
  69. package/package.json +5 -1
  70. package/plugins/crypto-auth/index.ts +1 -1
  71. package/plugins/crypto-auth/server/CryptoAuthLiveProvider.ts +2 -2
  72. package/vite.config.ts +40 -12
  73. package/app/client/src/assets/react.svg +0 -1
  74. package/core/client/LiveComponentsProvider.tsx +0 -531
  75. package/core/client/components/Live.tsx +0 -105
  76. package/core/client/hooks/AdaptiveChunkSizer.ts +0 -215
  77. package/core/client/hooks/state-validator.ts +0 -130
  78. package/core/client/hooks/useChunkedUpload.ts +0 -359
  79. package/core/client/hooks/useLiveChunkedUpload.ts +0 -87
  80. package/core/client/hooks/useLiveComponent.ts +0 -843
  81. package/core/client/hooks/useRoom.ts +0 -409
  82. package/core/client/hooks/useRoomProxy.ts +0 -382
  83. package/core/server/live/ComponentRegistry.ts +0 -1099
  84. package/core/server/live/FileUploadManager.ts +0 -282
  85. package/core/server/live/LiveComponentPerformanceMonitor.ts +0 -931
  86. package/core/server/live/LiveLogger.ts +0 -111
  87. package/core/server/live/LiveRoomManager.ts +0 -262
  88. package/core/server/live/RoomEventBus.ts +0 -234
  89. package/core/server/live/RoomStateManager.ts +0 -172
  90. package/core/server/live/SingleConnectionManager.ts +0 -0
  91. package/core/server/live/StateSignature.ts +0 -645
  92. package/core/server/live/WebSocketConnectionManager.ts +0 -709
  93. package/core/server/live/auth/LiveAuthContext.ts +0 -71
  94. package/core/server/live/auth/LiveAuthManager.ts +0 -304
  95. package/core/server/live/auth/index.ts +0 -19
  96. package/core/server/live/auth/types.ts +0 -179
@@ -1,8 +1,7 @@
1
1
  import { useMemo } from 'react'
2
- import { Live } from '../components/Live'
3
- import { useLiveChunkedUpload } from './useLiveChunkedUpload'
4
- import type { LiveChunkedUploadOptions } from './useLiveChunkedUpload'
5
- import type { FileUploadCompleteResponse } from '@core/types/types'
2
+ import { Live, useLiveChunkedUpload } from '@fluxstack/live-react'
3
+ import type { LiveChunkedUploadOptions } from '@fluxstack/live-react'
4
+ import type { FileUploadCompleteResponse } from '@fluxstack/live'
6
5
  import { LiveUpload } from '@server/live/LiveUpload'
7
6
 
8
7
  export interface UseLiveUploadOptions {
@@ -1,6 +1,40 @@
1
- // 🔥 FluxStack Client Core - Main Export
1
+ // FluxStack Client Core - Main Export
2
+ // Re-exports from @fluxstack/live-react + FluxStack-specific code
2
3
 
3
- // API Client (Eden Treaty)
4
+ // === Re-exports from @fluxstack/live-react ===
5
+
6
+ // Provider
7
+ export { LiveComponentsProvider, useLiveComponents } from '@fluxstack/live-react'
8
+ export type {
9
+ LiveComponentsProviderProps,
10
+ LiveComponentsContextValue,
11
+ } from '@fluxstack/live-react'
12
+ export type { LiveAuthOptions } from '@fluxstack/live-react'
13
+
14
+ // Live.use() API
15
+ export { Live } from '@fluxstack/live-react'
16
+
17
+ // Upload Hooks
18
+ export { useChunkedUpload } from '@fluxstack/live-react'
19
+ export type { ChunkedUploadOptions, ChunkedUploadState } from '@fluxstack/live-react'
20
+ export { useLiveChunkedUpload } from '@fluxstack/live-react'
21
+ export type { LiveChunkedUploadOptions } from '@fluxstack/live-react'
22
+
23
+ // Debugger Hook
24
+ export { useLiveDebugger } from '@fluxstack/live-react'
25
+ export type {
26
+ DebugEvent,
27
+ DebugEventType,
28
+ ComponentSnapshot,
29
+ DebugSnapshot,
30
+ DebugFilter,
31
+ UseLiveDebuggerReturn,
32
+ UseLiveDebuggerOptions,
33
+ } from '@fluxstack/live-react'
34
+
35
+ // === FluxStack-specific (stays here) ===
36
+
37
+ // Eden Treaty API client
4
38
  export {
5
39
  createEdenClient,
6
40
  getErrorMessage,
@@ -9,23 +43,9 @@ export {
9
43
  type EdenClientOptions
10
44
  } from './api'
11
45
 
12
- // Live Components Provider (Singleton WebSocket Connection)
13
- export {
14
- LiveComponentsProvider,
15
- useLiveComponents
16
- } from './LiveComponentsProvider'
17
- export type {
18
- LiveComponentsProviderProps,
19
- LiveComponentsContextValue,
20
- LiveAuthOptions
21
- } from './LiveComponentsProvider'
22
-
23
- // Chunked Upload Hook
24
- export { useChunkedUpload } from './hooks/useChunkedUpload'
25
- export type { ChunkedUploadOptions, ChunkedUploadState } from './hooks/useChunkedUpload'
26
- export { useLiveChunkedUpload } from './hooks/useLiveChunkedUpload'
27
- export type { LiveChunkedUploadOptions } from './hooks/useLiveChunkedUpload'
28
- export { useLiveUpload } from './hooks/useLiveUpload'
46
+ // LiveDebugger UI component (React component, 1325 lines - not extracted to lib)
47
+ export { LiveDebugger } from './components/LiveDebugger'
48
+ export type { LiveDebuggerProps } from './components/LiveDebugger'
29
49
 
30
- // Live Component Hook (API principal)
31
- export { Live } from './components/Live'
50
+ // useLiveUpload (FluxStack-specific convenience wrapper)
51
+ export { useLiveUpload } from './hooks/useLiveUpload'
@@ -7,7 +7,7 @@ import { fluxStackConfig } from "@config"
7
7
  import { getEnvironmentInfo } from "@core/config"
8
8
  import { logger } from "@core/utils/logger"
9
9
  import { displayStartupBanner, type StartupInfo } from "@core/utils/logger/startup-banner"
10
- import { componentRegistry } from "@core/server/live/ComponentRegistry"
10
+ import { componentRegistry } from "@core/server/live"
11
11
  import { FluxStackError } from "@core/utils/errors"
12
12
  import { createTimer, formatBytes, isProduction, isDevelopment } from "@core/utils/helpers"
13
13
  import type { Plugin } from "@core/plugins"
@@ -1,135 +1,135 @@
1
- /**
2
- * Built-in Plugins for FluxStack
3
- * Core plugins that provide essential functionality
4
- *
5
- * Note: Logger is NOT a plugin - it's core infrastructure used by plugins
6
- */
7
-
8
- // Import all built-in plugins
9
- import { swaggerPlugin } from './swagger'
10
- import { vitePlugin } from './vite'
11
- import { monitoringPlugin } from './monitoring'
12
-
13
- // Export individual plugins
14
- export { swaggerPlugin } from './swagger'
15
- export { vitePlugin } from './vite'
16
- export { monitoringPlugin } from './monitoring'
17
-
18
- // Deprecated: staticPlugin is now merged into vitePlugin (auto-detects dev/prod)
19
- /** @deprecated Use vitePlugin instead - it now handles both dev and prod */
20
- export const staticPlugin = vitePlugin
21
-
22
- // Export as a collection
23
- export const builtInPlugins = {
24
- swagger: swaggerPlugin,
25
- vite: vitePlugin,
26
- static: staticPlugin,
27
- monitoring: monitoringPlugin
28
- } as const
29
-
30
- // Export as an array for easy registration
31
- export const builtInPluginsList = [
32
- swaggerPlugin,
33
- vitePlugin,
34
- staticPlugin,
35
- monitoringPlugin
36
- ] as const
37
-
38
- // Plugin categories
39
- export const pluginCategories = {
40
- core: [vitePlugin], // vitePlugin now handles both dev (Vite) and prod (static)
41
- development: [vitePlugin],
42
- documentation: [swaggerPlugin],
43
- monitoring: [monitoringPlugin]
44
- } as const
45
-
46
- // Default plugin configuration
47
- export const defaultPluginConfig = {
48
- swagger: {
49
- enabled: true,
50
- path: '/swagger',
51
- title: 'FluxStack API',
52
- description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
53
- },
54
- vite: {
55
- enabled: true,
56
- port: 5173,
57
- host: 'localhost',
58
- checkInterval: 2000,
59
- maxRetries: 10,
60
- timeout: 5000
61
- },
62
- static: {
63
- enabled: true,
64
- publicDir: 'public',
65
- distDir: 'dist/client',
66
- indexFile: 'index.html',
67
- spa: {
68
- enabled: true,
69
- fallback: 'index.html'
70
- }
71
- },
72
- monitoring: {
73
- enabled: false, // Disabled by default to avoid overhead
74
- httpMetrics: true,
75
- systemMetrics: true,
76
- customMetrics: true,
77
- collectInterval: 5000,
78
- retentionPeriod: 300000,
79
- exporters: [
80
- {
81
- type: 'console',
82
- interval: 30000,
83
- enabled: false
84
- }
85
- ],
86
- thresholds: {
87
- responseTime: 1000,
88
- errorRate: 0.05,
89
- memoryUsage: 0.8,
90
- cpuUsage: 0.8
91
- }
92
- }
93
- } as const
94
-
95
- /**
96
- * Get default plugins for a specific environment
97
- */
98
- export function getDefaultPlugins(environment: 'development' | 'production' | 'test' = 'development') {
99
- // vitePlugin now auto-detects dev/prod and serves appropriately
100
- const basePlugins = [vitePlugin]
101
-
102
- switch (environment) {
103
- case 'development':
104
- return [...basePlugins, swaggerPlugin, monitoringPlugin]
105
- case 'production':
106
- return [...basePlugins, monitoringPlugin]
107
- case 'test':
108
- return [] // Minimal plugins for testing
109
- default:
110
- return basePlugins
111
- }
112
- }
113
-
114
- /**
115
- * Get plugin by name
116
- */
117
- export function getBuiltInPlugin(name: string) {
118
- return builtInPlugins[name as keyof typeof builtInPlugins]
119
- }
120
-
121
- /**
122
- * Check if a plugin is built-in
123
- */
124
- export function isBuiltInPlugin(name: string): boolean {
125
- return name in builtInPlugins
126
- }
127
-
128
- /**
129
- * Get plugins by category
130
- */
131
- export function getPluginsByCategory(category: keyof typeof pluginCategories) {
132
- return pluginCategories[category] || []
133
- }
134
-
1
+ /**
2
+ * Built-in Plugins for FluxStack
3
+ * Core plugins that provide essential functionality
4
+ *
5
+ * Note: Logger is NOT a plugin - it's core infrastructure used by plugins
6
+ */
7
+
8
+ // Import all built-in plugins
9
+ import { swaggerPlugin } from './swagger'
10
+ import { vitePlugin } from './vite'
11
+ import { monitoringPlugin } from './monitoring'
12
+
13
+ // Export individual plugins
14
+ export { swaggerPlugin } from './swagger'
15
+ export { vitePlugin } from './vite'
16
+ export { monitoringPlugin } from './monitoring'
17
+
18
+ // Deprecated: staticPlugin is now merged into vitePlugin (auto-detects dev/prod)
19
+ /** @deprecated Use vitePlugin instead - it now handles both dev and prod */
20
+ export const staticPlugin = vitePlugin
21
+
22
+ // Export as a collection
23
+ export const builtInPlugins = {
24
+ swagger: swaggerPlugin,
25
+ vite: vitePlugin,
26
+ static: staticPlugin,
27
+ monitoring: monitoringPlugin
28
+ } as const
29
+
30
+ // Export as an array for easy registration
31
+ export const builtInPluginsList = [
32
+ swaggerPlugin,
33
+ vitePlugin,
34
+ staticPlugin,
35
+ monitoringPlugin
36
+ ] as const
37
+
38
+ // Plugin categories
39
+ export const pluginCategories = {
40
+ core: [vitePlugin], // vitePlugin now handles both dev (Vite) and prod (static)
41
+ development: [vitePlugin],
42
+ documentation: [swaggerPlugin],
43
+ monitoring: [monitoringPlugin]
44
+ } as const
45
+
46
+ // Default plugin configuration
47
+ export const defaultPluginConfig = {
48
+ swagger: {
49
+ enabled: true,
50
+ path: '/swagger',
51
+ title: 'FluxStack API',
52
+ description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
53
+ },
54
+ vite: {
55
+ enabled: true,
56
+ port: 5173,
57
+ host: 'localhost',
58
+ checkInterval: 2000,
59
+ maxRetries: 10,
60
+ timeout: 5000
61
+ },
62
+ static: {
63
+ enabled: true,
64
+ publicDir: 'public',
65
+ distDir: 'dist/client',
66
+ indexFile: 'index.html',
67
+ spa: {
68
+ enabled: true,
69
+ fallback: 'index.html'
70
+ }
71
+ },
72
+ monitoring: {
73
+ enabled: false, // Disabled by default to avoid overhead
74
+ httpMetrics: true,
75
+ systemMetrics: true,
76
+ customMetrics: true,
77
+ collectInterval: 5000,
78
+ retentionPeriod: 300000,
79
+ exporters: [
80
+ {
81
+ type: 'console',
82
+ interval: 30000,
83
+ enabled: false
84
+ }
85
+ ],
86
+ thresholds: {
87
+ responseTime: 1000,
88
+ errorRate: 0.05,
89
+ memoryUsage: 0.8,
90
+ cpuUsage: 0.8
91
+ }
92
+ }
93
+ } as const
94
+
95
+ /**
96
+ * Get default plugins for a specific environment
97
+ */
98
+ export function getDefaultPlugins(environment: 'development' | 'production' | 'test' = 'development') {
99
+ // vitePlugin now auto-detects dev/prod and serves appropriately
100
+ const basePlugins = [vitePlugin]
101
+
102
+ switch (environment) {
103
+ case 'development':
104
+ return [...basePlugins, swaggerPlugin, monitoringPlugin]
105
+ case 'production':
106
+ return [...basePlugins, monitoringPlugin]
107
+ case 'test':
108
+ return [] // Minimal plugins for testing
109
+ default:
110
+ return basePlugins
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Get plugin by name
116
+ */
117
+ export function getBuiltInPlugin(name: string) {
118
+ return builtInPlugins[name as keyof typeof builtInPlugins]
119
+ }
120
+
121
+ /**
122
+ * Check if a plugin is built-in
123
+ */
124
+ export function isBuiltInPlugin(name: string): boolean {
125
+ return name in builtInPlugins
126
+ }
127
+
128
+ /**
129
+ * Get plugins by category
130
+ */
131
+ export function getPluginsByCategory(category: keyof typeof pluginCategories) {
132
+ return pluginCategories[category] || []
133
+ }
134
+
135
135
  export default builtInPlugins
@@ -27,6 +27,7 @@ ${clientLink}
27
27
 
28
28
  export class ${name} extends LiveComponent<typeof ${name}.defaultState> {
29
29
  static componentName = '${name}'
30
+ static publicActions = ['increment', 'decrement', 'reset'] as const
30
31
  static defaultState = {
31
32
  count: 0
32
33
  }
@@ -58,6 +59,7 @@ ${clientLink}
58
59
 
59
60
  export class ${name} extends LiveComponent<typeof ${name}.defaultState> {
60
61
  static componentName = '${name}'
62
+ static publicActions = ['submit', 'reset'] as const
61
63
  static defaultState = {
62
64
  name: '',
63
65
  email: '',
@@ -89,6 +91,7 @@ ${clientLink}
89
91
 
90
92
  export class ${name} extends LiveComponent<typeof ${name}.defaultState> {
91
93
  static componentName = '${name}'
94
+ static publicActions = ['sendMessage', 'setUsername'] as const
92
95
  static defaultState = {
93
96
  messages: [] as Array<{ id: string; text: string; username: string; timestamp: string }>,
94
97
  username: '',
@@ -125,6 +128,7 @@ ${clientLink}
125
128
 
126
129
  export class ${name} extends LiveComponent<typeof ${name}.defaultState> {
127
130
  static componentName = '${name}'
131
+ static publicActions = ['updateMessage', 'increment', 'reset'] as const
128
132
  static defaultState = {
129
133
  message: 'Hello from ${name}!',
130
134
  count: 0
@@ -4,7 +4,7 @@ import { clientConfig } from '@config'
4
4
  import { pluginsConfig } from '@config'
5
5
  import { isDevelopment } from "@core/utils/helpers"
6
6
  import { join } from "path"
7
- import { statSync, existsSync, readdirSync } from "fs"
7
+ import { existsSync } from "fs"
8
8
 
9
9
  type Plugin = FluxStack.Plugin
10
10
 
@@ -21,24 +21,30 @@ const STATIC_MAX_AGE = 31536000
21
21
  const HASHED_EXT = /\.[0-9a-f]{8,}\.\w+$/
22
22
 
23
23
  /**
24
- * Recursively collect all files under `dir` as relative paths (e.g. "/assets/app.abc123.js").
25
- * Runs once at startup in production the build output never changes.
24
+ * Collect all files under `dir` using Bun.Glob (native C++ implementation).
25
+ * Returns a map of relative URL paths absolute filesystem paths.
26
+ *
27
+ * Throws if the directory does not exist so callers get a clear signal
28
+ * instead of silently serving nothing.
26
29
  */
27
- function collectFiles(dir: string, prefix = ''): Map<string, string> {
30
+ function collectFiles(dir: string): Map<string, string> {
31
+ if (!existsSync(dir)) {
32
+ throw new Error(
33
+ `Static file directory "${dir}" does not exist. ` +
34
+ `Run the client build first or check your configuration.`
35
+ )
36
+ }
37
+
28
38
  const map = new Map<string, string>()
29
- try {
30
- const entries = readdirSync(dir, { withFileTypes: true })
31
- for (const entry of entries) {
32
- const rel = prefix + '/' + entry.name
33
- if (entry.isDirectory()) {
34
- for (const [k, v] of collectFiles(join(dir, entry.name), rel)) {
35
- map.set(k, v)
36
- }
37
- } else if (entry.isFile()) {
38
- map.set(rel, join(dir, entry.name))
39
- }
40
- }
41
- } catch {}
39
+ const glob = new Bun.Glob("**/*")
40
+
41
+ for (const relativePath of glob.scanSync({ cwd: dir, onlyFiles: true, dot: true })) {
42
+ // scanSync may return OS-native separators (backslashes on Windows)
43
+ // Normalize to forward slashes so URL lookups always match
44
+ const urlPath = '/' + relativePath.replaceAll('\\', '/')
45
+ map.set(urlPath, join(dir, relativePath))
46
+ }
47
+
42
48
  return map
43
49
  }
44
50
 
@@ -60,6 +66,15 @@ function createStaticFallback() {
60
66
  // Bun.file() handle cache — avoids re-creating handles on repeated requests
61
67
  const fileCache = new Map<string, ReturnType<typeof Bun.file>>()
62
68
 
69
+ // Build a set of paths that have a pre-compressed .gz sibling
70
+ const gzSet = new Set<string>()
71
+ for (const [rel] of fileMap) {
72
+ if (rel.endsWith('.gz')) {
73
+ // "/assets/app.abc123.js.gz" → "/assets/app.abc123.js"
74
+ gzSet.add(rel.slice(0, -3))
75
+ }
76
+ }
77
+
63
78
  return (c: { request?: Request }) => {
64
79
  const req = c.request
65
80
  if (!req) return
@@ -96,6 +111,39 @@ function createStaticFallback() {
96
111
  // O(1) lookup in pre-scanned file map
97
112
  const absolutePath = fileMap.get(pathname)
98
113
  if (absolutePath) {
114
+ // Check for pre-compressed .gz variant
115
+ const acceptEncoding = req.headers.get('accept-encoding') || ''
116
+ if (gzSet.has(pathname) && acceptEncoding.includes('gzip')) {
117
+ const gzPath = pathname + '.gz'
118
+ const gzAbsolute = fileMap.get(gzPath)
119
+ if (gzAbsolute) {
120
+ let gzFile = fileCache.get(gzPath)
121
+ if (!gzFile) {
122
+ gzFile = Bun.file(gzAbsolute)
123
+ fileCache.set(gzPath, gzFile)
124
+ }
125
+
126
+ // Determine original content type from the uncompressed file
127
+ let origFile = fileCache.get(pathname)
128
+ if (!origFile) {
129
+ origFile = Bun.file(absolutePath)
130
+ fileCache.set(pathname, origFile)
131
+ }
132
+
133
+ const headers: Record<string, string> = {
134
+ 'Content-Encoding': 'gzip',
135
+ 'Content-Type': origFile.type || 'application/octet-stream',
136
+ 'Vary': 'Accept-Encoding',
137
+ }
138
+
139
+ if (HASHED_EXT.test(pathname)) {
140
+ headers['Cache-Control'] = `public, max-age=${STATIC_MAX_AGE}, immutable`
141
+ }
142
+
143
+ return new Response(gzFile, { headers })
144
+ }
145
+ }
146
+
99
147
  let file = fileCache.get(pathname)
100
148
  if (!file) {
101
149
  file = Bun.file(absolutePath)
@@ -114,14 +162,19 @@ function createStaticFallback() {
114
162
  return file
115
163
  }
116
164
 
117
- // SPA fallback: serve index.html for unmatched routes
165
+ // SPA fallback: serve index.html for unmatched routes with no-cache
166
+ // so the browser always checks for a newer version on deploy
118
167
  if (indexFile) {
119
- return indexFile
168
+ return new Response(indexFile, {
169
+ headers: {
170
+ 'Cache-Control': 'no-cache',
171
+ }
172
+ })
120
173
  }
121
174
  }
122
175
  }
123
176
 
124
- /** Proxy request to Vite dev server */
177
+ /** Proxy request to Vite dev server — streams the response body */
125
178
  async function proxyToVite(ctx: RequestContext): Promise<void> {
126
179
  const { host, port } = clientConfig.vite
127
180
 
@@ -143,7 +196,8 @@ async function proxyToVite(ctx: RequestContext): Promise<void> {
143
196
  })
144
197
 
145
198
  ctx.handled = true
146
- ctx.response = new Response(await response.arrayBuffer(), {
199
+ // Stream the response body instead of buffering the entire payload in memory
200
+ ctx.response = new Response(response.body, {
147
201
  status: response.status,
148
202
  statusText: response.statusText,
149
203
  headers: response.headers
@@ -1,16 +1,15 @@
1
- // FluxStack framework exports
2
- export { FluxStackFramework } from "../framework/server"
3
- export { vitePlugin, staticPlugin } from "../plugins/built-in"
4
- export { swaggerPlugin } from "../plugins/built-in/swagger"
5
- export { PluginRegistry } from "../plugins/registry"
6
- export * from "../types"
7
-
8
- // Live Components exports
9
- export { liveComponentsPlugin } from "./live/websocket-plugin"
10
- export { componentRegistry } from "./live/ComponentRegistry"
11
- export { LiveComponent } from "../types/types"
12
-
13
- // Static Files Plugin
14
- export { staticFilesPlugin } from "./plugins/static-files-plugin"
15
-
1
+ // FluxStack framework exports
2
+ export { FluxStackFramework } from "../framework/server"
3
+ export { vitePlugin, staticPlugin } from "../plugins/built-in"
4
+ export { swaggerPlugin } from "../plugins/built-in/swagger"
5
+ export { PluginRegistry } from "../plugins/registry"
6
+ export * from "../types"
7
+
8
+ // Live Components exports
9
+ export { liveComponentsPlugin, componentRegistry } from "./live"
10
+ export { LiveComponent } from "../types/types"
11
+
12
+ // Static Files Plugin
13
+ export { staticFilesPlugin } from "./plugins/static-files-plugin"
14
+
16
15
  export * from "../types/types"
@@ -1,6 +1,6 @@
1
1
  // 🔥 Auto-generated Live Components Registration
2
2
  // This file is automatically generated during build time - DO NOT EDIT MANUALLY
3
- // Generated at: 2026-02-17T00:55:07.182Z
3
+ // Generated at: 2026-03-01T19:00:29.650Z
4
4
 
5
5
  import { LiveAdminPanel } from "@app/server/live/LiveAdminPanel"
6
6
  import { LiveChat } from "@app/server/live/LiveChat"
@@ -9,8 +9,9 @@ import { LiveForm } from "@app/server/live/LiveForm"
9
9
  import { LiveLocalCounter } from "@app/server/live/LiveLocalCounter"
10
10
  import { LiveProtectedChat } from "@app/server/live/LiveProtectedChat"
11
11
  import { LiveRoomChat } from "@app/server/live/LiveRoomChat"
12
+ import { LiveTodoList } from "@app/server/live/LiveTodoList"
12
13
  import { LiveUpload } from "@app/server/live/LiveUpload"
13
- import { componentRegistry } from "@core/server/live/ComponentRegistry"
14
+ import { componentRegistry } from "@core/server/live"
14
15
 
15
16
  // Register all components statically for production bundle
16
17
  function registerAllComponents() {
@@ -23,9 +24,10 @@ function registerAllComponents() {
23
24
  componentRegistry.registerComponentClass('LiveLocalCounter', LiveLocalCounter)
24
25
  componentRegistry.registerComponentClass('LiveProtectedChat', LiveProtectedChat)
25
26
  componentRegistry.registerComponentClass('LiveRoomChat', LiveRoomChat)
27
+ componentRegistry.registerComponentClass('LiveTodoList', LiveTodoList)
26
28
  componentRegistry.registerComponentClass('LiveUpload', LiveUpload)
27
29
 
28
- console.log('📝 Live components registered successfully! (8 components)')
30
+ console.log('📝 Live components registered successfully! (9 components)')
29
31
  } catch (error) {
30
32
  console.warn('⚠️ Error registering components:', error)
31
33
  }
@@ -43,5 +45,6 @@ export {
43
45
  LiveLocalCounter,
44
46
  LiveProtectedChat,
45
47
  LiveRoomChat,
48
+ LiveTodoList,
46
49
  LiveUpload
47
50
  }