@stacksjs/bun-router 0.0.16 → 0.0.18

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 (176) hide show
  1. package/dist/auth.d.ts +22 -8
  2. package/dist/chunk-1ahs68ys.js +18 -0
  3. package/dist/{chunk-0145g1me.js → chunk-cgptvjdf.js} +147 -75
  4. package/dist/chunk-g3ybefhg.js +1923 -0
  5. package/dist/cli.js +3 -2
  6. package/dist/container/container.d.ts +1 -0
  7. package/dist/container/contextual-binding.d.ts +0 -1
  8. package/dist/container/decorators.d.ts +2 -5
  9. package/dist/container/index.d.ts +16 -0
  10. package/dist/container/index.js +322 -0
  11. package/dist/container/service-provider.d.ts +3 -3
  12. package/dist/development/performance-profiler.d.ts +3 -3
  13. package/dist/development/route-debugger.d.ts +1 -1
  14. package/dist/development/route-inspector.d.ts +2 -2
  15. package/dist/file-serving/static-files.d.ts +16 -0
  16. package/dist/index.d.ts +17 -1
  17. package/dist/index.js +1159 -1380
  18. package/dist/middleware/cors.d.ts +9 -0
  19. package/dist/middleware/csrf.d.ts +7 -0
  20. package/dist/middleware/ddos_protection.d.ts +16 -1
  21. package/dist/middleware/rate_limit.d.ts +7 -1
  22. package/dist/middleware/request_tracer.d.ts +15 -9
  23. package/dist/middleware/response_cache.d.ts +2 -1
  24. package/dist/observability/integration.d.ts +1 -1
  25. package/dist/request/context.d.ts +12 -1
  26. package/dist/request/macros.d.ts +40 -2
  27. package/dist/response/macros.d.ts +4 -4
  28. package/dist/router/fluent-routing.d.ts +50 -13
  29. package/dist/router/handler-resolver.d.ts +8 -0
  30. package/dist/router/index.d.ts +9 -7
  31. package/dist/router/route-compiler.d.ts +8 -10
  32. package/dist/router/route-trie.d.ts +7 -1
  33. package/dist/router/router.d.ts +13 -34
  34. package/dist/router/validation-integration.d.ts +10 -4
  35. package/dist/testing/performance-testing.d.ts +2 -2
  36. package/dist/testing/test-client.d.ts +1 -1
  37. package/dist/testing/websocket-testing.d.ts +1 -1
  38. package/dist/types/middleware-types.d.ts +1 -1
  39. package/dist/types/route-inference.d.ts +9 -2
  40. package/dist/types.d.ts +62 -9
  41. package/dist/utils.d.ts +1 -1
  42. package/package.json +12 -3
  43. package/dist/router/fluent-router.d.ts +0 -315
  44. package/src/auth.ts +0 -469
  45. package/src/cache/lru-cache.ts +0 -457
  46. package/src/cache/middleware-memoization.ts +0 -531
  47. package/src/cache/route-cache-warmer.ts +0 -486
  48. package/src/cache/sqlite-cache.ts +0 -783
  49. package/src/cache/streaming-cache.ts +0 -572
  50. package/src/cli/colors.ts +0 -29
  51. package/src/cli/index.ts +0 -287
  52. package/src/cli/middleware.ts +0 -291
  53. package/src/cli/openapi.ts +0 -407
  54. package/src/cli/router.ts +0 -188
  55. package/src/cli/routes.ts +0 -265
  56. package/src/cli/utils.ts +0 -531
  57. package/src/cli.ts +0 -5
  58. package/src/config.ts +0 -322
  59. package/src/container/container.ts +0 -740
  60. package/src/container/contextual-binding.ts +0 -603
  61. package/src/container/decorators.ts +0 -359
  62. package/src/container/service-provider.ts +0 -596
  63. package/src/development/hot-reload.ts +0 -673
  64. package/src/development/index.ts +0 -499
  65. package/src/development/performance-profiler.ts +0 -717
  66. package/src/development/route-debugger.ts +0 -527
  67. package/src/development/route-inspector.ts +0 -749
  68. package/src/development/typescript-utilities.ts +0 -682
  69. package/src/docs.ts +0 -397
  70. package/src/errors/circuit-breaker.ts +0 -732
  71. package/src/errors/error-handler.ts +0 -569
  72. package/src/errors/error-reporting.ts +0 -672
  73. package/src/errors/exceptions.ts +0 -536
  74. package/src/errors/graceful-degradation.ts +0 -621
  75. package/src/errors/index.ts +0 -21
  76. package/src/errors/router-errors.ts +0 -632
  77. package/src/file-serving/static-files.ts +0 -581
  78. package/src/index.ts +0 -14
  79. package/src/middleware/auth.ts +0 -220
  80. package/src/middleware/content_security_policy.ts +0 -215
  81. package/src/middleware/cors.ts +0 -74
  82. package/src/middleware/csrf.ts +0 -118
  83. package/src/middleware/ddos_protection.ts +0 -255
  84. package/src/middleware/file_security.ts +0 -191
  85. package/src/middleware/file_upload.ts +0 -275
  86. package/src/middleware/helmet.ts +0 -268
  87. package/src/middleware/index.ts +0 -117
  88. package/src/middleware/input_validation.ts +0 -449
  89. package/src/middleware/json_body.ts +0 -37
  90. package/src/middleware/performance_alerting.ts +0 -538
  91. package/src/middleware/performance_dashboard.ts +0 -661
  92. package/src/middleware/performance_monitor.ts +0 -943
  93. package/src/middleware/pipeline.ts +0 -489
  94. package/src/middleware/rate_limit.ts +0 -245
  95. package/src/middleware/request_id.ts +0 -36
  96. package/src/middleware/request_signing.ts +0 -636
  97. package/src/middleware/request_tracer.ts +0 -636
  98. package/src/middleware/response_cache.ts +0 -743
  99. package/src/middleware/security.ts +0 -482
  100. package/src/middleware/security_suite.ts +0 -257
  101. package/src/middleware/session.ts +0 -91
  102. package/src/model-binding/index.ts +0 -18
  103. package/src/model-binding/model-middleware.ts +0 -425
  104. package/src/model-binding/model-registry.ts +0 -550
  105. package/src/model-binding.ts +0 -370
  106. package/src/model-resolver-factory.ts +0 -106
  107. package/src/observability/correlation.ts +0 -691
  108. package/src/observability/health-checks.ts +0 -729
  109. package/src/observability/index.ts +0 -184
  110. package/src/observability/integration.ts +0 -548
  111. package/src/observability/metrics.ts +0 -753
  112. package/src/observability/tracing.ts +0 -638
  113. package/src/optimization/bun-utilities.ts +0 -778
  114. package/src/query-builder-integration.ts +0 -137
  115. package/src/request/context.ts +0 -62
  116. package/src/request/enhanced-request.ts +0 -857
  117. package/src/request/macros.ts +0 -688
  118. package/src/response/macros.ts +0 -665
  119. package/src/response/response-factory.ts +0 -596
  120. package/src/router/api-routes.ts +0 -243
  121. package/src/router/file-based-routing.ts +0 -690
  122. package/src/router/file-streaming.ts +0 -383
  123. package/src/router/fluent-router.ts +0 -927
  124. package/src/router/fluent-routing.ts +0 -797
  125. package/src/router/group-organization.ts +0 -213
  126. package/src/router/handler-resolver.ts +0 -291
  127. package/src/router/http-methods.ts +0 -377
  128. package/src/router/index.ts +0 -187
  129. package/src/router/middleware-groups.ts +0 -222
  130. package/src/router/middleware-integration.ts +0 -399
  131. package/src/router/middleware.ts +0 -231
  132. package/src/router/model-binding.ts +0 -215
  133. package/src/router/optimized-route-matching.ts +0 -253
  134. package/src/router/route-building.ts +0 -221
  135. package/src/router/route-compiler.ts +0 -702
  136. package/src/router/route-matching.ts +0 -349
  137. package/src/router/route-trie.ts +0 -464
  138. package/src/router/router.ts +0 -1604
  139. package/src/router/server.ts +0 -462
  140. package/src/router/validation-integration.ts +0 -443
  141. package/src/router/view-rendering.ts +0 -233
  142. package/src/router/websocket.ts +0 -100
  143. package/src/routing/route-caching.ts +0 -402
  144. package/src/routing/route-throttling.ts +0 -469
  145. package/src/routing/subdomain-routing.ts +0 -492
  146. package/src/session/database-store.ts +0 -109
  147. package/src/session/file-store.ts +0 -148
  148. package/src/session/index.ts +0 -244
  149. package/src/session/memory-store.ts +0 -88
  150. package/src/session/redis-store.ts +0 -93
  151. package/src/streaming/index.ts +0 -17
  152. package/src/streaming/sse-handler.ts +0 -482
  153. package/src/streaming/stream-handler.ts +0 -552
  154. package/src/testing/auth-testing.ts +0 -446
  155. package/src/testing/file-upload-testing.ts +0 -543
  156. package/src/testing/index.ts +0 -10
  157. package/src/testing/middleware-testing.ts +0 -322
  158. package/src/testing/model-binding-testing.ts +0 -645
  159. package/src/testing/performance-testing.ts +0 -738
  160. package/src/testing/test-client.ts +0 -310
  161. package/src/testing/test-request.ts +0 -315
  162. package/src/testing/test-response.ts +0 -332
  163. package/src/testing/types.ts +0 -224
  164. package/src/testing/websocket-testing.ts +0 -590
  165. package/src/types/controller-types.ts +0 -385
  166. package/src/types/core.ts +0 -683
  167. package/src/types/middleware-types.ts +0 -419
  168. package/src/types/request-response-augmentation.ts +0 -489
  169. package/src/types/route-inference.ts +0 -357
  170. package/src/types.ts +0 -2067
  171. package/src/url.ts +0 -126
  172. package/src/utils/index.ts +0 -1
  173. package/src/utils/query-preservation.ts +0 -201
  174. package/src/utils.ts +0 -392
  175. package/src/validation/validator.ts +0 -685
  176. package/src/websocket/clustering.ts +0 -762
