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.
- package/.dockerignore +1 -2
- package/Dockerfile +8 -8
- package/LLMD/INDEX.md +64 -0
- package/LLMD/MAINTENANCE.md +197 -0
- package/LLMD/MIGRATION.md +156 -0
- package/LLMD/config/.gitkeep +1 -0
- package/LLMD/config/declarative-system.md +268 -0
- package/LLMD/config/environment-vars.md +327 -0
- package/LLMD/config/runtime-reload.md +401 -0
- package/LLMD/core/.gitkeep +1 -0
- package/LLMD/core/build-system.md +599 -0
- package/LLMD/core/framework-lifecycle.md +229 -0
- package/LLMD/core/plugin-system.md +451 -0
- package/LLMD/patterns/.gitkeep +1 -0
- package/LLMD/patterns/anti-patterns.md +297 -0
- package/LLMD/patterns/project-structure.md +264 -0
- package/LLMD/patterns/type-safety.md +440 -0
- package/LLMD/reference/.gitkeep +1 -0
- package/LLMD/reference/cli-commands.md +250 -0
- package/LLMD/reference/plugin-hooks.md +357 -0
- package/LLMD/reference/routing.md +39 -0
- package/LLMD/reference/troubleshooting.md +364 -0
- package/LLMD/resources/.gitkeep +1 -0
- package/LLMD/resources/controllers.md +465 -0
- package/LLMD/resources/live-components.md +703 -0
- package/LLMD/resources/live-rooms.md +482 -0
- package/LLMD/resources/live-upload.md +130 -0
- package/LLMD/resources/plugins-external.md +617 -0
- package/LLMD/resources/routes-eden.md +254 -0
- package/README.md +37 -17
- package/app/client/index.html +0 -1
- package/app/client/src/App.tsx +107 -150
- package/app/client/src/components/AppLayout.tsx +68 -0
- package/app/client/src/components/BackButton.tsx +13 -0
- package/app/client/src/components/DemoPage.tsx +20 -0
- package/app/client/src/components/LiveUploadWidget.tsx +204 -0
- package/app/client/src/lib/eden-api.ts +85 -60
- package/app/client/src/live/ChatDemo.tsx +107 -0
- package/app/client/src/live/CounterDemo.tsx +206 -0
- package/app/client/src/live/FormDemo.tsx +119 -0
- package/app/client/src/live/RoomChatDemo.tsx +242 -0
- package/app/client/src/live/UploadDemo.tsx +21 -0
- package/app/client/src/main.tsx +4 -1
- package/app/client/src/pages/ApiTestPage.tsx +108 -0
- package/app/client/src/pages/HomePage.tsx +76 -0
- package/app/server/app.ts +1 -4
- package/app/server/controllers/users.controller.ts +36 -44
- package/app/server/index.ts +25 -35
- package/app/server/live/LiveChat.ts +77 -0
- package/app/server/live/LiveCounter.ts +67 -0
- package/app/server/live/LiveForm.ts +63 -0
- package/app/server/live/LiveLocalCounter.ts +32 -0
- package/app/server/live/LiveRoomChat.ts +285 -0
- package/app/server/live/LiveUpload.ts +81 -0
- package/app/server/routes/index.ts +3 -1
- package/app/server/routes/room.routes.ts +117 -0
- package/app/server/routes/users.routes.ts +35 -27
- package/app/shared/types/index.ts +14 -2
- package/config/app.config.ts +2 -62
- package/config/client.config.ts +2 -95
- package/config/database.config.ts +2 -99
- package/config/fluxstack.config.ts +25 -45
- package/config/index.ts +57 -38
- package/config/monitoring.config.ts +2 -114
- package/config/plugins.config.ts +2 -80
- package/config/server.config.ts +2 -68
- package/config/services.config.ts +2 -130
- package/config/system/app.config.ts +29 -0
- package/config/system/build.config.ts +49 -0
- package/config/system/client.config.ts +68 -0
- package/config/system/database.config.ts +17 -0
- package/config/system/fluxstack.config.ts +114 -0
- package/config/{logger.config.ts → system/logger.config.ts} +3 -1
- package/config/system/monitoring.config.ts +114 -0
- package/config/system/plugins.config.ts +84 -0
- package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
- package/config/system/server.config.ts +68 -0
- package/config/system/services.config.ts +46 -0
- package/config/{system.config.ts → system/system.config.ts} +1 -1
- package/core/build/flux-plugins-generator.ts +325 -325
- package/core/build/index.ts +39 -27
- package/core/build/live-components-generator.ts +3 -3
- package/core/build/optimizer.ts +235 -235
- package/core/cli/command-registry.ts +6 -4
- package/core/cli/commands/build.ts +79 -0
- package/core/cli/commands/create.ts +54 -0
- package/core/cli/commands/dev.ts +101 -0
- package/core/cli/commands/help.ts +34 -0
- package/core/cli/commands/index.ts +34 -0
- package/core/cli/commands/make-plugin.ts +90 -0
- package/core/cli/commands/plugin-add.ts +197 -0
- package/core/cli/commands/plugin-deps.ts +2 -2
- package/core/cli/commands/plugin-list.ts +208 -0
- package/core/cli/commands/plugin-remove.ts +170 -0
- package/core/cli/generators/component.ts +769 -769
- package/core/cli/generators/controller.ts +1 -1
- package/core/cli/generators/index.ts +146 -146
- package/core/cli/generators/interactive.ts +227 -227
- package/core/cli/generators/plugin.ts +2 -2
- package/core/cli/generators/prompts.ts +82 -82
- package/core/cli/generators/route.ts +6 -6
- package/core/cli/generators/service.ts +2 -2
- package/core/cli/generators/template-engine.ts +4 -3
- package/core/cli/generators/types.ts +2 -2
- package/core/cli/generators/utils.ts +191 -191
- package/core/cli/index.ts +115 -686
- package/core/cli/plugin-discovery.ts +2 -2
- package/core/client/LiveComponentsProvider.tsx +60 -8
- package/core/client/api/eden.ts +183 -0
- package/core/client/api/index.ts +11 -0
- package/core/client/components/Live.tsx +104 -0
- package/core/client/fluxstack.ts +1 -9
- package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
- package/core/client/hooks/state-validator.ts +1 -1
- package/core/client/hooks/useAuth.ts +48 -48
- package/core/client/hooks/useChunkedUpload.ts +85 -35
- package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
- package/core/client/hooks/useLiveComponent.ts +800 -0
- package/core/client/hooks/useLiveUpload.ts +71 -0
- package/core/client/hooks/useRoom.ts +409 -0
- package/core/client/hooks/useRoomProxy.ts +382 -0
- package/core/client/index.ts +17 -68
- package/core/client/standalone-entry.ts +8 -0
- package/core/client/standalone.ts +74 -53
- package/core/client/state/createStore.ts +192 -192
- package/core/client/state/index.ts +14 -14
- package/core/config/index.ts +70 -291
- package/core/config/schema.ts +42 -723
- package/core/framework/client.ts +131 -131
- package/core/framework/index.ts +7 -7
- package/core/framework/server.ts +47 -40
- package/core/framework/types.ts +2 -2
- package/core/index.ts +23 -4
- package/core/live/ComponentRegistry.ts +3 -3
- package/core/live/types.ts +77 -0
- package/core/plugins/built-in/index.ts +134 -134
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1066
- package/core/plugins/built-in/live-components/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +111 -47
- package/core/plugins/built-in/static/index.ts +1 -1
- package/core/plugins/built-in/swagger/index.ts +68 -265
- package/core/plugins/built-in/vite/index.ts +85 -185
- package/core/plugins/built-in/vite/vite-dev.ts +10 -16
- package/core/plugins/config.ts +9 -7
- package/core/plugins/dependency-manager.ts +31 -1
- package/core/plugins/discovery.ts +19 -7
- package/core/plugins/executor.ts +2 -2
- package/core/plugins/index.ts +203 -203
- package/core/plugins/manager.ts +27 -39
- package/core/plugins/module-resolver.ts +19 -8
- package/core/plugins/registry.ts +255 -19
- package/core/plugins/types.ts +20 -53
- package/core/server/framework.ts +66 -43
- package/core/server/index.ts +15 -15
- package/core/server/live/ComponentRegistry.ts +78 -71
- package/core/server/live/FileUploadManager.ts +23 -10
- package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
- package/core/server/live/LiveRoomManager.ts +261 -0
- package/core/server/live/RoomEventBus.ts +234 -0
- package/core/server/live/RoomStateManager.ts +172 -0
- package/core/server/live/StateSignature.ts +643 -643
- package/core/server/live/WebSocketConnectionManager.ts +30 -19
- package/core/server/live/auto-generated-components.ts +21 -9
- package/core/server/live/index.ts +14 -0
- package/core/server/live/websocket-plugin.ts +214 -67
- package/core/server/middleware/elysia-helpers.ts +7 -2
- package/core/server/middleware/errorHandling.ts +1 -1
- package/core/server/middleware/index.ts +31 -31
- package/core/server/plugins/database.ts +180 -180
- package/core/server/plugins/static-files-plugin.ts +69 -69
- package/core/server/plugins/swagger.ts +1 -1
- package/core/server/rooms/RoomBroadcaster.ts +357 -0
- package/core/server/rooms/RoomSystem.ts +463 -0
- package/core/server/rooms/index.ts +13 -0
- package/core/server/services/BaseService.ts +1 -1
- package/core/server/services/ServiceContainer.ts +1 -1
- package/core/server/services/index.ts +8 -8
- package/core/templates/create-project.ts +12 -12
- package/core/testing/index.ts +9 -9
- package/core/testing/setup.ts +73 -73
- package/core/types/api.ts +168 -168
- package/core/types/build.ts +219 -219
- package/core/types/config.ts +56 -26
- package/core/types/index.ts +4 -4
- package/core/types/plugin.ts +107 -107
- package/core/types/types.ts +353 -14
- package/core/utils/build-logger.ts +324 -324
- package/core/utils/config-schema.ts +480 -480
- package/core/utils/env.ts +2 -8
- package/core/utils/errors/codes.ts +114 -114
- package/core/utils/errors/handlers.ts +36 -1
- package/core/utils/errors/index.ts +49 -5
- package/core/utils/errors/middleware.ts +113 -113
- package/core/utils/helpers.ts +6 -16
- package/core/utils/index.ts +17 -17
- package/core/utils/logger/colors.ts +114 -114
- package/core/utils/logger/config.ts +13 -9
- package/core/utils/logger/formatter.ts +82 -82
- package/core/utils/logger/group-logger.ts +101 -101
- package/core/utils/logger/index.ts +6 -1
- package/core/utils/logger/stack-trace.ts +3 -1
- package/core/utils/logger/startup-banner.ts +82 -82
- package/core/utils/logger/winston-logger.ts +152 -152
- package/core/utils/monitoring/index.ts +211 -211
- package/core/utils/sync-version.ts +66 -66
- package/core/utils/version.ts +1 -1
- package/create-fluxstack.ts +8 -7
- package/package.json +12 -13
- package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
- package/plugins/crypto-auth/client/components/index.ts +11 -11
- package/plugins/crypto-auth/client/index.ts +11 -11
- package/plugins/crypto-auth/config/index.ts +1 -1
- package/plugins/crypto-auth/index.ts +4 -4
- package/plugins/crypto-auth/package.json +65 -65
- package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
- package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
- package/plugins/crypto-auth/server/index.ts +21 -21
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
- package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
- package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
- package/tsconfig.api-strict.json +16 -0
- package/tsconfig.json +48 -52
- package/{app/client/tsconfig.node.json → tsconfig.node.json} +25 -25
- package/types/global.d.ts +29 -29
- package/types/vitest.d.ts +8 -8
- package/vite.config.ts +38 -62
- package/vitest.config.live.ts +10 -9
- package/vitest.config.ts +29 -17
- package/app/client/README.md +0 -69
- package/app/client/SIMPLIFICATION.md +0 -140
- package/app/client/frontend-only.ts +0 -12
- package/app/client/src/live/FileUploadExample.tsx +0 -359
- package/app/client/src/live/MinimalLiveClock.tsx +0 -47
- package/app/client/src/live/QuickUploadTest.tsx +0 -193
- package/app/client/tsconfig.app.json +0 -45
- package/app/client/tsconfig.json +0 -7
- package/app/client/zustand-setup.md +0 -65
- package/app/server/backend-only.ts +0 -18
- package/app/server/live/LiveClockComponent.ts +0 -215
- package/app/server/live/LiveFileUploadComponent.ts +0 -77
- package/app/server/routes/env-test.ts +0 -110
- package/core/client/hooks/index.ts +0 -7
- package/core/client/hooks/useHybridLiveComponent.ts +0 -685
- package/core/client/hooks/useTypedLiveComponent.ts +0 -133
- package/core/client/hooks/useWebSocket.ts +0 -361
- package/core/config/env.ts +0 -546
- package/core/config/loader.ts +0 -522
- package/core/config/runtime-config.ts +0 -327
- package/core/config/validator.ts +0 -540
- package/core/server/backend-entry.ts +0 -51
- package/core/server/standalone.ts +0 -106
- package/core/utils/regenerate-files.ts +0 -69
- package/fluxstack.config.ts +0 -354
|
@@ -1,215 +1,215 @@
|
|
|
1
|
-
// 🚀 Adaptive Chunk Sizing - Dynamic chunk size adjustment based on connection speed
|
|
2
|
-
// Automatically optimizes upload speed by adjusting chunk sizes
|
|
3
|
-
|
|
4
|
-
export interface AdaptiveChunkConfig {
|
|
5
|
-
minChunkSize: number // Minimum chunk size (default: 16KB)
|
|
6
|
-
maxChunkSize: number // Maximum chunk size (default: 1MB)
|
|
7
|
-
initialChunkSize: number // Starting chunk size (default: 64KB)
|
|
8
|
-
targetLatency: number // Target latency per chunk in ms (default: 200ms)
|
|
9
|
-
adjustmentFactor: number // How aggressively to adjust (default: 1.5)
|
|
10
|
-
measurementWindow: number // Number of chunks to measure (default: 3)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface ChunkMetrics {
|
|
14
|
-
chunkIndex: number
|
|
15
|
-
chunkSize: number
|
|
16
|
-
startTime: number
|
|
17
|
-
endTime: number
|
|
18
|
-
latency: number
|
|
19
|
-
throughput: number // bytes per second
|
|
20
|
-
success: boolean
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class AdaptiveChunkSizer {
|
|
24
|
-
private config: Required<AdaptiveChunkConfig>
|
|
25
|
-
private currentChunkSize: number
|
|
26
|
-
private metrics: ChunkMetrics[] = []
|
|
27
|
-
private consecutiveErrors = 0
|
|
28
|
-
private consecutiveSuccesses = 0
|
|
29
|
-
|
|
30
|
-
constructor(config: Partial<AdaptiveChunkConfig> = {}) {
|
|
31
|
-
this.config = {
|
|
32
|
-
minChunkSize: config.minChunkSize ?? 16 * 1024, // 16KB
|
|
33
|
-
maxChunkSize: config.maxChunkSize ?? 1024 * 1024, // 1MB
|
|
34
|
-
initialChunkSize: config.initialChunkSize ?? 64 * 1024, // 64KB
|
|
35
|
-
targetLatency: config.targetLatency ?? 200, // 200ms
|
|
36
|
-
adjustmentFactor: config.adjustmentFactor ?? 1.5,
|
|
37
|
-
measurementWindow: config.measurementWindow ?? 3
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
this.currentChunkSize = this.config.initialChunkSize
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get the current optimal chunk size
|
|
45
|
-
*/
|
|
46
|
-
getChunkSize(): number {
|
|
47
|
-
return this.currentChunkSize
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Record the start of a chunk upload
|
|
52
|
-
*/
|
|
53
|
-
recordChunkStart(chunkIndex: number): number {
|
|
54
|
-
return Date.now()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Record the completion of a chunk upload and adjust chunk size
|
|
59
|
-
*/
|
|
60
|
-
recordChunkComplete(
|
|
61
|
-
chunkIndex: number,
|
|
62
|
-
chunkSize: number,
|
|
63
|
-
startTime: number,
|
|
64
|
-
success: boolean
|
|
65
|
-
): void {
|
|
66
|
-
const endTime = Date.now()
|
|
67
|
-
const latency = endTime - startTime
|
|
68
|
-
const throughput = success ? (chunkSize / latency) * 1000 : 0 // bytes per second
|
|
69
|
-
|
|
70
|
-
const metric: ChunkMetrics = {
|
|
71
|
-
chunkIndex,
|
|
72
|
-
chunkSize,
|
|
73
|
-
startTime,
|
|
74
|
-
endTime,
|
|
75
|
-
latency,
|
|
76
|
-
throughput,
|
|
77
|
-
success
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this.metrics.push(metric)
|
|
81
|
-
|
|
82
|
-
// Keep only recent measurements
|
|
83
|
-
if (this.metrics.length > this.config.measurementWindow * 2) {
|
|
84
|
-
this.metrics = this.metrics.slice(-this.config.measurementWindow * 2)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (success) {
|
|
88
|
-
this.consecutiveSuccesses++
|
|
89
|
-
this.consecutiveErrors = 0
|
|
90
|
-
this.adjustChunkSizeUp(latency)
|
|
91
|
-
} else {
|
|
92
|
-
this.consecutiveErrors++
|
|
93
|
-
this.consecutiveSuccesses = 0
|
|
94
|
-
this.adjustChunkSizeDown()
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
console.log(`📊 Adaptive Chunk Stats:`, {
|
|
98
|
-
chunkIndex,
|
|
99
|
-
currentSize: this.formatBytes(this.currentChunkSize),
|
|
100
|
-
latency: `${latency}ms`,
|
|
101
|
-
throughput: `${this.formatBytes(throughput)}/s`,
|
|
102
|
-
avgThroughput: `${this.formatBytes(this.getAverageThroughput())}/s`,
|
|
103
|
-
success
|
|
104
|
-
})
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Increase chunk size if connection is fast
|
|
109
|
-
*/
|
|
110
|
-
private adjustChunkSizeUp(latency: number): void {
|
|
111
|
-
// Only increase if we have enough successful measurements
|
|
112
|
-
if (this.consecutiveSuccesses < 2) return
|
|
113
|
-
|
|
114
|
-
// Only increase if latency is below target
|
|
115
|
-
if (latency > this.config.targetLatency) return
|
|
116
|
-
|
|
117
|
-
// Calculate new chunk size based on how much faster we are than target
|
|
118
|
-
const latencyRatio = this.config.targetLatency / latency
|
|
119
|
-
let newSize = Math.floor(this.currentChunkSize * Math.min(latencyRatio, this.config.adjustmentFactor))
|
|
120
|
-
|
|
121
|
-
// Cap at max chunk size
|
|
122
|
-
newSize = Math.min(newSize, this.config.maxChunkSize)
|
|
123
|
-
|
|
124
|
-
if (newSize > this.currentChunkSize) {
|
|
125
|
-
console.log(`⬆️ Increasing chunk size: ${this.formatBytes(this.currentChunkSize)} → ${this.formatBytes(newSize)}`)
|
|
126
|
-
this.currentChunkSize = newSize
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Decrease chunk size if connection is slow or unstable
|
|
132
|
-
*/
|
|
133
|
-
private adjustChunkSizeDown(): void {
|
|
134
|
-
// Decrease more aggressively on errors
|
|
135
|
-
const decreaseFactor = this.consecutiveErrors > 1 ? 2 : this.config.adjustmentFactor
|
|
136
|
-
|
|
137
|
-
let newSize = Math.floor(this.currentChunkSize / decreaseFactor)
|
|
138
|
-
|
|
139
|
-
// Cap at min chunk size
|
|
140
|
-
newSize = Math.max(newSize, this.config.minChunkSize)
|
|
141
|
-
|
|
142
|
-
if (newSize < this.currentChunkSize) {
|
|
143
|
-
console.log(`⬇️ Decreasing chunk size: ${this.formatBytes(this.currentChunkSize)} → ${this.formatBytes(newSize)}`)
|
|
144
|
-
this.currentChunkSize = newSize
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Get average throughput from recent measurements
|
|
150
|
-
*/
|
|
151
|
-
getAverageThroughput(): number {
|
|
152
|
-
if (this.metrics.length === 0) return 0
|
|
153
|
-
|
|
154
|
-
const recentMetrics = this.metrics
|
|
155
|
-
.slice(-this.config.measurementWindow)
|
|
156
|
-
.filter(m => m.success)
|
|
157
|
-
|
|
158
|
-
if (recentMetrics.length === 0) return 0
|
|
159
|
-
|
|
160
|
-
const totalThroughput = recentMetrics.reduce((sum, m) => sum + m.throughput, 0)
|
|
161
|
-
return totalThroughput / recentMetrics.length
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Get average latency from recent measurements
|
|
166
|
-
*/
|
|
167
|
-
getAverageLatency(): number {
|
|
168
|
-
if (this.metrics.length === 0) return 0
|
|
169
|
-
|
|
170
|
-
const recentMetrics = this.metrics
|
|
171
|
-
.slice(-this.config.measurementWindow)
|
|
172
|
-
.filter(m => m.success)
|
|
173
|
-
|
|
174
|
-
if (recentMetrics.length === 0) return 0
|
|
175
|
-
|
|
176
|
-
const totalLatency = recentMetrics.reduce((sum, m) => sum + m.latency, 0)
|
|
177
|
-
return totalLatency / recentMetrics.length
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Get current performance statistics
|
|
182
|
-
*/
|
|
183
|
-
getStats() {
|
|
184
|
-
return {
|
|
185
|
-
currentChunkSize: this.currentChunkSize,
|
|
186
|
-
averageThroughput: this.getAverageThroughput(),
|
|
187
|
-
averageLatency: this.getAverageLatency(),
|
|
188
|
-
consecutiveSuccesses: this.consecutiveSuccesses,
|
|
189
|
-
consecutiveErrors: this.consecutiveErrors,
|
|
190
|
-
totalMeasurements: this.metrics.length,
|
|
191
|
-
config: this.config
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Reset the adaptive chunking state
|
|
197
|
-
*/
|
|
198
|
-
reset(): void {
|
|
199
|
-
this.currentChunkSize = this.config.initialChunkSize
|
|
200
|
-
this.metrics = []
|
|
201
|
-
this.consecutiveErrors = 0
|
|
202
|
-
this.consecutiveSuccesses = 0
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Format bytes for display
|
|
207
|
-
*/
|
|
208
|
-
private formatBytes(bytes: number): string {
|
|
209
|
-
if (bytes === 0) return '0 B'
|
|
210
|
-
const k = 1024
|
|
211
|
-
const sizes = ['B', 'KB', 'MB', 'GB']
|
|
212
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
213
|
-
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
|
|
214
|
-
}
|
|
215
|
-
}
|
|
1
|
+
// 🚀 Adaptive Chunk Sizing - Dynamic chunk size adjustment based on connection speed
|
|
2
|
+
// Automatically optimizes upload speed by adjusting chunk sizes
|
|
3
|
+
|
|
4
|
+
export interface AdaptiveChunkConfig {
|
|
5
|
+
minChunkSize: number // Minimum chunk size (default: 16KB)
|
|
6
|
+
maxChunkSize: number // Maximum chunk size (default: 1MB)
|
|
7
|
+
initialChunkSize: number // Starting chunk size (default: 64KB)
|
|
8
|
+
targetLatency: number // Target latency per chunk in ms (default: 200ms)
|
|
9
|
+
adjustmentFactor: number // How aggressively to adjust (default: 1.5)
|
|
10
|
+
measurementWindow: number // Number of chunks to measure (default: 3)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ChunkMetrics {
|
|
14
|
+
chunkIndex: number
|
|
15
|
+
chunkSize: number
|
|
16
|
+
startTime: number
|
|
17
|
+
endTime: number
|
|
18
|
+
latency: number
|
|
19
|
+
throughput: number // bytes per second
|
|
20
|
+
success: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class AdaptiveChunkSizer {
|
|
24
|
+
private config: Required<AdaptiveChunkConfig>
|
|
25
|
+
private currentChunkSize: number
|
|
26
|
+
private metrics: ChunkMetrics[] = []
|
|
27
|
+
private consecutiveErrors = 0
|
|
28
|
+
private consecutiveSuccesses = 0
|
|
29
|
+
|
|
30
|
+
constructor(config: Partial<AdaptiveChunkConfig> = {}) {
|
|
31
|
+
this.config = {
|
|
32
|
+
minChunkSize: config.minChunkSize ?? 16 * 1024, // 16KB
|
|
33
|
+
maxChunkSize: config.maxChunkSize ?? 1024 * 1024, // 1MB
|
|
34
|
+
initialChunkSize: config.initialChunkSize ?? 64 * 1024, // 64KB
|
|
35
|
+
targetLatency: config.targetLatency ?? 200, // 200ms
|
|
36
|
+
adjustmentFactor: config.adjustmentFactor ?? 1.5,
|
|
37
|
+
measurementWindow: config.measurementWindow ?? 3
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.currentChunkSize = this.config.initialChunkSize
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the current optimal chunk size
|
|
45
|
+
*/
|
|
46
|
+
getChunkSize(): number {
|
|
47
|
+
return this.currentChunkSize
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Record the start of a chunk upload
|
|
52
|
+
*/
|
|
53
|
+
recordChunkStart(chunkIndex: number): number {
|
|
54
|
+
return Date.now()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Record the completion of a chunk upload and adjust chunk size
|
|
59
|
+
*/
|
|
60
|
+
recordChunkComplete(
|
|
61
|
+
chunkIndex: number,
|
|
62
|
+
chunkSize: number,
|
|
63
|
+
startTime: number,
|
|
64
|
+
success: boolean
|
|
65
|
+
): void {
|
|
66
|
+
const endTime = Date.now()
|
|
67
|
+
const latency = endTime - startTime
|
|
68
|
+
const throughput = success ? (chunkSize / latency) * 1000 : 0 // bytes per second
|
|
69
|
+
|
|
70
|
+
const metric: ChunkMetrics = {
|
|
71
|
+
chunkIndex,
|
|
72
|
+
chunkSize,
|
|
73
|
+
startTime,
|
|
74
|
+
endTime,
|
|
75
|
+
latency,
|
|
76
|
+
throughput,
|
|
77
|
+
success
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.metrics.push(metric)
|
|
81
|
+
|
|
82
|
+
// Keep only recent measurements
|
|
83
|
+
if (this.metrics.length > this.config.measurementWindow * 2) {
|
|
84
|
+
this.metrics = this.metrics.slice(-this.config.measurementWindow * 2)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (success) {
|
|
88
|
+
this.consecutiveSuccesses++
|
|
89
|
+
this.consecutiveErrors = 0
|
|
90
|
+
this.adjustChunkSizeUp(latency)
|
|
91
|
+
} else {
|
|
92
|
+
this.consecutiveErrors++
|
|
93
|
+
this.consecutiveSuccesses = 0
|
|
94
|
+
this.adjustChunkSizeDown()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log(`📊 Adaptive Chunk Stats:`, {
|
|
98
|
+
chunkIndex,
|
|
99
|
+
currentSize: this.formatBytes(this.currentChunkSize),
|
|
100
|
+
latency: `${latency}ms`,
|
|
101
|
+
throughput: `${this.formatBytes(throughput)}/s`,
|
|
102
|
+
avgThroughput: `${this.formatBytes(this.getAverageThroughput())}/s`,
|
|
103
|
+
success
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Increase chunk size if connection is fast
|
|
109
|
+
*/
|
|
110
|
+
private adjustChunkSizeUp(latency: number): void {
|
|
111
|
+
// Only increase if we have enough successful measurements
|
|
112
|
+
if (this.consecutiveSuccesses < 2) return
|
|
113
|
+
|
|
114
|
+
// Only increase if latency is below target
|
|
115
|
+
if (latency > this.config.targetLatency) return
|
|
116
|
+
|
|
117
|
+
// Calculate new chunk size based on how much faster we are than target
|
|
118
|
+
const latencyRatio = this.config.targetLatency / latency
|
|
119
|
+
let newSize = Math.floor(this.currentChunkSize * Math.min(latencyRatio, this.config.adjustmentFactor))
|
|
120
|
+
|
|
121
|
+
// Cap at max chunk size
|
|
122
|
+
newSize = Math.min(newSize, this.config.maxChunkSize)
|
|
123
|
+
|
|
124
|
+
if (newSize > this.currentChunkSize) {
|
|
125
|
+
console.log(`⬆️ Increasing chunk size: ${this.formatBytes(this.currentChunkSize)} → ${this.formatBytes(newSize)}`)
|
|
126
|
+
this.currentChunkSize = newSize
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Decrease chunk size if connection is slow or unstable
|
|
132
|
+
*/
|
|
133
|
+
private adjustChunkSizeDown(): void {
|
|
134
|
+
// Decrease more aggressively on errors
|
|
135
|
+
const decreaseFactor = this.consecutiveErrors > 1 ? 2 : this.config.adjustmentFactor
|
|
136
|
+
|
|
137
|
+
let newSize = Math.floor(this.currentChunkSize / decreaseFactor)
|
|
138
|
+
|
|
139
|
+
// Cap at min chunk size
|
|
140
|
+
newSize = Math.max(newSize, this.config.minChunkSize)
|
|
141
|
+
|
|
142
|
+
if (newSize < this.currentChunkSize) {
|
|
143
|
+
console.log(`⬇️ Decreasing chunk size: ${this.formatBytes(this.currentChunkSize)} → ${this.formatBytes(newSize)}`)
|
|
144
|
+
this.currentChunkSize = newSize
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get average throughput from recent measurements
|
|
150
|
+
*/
|
|
151
|
+
getAverageThroughput(): number {
|
|
152
|
+
if (this.metrics.length === 0) return 0
|
|
153
|
+
|
|
154
|
+
const recentMetrics = this.metrics
|
|
155
|
+
.slice(-this.config.measurementWindow)
|
|
156
|
+
.filter(m => m.success)
|
|
157
|
+
|
|
158
|
+
if (recentMetrics.length === 0) return 0
|
|
159
|
+
|
|
160
|
+
const totalThroughput = recentMetrics.reduce((sum, m) => sum + m.throughput, 0)
|
|
161
|
+
return totalThroughput / recentMetrics.length
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get average latency from recent measurements
|
|
166
|
+
*/
|
|
167
|
+
getAverageLatency(): number {
|
|
168
|
+
if (this.metrics.length === 0) return 0
|
|
169
|
+
|
|
170
|
+
const recentMetrics = this.metrics
|
|
171
|
+
.slice(-this.config.measurementWindow)
|
|
172
|
+
.filter(m => m.success)
|
|
173
|
+
|
|
174
|
+
if (recentMetrics.length === 0) return 0
|
|
175
|
+
|
|
176
|
+
const totalLatency = recentMetrics.reduce((sum, m) => sum + m.latency, 0)
|
|
177
|
+
return totalLatency / recentMetrics.length
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get current performance statistics
|
|
182
|
+
*/
|
|
183
|
+
getStats() {
|
|
184
|
+
return {
|
|
185
|
+
currentChunkSize: this.currentChunkSize,
|
|
186
|
+
averageThroughput: this.getAverageThroughput(),
|
|
187
|
+
averageLatency: this.getAverageLatency(),
|
|
188
|
+
consecutiveSuccesses: this.consecutiveSuccesses,
|
|
189
|
+
consecutiveErrors: this.consecutiveErrors,
|
|
190
|
+
totalMeasurements: this.metrics.length,
|
|
191
|
+
config: this.config
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Reset the adaptive chunking state
|
|
197
|
+
*/
|
|
198
|
+
reset(): void {
|
|
199
|
+
this.currentChunkSize = this.config.initialChunkSize
|
|
200
|
+
this.metrics = []
|
|
201
|
+
this.consecutiveErrors = 0
|
|
202
|
+
this.consecutiveSuccesses = 0
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Format bytes for display
|
|
207
|
+
*/
|
|
208
|
+
private formatBytes(bytes: number): string {
|
|
209
|
+
if (bytes === 0) return '0 B'
|
|
210
|
+
const k = 1024
|
|
211
|
+
const sizes = ['B', 'KB', 'MB', 'GB']
|
|
212
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
213
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Authentication Hook
|
|
3
|
-
* Core FluxStack authentication utilities
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { BaseUser, BaseUserStore } from '../state/index'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Create authentication hook for a user store
|
|
10
|
-
*/
|
|
11
|
-
export function createAuthHook(useUserStore: () => BaseUserStore) {
|
|
12
|
-
return function useAuth() {
|
|
13
|
-
const store = useUserStore()
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
// State
|
|
17
|
-
currentUser: store.currentUser,
|
|
18
|
-
isAuthenticated: store.isAuthenticated,
|
|
19
|
-
isLoading: store.isLoading,
|
|
20
|
-
error: store.error,
|
|
21
|
-
|
|
22
|
-
// Computed
|
|
23
|
-
isAdmin: store.currentUser?.role === 'admin',
|
|
24
|
-
|
|
25
|
-
// Actions
|
|
26
|
-
login: store.login,
|
|
27
|
-
register: store.register,
|
|
28
|
-
logout: store.logout,
|
|
29
|
-
updateProfile: store.updateProfile,
|
|
30
|
-
clearError: store.clearError
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Base auth hook interface
|
|
37
|
-
*/
|
|
38
|
-
export interface AuthHook {
|
|
39
|
-
currentUser: BaseUser | null
|
|
40
|
-
isAuthenticated: boolean
|
|
41
|
-
isLoading: boolean
|
|
42
|
-
error: string | null
|
|
43
|
-
isAdmin: boolean
|
|
44
|
-
login: (credentials: { email: string; password: string }) => Promise<void>
|
|
45
|
-
register: (data: { email: string; password: string; name: string }) => Promise<void>
|
|
46
|
-
logout: () => void
|
|
47
|
-
updateProfile: (data: Partial<BaseUser>) => Promise<void>
|
|
48
|
-
clearError: () => void
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Hook
|
|
3
|
+
* Core FluxStack authentication utilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { BaseUser, BaseUserStore } from '../state/index'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create authentication hook for a user store
|
|
10
|
+
*/
|
|
11
|
+
export function createAuthHook(useUserStore: () => BaseUserStore) {
|
|
12
|
+
return function useAuth() {
|
|
13
|
+
const store = useUserStore()
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
// State
|
|
17
|
+
currentUser: store.currentUser,
|
|
18
|
+
isAuthenticated: store.isAuthenticated,
|
|
19
|
+
isLoading: store.isLoading,
|
|
20
|
+
error: store.error,
|
|
21
|
+
|
|
22
|
+
// Computed
|
|
23
|
+
isAdmin: store.currentUser?.role === 'admin',
|
|
24
|
+
|
|
25
|
+
// Actions
|
|
26
|
+
login: store.login,
|
|
27
|
+
register: store.register,
|
|
28
|
+
logout: store.logout,
|
|
29
|
+
updateProfile: store.updateProfile,
|
|
30
|
+
clearError: store.clearError
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Base auth hook interface
|
|
37
|
+
*/
|
|
38
|
+
export interface AuthHook {
|
|
39
|
+
currentUser: BaseUser | null
|
|
40
|
+
isAuthenticated: boolean
|
|
41
|
+
isLoading: boolean
|
|
42
|
+
error: string | null
|
|
43
|
+
isAdmin: boolean
|
|
44
|
+
login: (credentials: { email: string; password: string }) => Promise<void>
|
|
45
|
+
register: (data: { email: string; password: string; name: string }) => Promise<void>
|
|
46
|
+
logout: () => void
|
|
47
|
+
updateProfile: (data: Partial<BaseUser>) => Promise<void>
|
|
48
|
+
clearError: () => void
|
|
49
49
|
}
|