@@ -1,148 +0,0 @@
1
- import { existsSync, mkdirSync, readdirSync, unlinkSync, writeFileSync, readFileSync } from 'node:fs'
2
- import { join } from 'node:path'
3
- import { tmpdir } from 'node:os'
4
- import type { SessionData, SessionStore } from '../types/core'
5
-
6
- interface FileSession {
7
- data: SessionData
8
- expiresAt: number
9
- }
10
-
11
- /**
12
- * File-based session store.
13
- * Persists sessions to disk as JSON files.
14
- * Suitable for single-server deployments.
15
- */
16
- export class FileSessionStore implements SessionStore<SessionData> {
17
- private dir: string
18
- private cleanupInterval: ReturnType<typeof setInterval> | null = null
19
-
20
- constructor(
21
- private defaultTtl: number = 86400,
22
- dir?: string,
23
- ) {
24
- this.dir = dir || join(tmpdir(), 'bun-router-sessions')
25
- if (!existsSync(this.dir)) {
26
- mkdirSync(this.dir, { recursive: true })
27
- }
28
-
29
- // Cleanup every 10 minutes
30
- this.cleanupInterval = setInterval(() => this.cleanup(), 10 * 60 * 1000)
31
- }
32
-
33
- private filePath(sid: string): string {
34
- // Sanitize session ID to prevent path traversal
35
- const safeSid = sid.replace(/[^a-zA-Z0-9_-]/g, '')
36
- return join(this.dir, `${safeSid}.json`)
37
- }
38
-
39
- async get(sid: string): Promise<SessionData | null> {
40
- const path = this.filePath(sid)
41
- if (!existsSync(path)) return null
42
-
43
- try {
44
- const content = readFileSync(path, 'utf-8')
45
- const stored: FileSession = JSON.parse(content)
46
-
47
- if (Date.now() > stored.expiresAt) {
48
- unlinkSync(path)
49
- return null
50
- }
51
-
52
- return stored.data
53
- }
54
- catch {
55
- return null
56
- }
57
- }
58
-
59
- async set(sid: string, session: SessionData, ttl?: number): Promise<void> {
60
- const stored: FileSession = {
61
- data: session,
62
- expiresAt: Date.now() + (ttl ?? this.defaultTtl) * 1000,
63
- }
64
-
65
- writeFileSync(this.filePath(sid), JSON.stringify(stored), 'utf-8')
66
- }
67
-
68
- async destroy(sid: string): Promise<void> {
69
- const path = this.filePath(sid)
70
- if (existsSync(path)) {
71
- unlinkSync(path)
72
- }
73
- }
74
-
75
- async touch(sid: string, session: SessionData, ttl?: number): Promise<void> {
76
- const path = this.filePath(sid)
77
- if (!existsSync(path)) return
78
-
79
- const stored: FileSession = {
80
- data: session,
81
- expiresAt: Date.now() + (ttl ?? this.defaultTtl) * 1000,
82
- }
83
-
84
- writeFileSync(path, JSON.stringify(stored), 'utf-8')
85
- }
86
-
87
- async all(): Promise<Record<string, SessionData>> {
88
- const result: Record<string, SessionData> = {}
89
- const now = Date.now()
90
-
91
- try {
92
- const files = readdirSync(this.dir).filter(f => f.endsWith('.json'))
93
- for (const file of files) {
94
- const content = readFileSync(join(this.dir, file), 'utf-8')
95
- const stored: FileSession = JSON.parse(content)
96
- if (now <= stored.expiresAt) {
97
- const sid = file.replace('.json', '')
98
- result[sid] = stored.data
99
- }
100
- }
101
- }
102
- catch { /* ignore errors */ }
103
-
104
- return result
105
- }
106
-
107
- async length(): Promise<number> {
108
- try {
109
- return readdirSync(this.dir).filter(f => f.endsWith('.json')).length
110
- }
111
- catch {
112
- return 0
113
- }
114
- }
115
-
116
- async clear(): Promise<void> {
117
- try {
118
- const files = readdirSync(this.dir).filter(f => f.endsWith('.json'))
119
- for (const file of files) {
120
- unlinkSync(join(this.dir, file))
121
- }
122
- }
123
- catch { /* ignore errors */ }
124
- }
125
-
126
- private cleanup(): void {
127
- const now = Date.now()
128
- try {
129
- const files = readdirSync(this.dir).filter(f => f.endsWith('.json'))
130
- for (const file of files) {
131
- const path = join(this.dir, file)
132
- const content = readFileSync(path, 'utf-8')
133
- const stored: FileSession = JSON.parse(content)
134
- if (now > stored.expiresAt) {
135
- unlinkSync(path)
136
- }
137
- }
138
- }
139
- catch { /* ignore errors */ }
140
- }
141
-
142
- dispose(): void {
143
- if (this.cleanupInterval) {
144
- clearInterval(this.cleanupInterval)
145
- this.cleanupInterval = null
146
- }
147
- }
148
- }
@@ -1,244 +0,0 @@
1
- import type { SessionData, SessionStore } from '../types/core'
2
- import { MemorySessionStore } from './memory-store'
3
- import { FileSessionStore } from './file-store'
4
- import { RedisSessionStore } from './redis-store'
5
- import type { RedisClient } from './redis-store'
6
- import { DatabaseSessionStore } from './database-store'
7
- import type { SessionDatabaseAdapter } from './database-store'
8
-
9
- export { MemorySessionStore } from './memory-store'
10
- export { FileSessionStore } from './file-store'
11
- export { RedisSessionStore } from './redis-store'
12
- export type { RedisClient } from './redis-store'
13
- export { DatabaseSessionStore } from './database-store'
14
- export type { SessionDatabaseAdapter } from './database-store'
15
-
16
- export interface SessionConfig {
17
- driver: 'memory' | 'file' | 'redis' | 'database'
18
- ttl?: number
19
- cookie?: {
20
- name?: string
21
- maxAge?: number
22
- path?: string
23
- httpOnly?: boolean
24
- secure?: boolean
25
- sameSite?: 'strict' | 'lax' | 'none'
26
- }
27
- // Driver-specific options
28
- file?: {
29
- dir?: string
30
- }
31
- redis?: {
32
- client: RedisClient
33
- prefix?: string
34
- }
35
- database?: {
36
- adapter: SessionDatabaseAdapter
37
- }
38
- }
39
-
40
- /**
41
- * Create a session store based on configuration
42
- */
43
- export function createSessionStore(config: SessionConfig): SessionStore<SessionData> {
44
- const ttl = config.ttl ?? 86400
45
-
46
- switch (config.driver) {
47
- case 'memory':
48
- return new MemorySessionStore(ttl)
49
-
50
- case 'file':
51
- return new FileSessionStore(ttl, config.file?.dir)
52
-
53
- case 'redis': {
54
- if (!config.redis?.client) {
55
- throw new Error('Redis client is required for redis session driver')
56
- }
57
- return new RedisSessionStore(config.redis.client, ttl, config.redis.prefix)
58
- }
59
-
60
- case 'database': {
61
- if (!config.database?.adapter) {
62
- throw new Error('Database adapter is required for database session driver')
63
- }
64
- return new DatabaseSessionStore(config.database.adapter, ttl)
65
- }
66
-
67
- default:
68
- return new MemorySessionStore(ttl)
69
- }
70
- }
71
-
72
- /**
73
- * Session manager for request handling.
74
- * Wraps a SessionStore and provides flash data, regeneration, etc.
75
- */
76
- export class SessionManager {
77
- private sessionId: string
78
- private data: SessionData
79
- private store: SessionStore<SessionData>
80
- private flashedKeys: string[] = []
81
- private previousFlash: Record<string, unknown> = {}
82
- private dirty = false
83
-
84
- constructor(sessionId: string, data: SessionData, store: SessionStore<SessionData>) {
85
- this.sessionId = sessionId
86
- this.data = data
87
- this.store = store
88
-
89
- // Capture previous flash data to clear after this request
90
- this.previousFlash = { ...(data.flash || {}) }
91
- }
92
-
93
- get id(): string {
94
- return this.sessionId
95
- }
96
-
97
- /**
98
- * Get a value from the session
99
- */
100
- get<T = unknown>(key: string): T | undefined {
101
- // Check flash data first
102
- if (this.data.flash && key in this.data.flash) {
103
- return this.data.flash[key] as T
104
- }
105
- if (this.data.data && key in this.data.data) {
106
- return this.data.data[key] as T
107
- }
108
- return undefined
109
- }
110
-
111
- /**
112
- * Set a value in the session
113
- */
114
- set(key: string, value: unknown): void {
115
- if (!this.data.data) this.data.data = {}
116
- this.data.data[key] = value
117
- this.dirty = true
118
- }
119
-
120
- /**
121
- * Check if a key exists in the session
122
- */
123
- has(key: string): boolean {
124
- return (this.data.data && key in this.data.data) || (this.data.flash && key in this.data.flash) || false
125
- }
126
-
127
- /**
128
- * Remove a value from the session
129
- */
130
- forget(key: string): void {
131
- if (this.data.data) {
132
- delete this.data.data[key]
133
- this.dirty = true
134
- }
135
- }
136
-
137
- /**
138
- * Get all session data
139
- */
140
- all(): Record<string, unknown> {
141
- return { ...(this.data.data || {}), ...(this.data.flash || {}) }
142
- }
143
-
144
- /**
145
- * Flash a key-value pair for the next request only
146
- */
147
- flash(key: string, value: unknown): void {
148
- if (!this.data.flash) this.data.flash = {}
149
- this.data.flash[key] = value
150
- this.flashedKeys.push(key)
151
- this.dirty = true
152
- }
153
-
154
- /**
155
- * Get a flash value (available for current request)
156
- */
157
- getFlash<T = unknown>(key: string): T | undefined {
158
- return this.previousFlash[key] as T | undefined
159
- }
160
-
161
- /**
162
- * Keep specific flash data for another request
163
- */
164
- keep(keys: string[]): void {
165
- for (const key of keys) {
166
- if (key in this.previousFlash) {
167
- this.flash(key, this.previousFlash[key])
168
- }
169
- }
170
- }
171
-
172
- /**
173
- * Reflash all flash data for another request
174
- */
175
- reflash(): void {
176
- for (const [key, value] of Object.entries(this.previousFlash)) {
177
- this.flash(key, value)
178
- }
179
- }
180
-
181
- /**
182
- * Regenerate session ID (keeps data)
183
- */
184
- async regenerate(): Promise<string> {
185
- const oldId = this.sessionId
186
- this.sessionId = generateSessionId()
187
-
188
- // Move data to new session
189
- await this.store.set(this.sessionId, this.data)
190
- await this.store.destroy(oldId)
191
-
192
- return this.sessionId
193
- }
194
-
195
- /**
196
- * Invalidate the session (new ID, clear data)
197
- */
198
- async invalidate(): Promise<string> {
199
- const oldId = this.sessionId
200
- this.sessionId = generateSessionId()
201
- this.data = { id: this.sessionId }
202
-
203
- await this.store.destroy(oldId)
204
- await this.store.set(this.sessionId, this.data)
205
-
206
- return this.sessionId
207
- }
208
-
209
- /**
210
- * Save session data to the store.
211
- * Call this at the end of the request.
212
- */
213
- async save(): Promise<void> {
214
- // Clear old flash data (data that was available this request but not re-flashed)
215
- if (this.data.flash) {
216
- const newFlash: Record<string, unknown> = {}
217
- for (const key of this.flashedKeys) {
218
- if (this.data.flash[key] !== undefined) {
219
- newFlash[key] = this.data.flash[key]
220
- }
221
- }
222
- this.data.flash = Object.keys(newFlash).length > 0 ? newFlash : undefined
223
- }
224
-
225
- await this.store.set(this.sessionId, this.data)
226
- }
227
-
228
- /**
229
- * Destroy the session completely
230
- */
231
- async destroy(): Promise<void> {
232
- await this.store.destroy(this.sessionId)
233
- this.data = {}
234
- }
235
- }
236
-
237
- /**
238
- * Generate a cryptographically secure session ID
239
- */
240
- export function generateSessionId(): string {
241
- const bytes = new Uint8Array(32)
242
- crypto.getRandomValues(bytes)
243
- return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('')
244
- }
@@ -1,88 +0,0 @@
1
- import type { SessionData, SessionStore } from '../types/core'
2
-
3
- interface StoredSession {
4
- data: SessionData
5
- expiresAt: number
6
- }
7
-
8
- /**
9
- * In-memory session store.
10
- * Fast but data is lost on server restart.
11
- * Suitable for development or single-process deployments.
12
- */
13
- export class MemorySessionStore implements SessionStore<SessionData> {
14
- private sessions = new Map<string, StoredSession>()
15
- private cleanupInterval: ReturnType<typeof setInterval> | null = null
16
-
17
- constructor(private defaultTtl: number = 86400) {
18
- // Run cleanup every 5 minutes
19
- this.cleanupInterval = setInterval(() => this.cleanup(), 5 * 60 * 1000)
20
- }
21
-
22
- async get(sid: string): Promise<SessionData | null> {
23
- const stored = this.sessions.get(sid)
24
- if (!stored) return null
25
-
26
- if (Date.now() > stored.expiresAt) {
27
- this.sessions.delete(sid)
28
- return null
29
- }
30
-
31
- return stored.data
32
- }
33
-
34
- async set(sid: string, session: SessionData, ttl?: number): Promise<void> {
35
- const expiresAt = Date.now() + (ttl ?? this.defaultTtl) * 1000
36
- this.sessions.set(sid, { data: session, expiresAt })
37
- }
38
-
39
- async destroy(sid: string): Promise<void> {
40
- this.sessions.delete(sid)
41
- }
42
-
43
- async touch(sid: string, session: SessionData, ttl?: number): Promise<void> {
44
- const stored = this.sessions.get(sid)
45
- if (stored) {
46
- stored.expiresAt = Date.now() + (ttl ?? this.defaultTtl) * 1000
47
- stored.data = session
48
- }
49
- }
50
-
51
- async all(): Promise<Record<string, SessionData>> {
52
- const result: Record<string, SessionData> = {}
53
- const now = Date.now()
54
-
55
- for (const [sid, stored] of this.sessions) {
56
- if (now <= stored.expiresAt) {
57
- result[sid] = stored.data
58
- }
59
- }
60
-
61
- return result
62
- }
63
-
64
- async length(): Promise<number> {
65
- return this.sessions.size
66
- }
67
-
68
- async clear(): Promise<void> {
69
- this.sessions.clear()
70
- }
71
-
72
- private cleanup(): void {
73
- const now = Date.now()
74
- for (const [sid, stored] of this.sessions) {
75
- if (now > stored.expiresAt) {
76
- this.sessions.delete(sid)
77
- }
78
- }
79
- }
80
-
81
- dispose(): void {
82
- if (this.cleanupInterval) {
83
- clearInterval(this.cleanupInterval)
84
- this.cleanupInterval = null
85
- }
86
- this.sessions.clear()
87
- }
88
- }
@@ -1,93 +0,0 @@
1
- import type { SessionData, SessionStore } from '../types/core'
2
-
3
- /**
4
- * Minimal Redis client interface.
5
- * Compatible with ioredis, node-redis, or any client implementing these methods.
6
- */
7
- export interface RedisClient {
8
- get(key: string): Promise<string | null>
9
- set(key: string, value: string, ...args: any[]): Promise<any>
10
- del(key: string | string[]): Promise<number>
11
- expire(key: string, seconds: number): Promise<number>
12
- keys(pattern: string): Promise<string[]>
13
- }
14
-
15
- /**
16
- * Redis-backed session store.
17
- * Ideal for distributed/multi-server deployments.
18
- * Requires a Redis client to be passed in.
19
- */
20
- export class RedisSessionStore implements SessionStore<SessionData> {
21
- private prefix: string
22
-
23
- constructor(
24
- private client: RedisClient,
25
- private defaultTtl: number = 86400,
26
- prefix: string = 'sess:',
27
- ) {
28
- this.prefix = prefix
29
- }
30
-
31
- private key(sid: string): string {
32
- return `${this.prefix}${sid}`
33
- }
34
-
35
- async get(sid: string): Promise<SessionData | null> {
36
- const data = await this.client.get(this.key(sid))
37
- if (!data) return null
38
-
39
- try {
40
- return JSON.parse(data) as SessionData
41
- }
42
- catch {
43
- return null
44
- }
45
- }
46
-
47
- async set(sid: string, session: SessionData, ttl?: number): Promise<void> {
48
- const key = this.key(sid)
49
- const seconds = ttl ?? this.defaultTtl
50
- await this.client.set(key, JSON.stringify(session), 'EX', seconds)
51
- }
52
-
53
- async destroy(sid: string): Promise<void> {
54
- await this.client.del(this.key(sid))
55
- }
56
-
57
- async touch(sid: string, session: SessionData, ttl?: number): Promise<void> {
58
- const key = this.key(sid)
59
- const seconds = ttl ?? this.defaultTtl
60
- // Reset TTL and update data
61
- await this.client.set(key, JSON.stringify(session), 'EX', seconds)
62
- }
63
-
64
- async all(): Promise<Record<string, SessionData>> {
65
- const keys = await this.client.keys(`${this.prefix}*`)
66
- const result: Record<string, SessionData> = {}
67
-
68
- for (const key of keys) {
69
- const data = await this.client.get(key)
70
- if (data) {
71
- try {
72
- const sid = key.slice(this.prefix.length)
73
- result[sid] = JSON.parse(data)
74
- }
75
- catch { /* skip invalid data */ }
76
- }
77
- }
78
-
79
- return result
80
- }
81
-
82
- async length(): Promise<number> {
83
- const keys = await this.client.keys(`${this.prefix}*`)
84
- return keys.length
85
- }
86
-
87
- async clear(): Promise<void> {
88
- const keys = await this.client.keys(`${this.prefix}*`)
89
- if (keys.length > 0) {
90
- await this.client.del(keys)
91
- }
92
- }
93
- }
@@ -1,17 +0,0 @@
1
- export type { SSEConfig, SSEEvent } from '../types'
2
-
3
- export {
4
- createSSEMiddleware,
5
- SSEConnectionManager,
6
- SSEHandler,
7
- sseManager,
8
- SSEUtils,
9
- } from './sse-handler'
10
-
11
- export {
12
- type BaseStreamConfig,
13
- FileStreamHandler,
14
- StreamHandler,
15
- StreamResponse,
16
- StreamUtils,
17
- } from './stream-handler'