@gravito/core 1.6.0 → 2.0.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 (171) hide show
  1. package/README.md +100 -6
  2. package/README.zh-TW.md +101 -6
  3. package/dist/Application.d.ts +256 -0
  4. package/dist/CommandKernel.d.ts +33 -0
  5. package/dist/ConfigManager.d.ts +65 -0
  6. package/dist/Container/RequestScopeManager.d.ts +62 -0
  7. package/dist/Container/RequestScopeMetrics.d.ts +144 -0
  8. package/dist/Container.d.ts +153 -0
  9. package/dist/ErrorHandler.d.ts +66 -0
  10. package/dist/Event.d.ts +5 -0
  11. package/dist/EventManager.d.ts +123 -0
  12. package/dist/GlobalErrorHandlers.d.ts +47 -0
  13. package/dist/GravitoServer.d.ts +28 -0
  14. package/dist/HookManager.d.ts +435 -0
  15. package/dist/Listener.d.ts +4 -0
  16. package/dist/Logger.d.ts +20 -0
  17. package/dist/PlanetCore.d.ts +402 -0
  18. package/dist/RequestContext.d.ts +97 -0
  19. package/dist/Route.d.ts +36 -0
  20. package/dist/Router.d.ts +270 -0
  21. package/dist/ServiceProvider.d.ts +178 -0
  22. package/dist/adapters/GravitoEngineAdapter.d.ts +27 -0
  23. package/dist/adapters/bun/AdaptiveAdapter.d.ts +99 -0
  24. package/dist/adapters/bun/BunContext.d.ts +54 -0
  25. package/dist/adapters/bun/BunNativeAdapter.d.ts +66 -0
  26. package/dist/adapters/bun/BunRequest.d.ts +31 -0
  27. package/dist/adapters/bun/BunWebSocketHandler.d.ts +48 -0
  28. package/dist/adapters/bun/RadixNode.d.ts +19 -0
  29. package/dist/adapters/bun/RadixRouter.d.ts +32 -0
  30. package/dist/adapters/bun/index.d.ts +7 -0
  31. package/dist/adapters/bun/types.d.ts +20 -0
  32. package/dist/adapters/index.d.ts +12 -0
  33. package/dist/adapters/types.d.ts +235 -0
  34. package/dist/binary/BinaryUtils.d.ts +105 -0
  35. package/dist/binary/index.d.ts +5 -0
  36. package/dist/cli/queue-commands.d.ts +6 -0
  37. package/dist/compat/async-local-storage.browser.d.ts +9 -0
  38. package/dist/compat/async-local-storage.d.ts +7 -0
  39. package/dist/compat/crypto.browser.d.ts +5 -0
  40. package/dist/compat/crypto.d.ts +6 -0
  41. package/dist/compat.cjs +42 -11
  42. package/dist/compat.cjs.map +9 -0
  43. package/dist/compat.d.ts +23 -1
  44. package/dist/compat.js +3 -0
  45. package/dist/compat.js.map +9 -0
  46. package/dist/engine/AOTRouter.d.ts +139 -0
  47. package/dist/engine/FastContext.d.ts +141 -0
  48. package/dist/engine/Gravito.d.ts +131 -0
  49. package/dist/engine/MinimalContext.d.ts +102 -0
  50. package/dist/engine/analyzer.d.ts +113 -0
  51. package/dist/engine/constants.d.ts +23 -0
  52. package/dist/engine/index.cjs +758 -532
  53. package/dist/engine/index.cjs.map +22 -0
  54. package/dist/engine/index.d.ts +14 -690
  55. package/dist/engine/index.js +758 -508
  56. package/dist/engine/index.js.map +22 -0
  57. package/dist/engine/path.d.ts +26 -0
  58. package/dist/engine/pool.d.ts +83 -0
  59. package/dist/engine/types.d.ts +149 -0
  60. package/dist/error-handling/RequestScopeErrorContext.d.ts +126 -0
  61. package/dist/events/BackpressureManager.d.ts +215 -0
  62. package/dist/events/CircuitBreaker.d.ts +229 -0
  63. package/dist/events/DeadLetterQueue.d.ts +219 -0
  64. package/dist/events/EventBackend.d.ts +12 -0
  65. package/dist/events/EventOptions.d.ts +204 -0
  66. package/dist/events/EventPriorityQueue.d.ts +63 -0
  67. package/dist/events/FlowControlStrategy.d.ts +109 -0
  68. package/dist/events/IdempotencyCache.d.ts +60 -0
  69. package/dist/events/MessageQueueBridge.d.ts +184 -0
  70. package/dist/events/PriorityEscalationManager.d.ts +82 -0
  71. package/dist/events/RetryScheduler.d.ts +104 -0
  72. package/dist/events/WorkerPool.d.ts +98 -0
  73. package/dist/events/WorkerPoolConfig.d.ts +153 -0
  74. package/dist/events/WorkerPoolMetrics.d.ts +65 -0
  75. package/dist/events/aggregation/AggregationWindow.d.ts +77 -0
  76. package/dist/events/aggregation/DeduplicationManager.d.ts +135 -0
  77. package/dist/events/aggregation/EventAggregationManager.d.ts +108 -0
  78. package/dist/events/aggregation/EventBatcher.d.ts +99 -0
  79. package/dist/events/aggregation/index.d.ts +10 -0
  80. package/dist/events/aggregation/types.d.ts +117 -0
  81. package/dist/events/index.d.ts +26 -0
  82. package/dist/events/observability/EventMetrics.d.ts +132 -0
  83. package/dist/events/observability/EventTracer.d.ts +68 -0
  84. package/dist/events/observability/EventTracing.d.ts +161 -0
  85. package/dist/events/observability/OTelEventMetrics.d.ts +332 -0
  86. package/dist/events/observability/ObservableHookManager.d.ts +108 -0
  87. package/dist/events/observability/StreamWorkerMetrics.d.ts +76 -0
  88. package/dist/events/observability/index.d.ts +24 -0
  89. package/dist/events/observability/metrics-types.d.ts +16 -0
  90. package/dist/events/queue-core.d.ts +77 -0
  91. package/dist/events/task-executor.d.ts +51 -0
  92. package/dist/events/types.d.ts +134 -0
  93. package/dist/exceptions/AuthenticationException.d.ts +8 -0
  94. package/dist/exceptions/AuthorizationException.d.ts +8 -0
  95. package/dist/exceptions/CircularDependencyException.d.ts +9 -0
  96. package/dist/exceptions/GravitoException.d.ts +23 -0
  97. package/dist/exceptions/HttpException.d.ts +9 -0
  98. package/dist/exceptions/ModelNotFoundException.d.ts +10 -0
  99. package/dist/exceptions/ValidationException.d.ts +22 -0
  100. package/dist/exceptions/index.d.ts +7 -0
  101. package/dist/ffi/NativeAccelerator.d.ts +69 -0
  102. package/dist/ffi/NativeHasher.d.ts +139 -0
  103. package/dist/ffi/cbor-fallback.d.ts +96 -0
  104. package/dist/ffi/hash-fallback.d.ts +33 -0
  105. package/dist/ffi/index.cjs +621 -0
  106. package/dist/ffi/index.cjs.map +14 -0
  107. package/dist/ffi/index.d.ts +10 -0
  108. package/dist/ffi/index.js +602 -0
  109. package/dist/ffi/index.js.map +14 -0
  110. package/dist/ffi/types.d.ts +135 -0
  111. package/dist/health/HealthProvider.d.ts +67 -0
  112. package/dist/helpers/Arr.d.ts +19 -0
  113. package/dist/helpers/Str.d.ts +38 -0
  114. package/dist/helpers/data.d.ts +25 -0
  115. package/dist/helpers/errors.d.ts +34 -0
  116. package/dist/helpers/response.d.ts +41 -0
  117. package/dist/helpers.d.ts +338 -0
  118. package/dist/hooks/ActionManager.d.ts +132 -0
  119. package/dist/hooks/AsyncDetector.d.ts +84 -0
  120. package/dist/hooks/FilterManager.d.ts +71 -0
  121. package/dist/hooks/MigrationWarner.d.ts +24 -0
  122. package/dist/hooks/dlq-operations.d.ts +60 -0
  123. package/dist/hooks/index.d.ts +11 -0
  124. package/dist/hooks/types.d.ts +107 -0
  125. package/dist/http/CookieJar.d.ts +51 -0
  126. package/dist/http/cookie.d.ts +29 -0
  127. package/dist/http/index.d.ts +12 -0
  128. package/dist/{compat-C4Src6NN.d.cts → http/types.d.ts} +48 -16
  129. package/dist/index.browser.d.ts +34 -0
  130. package/dist/index.cjs +12909 -9492
  131. package/dist/index.cjs.map +168 -0
  132. package/dist/index.d.ts +58 -8707
  133. package/dist/index.js +12906 -9381
  134. package/dist/index.js.map +168 -0
  135. package/dist/observability/QueueDashboard.d.ts +136 -0
  136. package/dist/observability/contracts.d.ts +137 -0
  137. package/dist/observability/index.d.ts +13 -0
  138. package/dist/reliability/DeadLetterQueueManager.d.ts +349 -0
  139. package/dist/reliability/RetryPolicy.d.ts +217 -0
  140. package/dist/reliability/index.d.ts +6 -0
  141. package/dist/router/ControllerDispatcher.d.ts +12 -0
  142. package/dist/router/RequestValidator.d.ts +20 -0
  143. package/dist/runtime/adapter-bun.d.ts +12 -0
  144. package/dist/runtime/adapter-deno.d.ts +12 -0
  145. package/dist/runtime/adapter-node.d.ts +12 -0
  146. package/dist/runtime/adapter-unknown.d.ts +13 -0
  147. package/dist/runtime/archive.d.ts +17 -0
  148. package/dist/runtime/compression.d.ts +21 -0
  149. package/dist/runtime/deep-equals.d.ts +56 -0
  150. package/dist/runtime/detection.d.ts +22 -0
  151. package/dist/runtime/escape.d.ts +34 -0
  152. package/dist/runtime/index.browser.d.ts +20 -0
  153. package/dist/runtime/index.d.ts +44 -0
  154. package/dist/runtime/markdown.d.ts +44 -0
  155. package/dist/runtime/types.d.ts +436 -0
  156. package/dist/runtime-helpers.d.ts +67 -0
  157. package/dist/runtime.d.ts +11 -0
  158. package/dist/security/Encrypter.d.ts +33 -0
  159. package/dist/security/Hasher.d.ts +29 -0
  160. package/dist/testing/HttpTester.d.ts +39 -0
  161. package/dist/testing/TestResponse.d.ts +78 -0
  162. package/dist/testing/index.d.ts +2 -0
  163. package/dist/transpiler-utils.d.ts +170 -0
  164. package/dist/types/events.d.ts +94 -0
  165. package/dist/types.d.ts +13 -0
  166. package/package.json +23 -53
  167. package/src/ffi/native/cbor.c +1148 -0
  168. package/dist/compat-C4Src6NN.d.ts +0 -357
  169. package/dist/compat.d.cts +0 -1
  170. package/dist/engine/index.d.cts +0 -702
  171. package/dist/index.d.cts +0 -8734
@@ -1,26 +1,52 @@
1
+ // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+ var __require = import.meta.require;
29
+
30
+ // src/engine/index.ts
31
+ var exports_engine = {};
32
+ __export(exports_engine, {
33
+ extractPath: () => extractPath,
34
+ ObjectPool: () => ObjectPool,
35
+ MinimalContext: () => MinimalContext,
36
+ Gravito: () => Gravito,
37
+ FastContextImpl: () => FastContext,
38
+ AOTRouter: () => AOTRouter
39
+ });
40
+
1
41
  // src/adapters/bun/RadixNode.ts
2
- var RadixNode = class _RadixNode {
3
- // Path segment for this node (e.g., "users", ":id")
42
+ class RadixNode {
4
43
  segment;
5
- // Node type (Static, Param, Wildcard)
6
44
  type;
7
- // Children nodes (mapped by segment for fast lookup)
8
- children = /* @__PURE__ */ new Map();
9
- // Specialized child for parameter node (only one per level allowed usually to avoid ambiguity, though some routers support multiple)
45
+ children = new Map;
10
46
  paramChild = null;
11
- // Specialized child for wildcard node
12
47
  wildcardChild = null;
13
- // Handlers registered at this node (keyed by HTTP method)
14
- handlers = /* @__PURE__ */ new Map();
15
- // Parameter name if this is a PARAM node (e.g., "id" for ":id")
48
+ handlers = new Map;
16
49
  paramName = null;
17
- // Parameter constraints (regex) - only applicable if this is a PARAM node
18
- // If we support per-route constraints, they might need to be stored differently,
19
- // but for now assume constraints are defined at node level (uncommon) or checked at match time.
20
- // Laravel allows global pattern constraints or per-route.
21
- // Ideally, constraints should be stored with the handler or part of matching logic.
22
- // For a Radix tree, if we have constraints, we might need to backtrack if constraint fails?
23
- // Or simply store constraint with the param node.
24
50
  regex = null;
25
51
  constructor(segment = "", type = 0 /* STATIC */) {
26
52
  this.segment = segment;
@@ -38,44 +64,61 @@ var RadixNode = class _RadixNode {
38
64
  };
39
65
  }
40
66
  static fromJSON(json) {
41
- const node = new _RadixNode(json.segment, json.type);
67
+ const node = new RadixNode(json.segment, json.type);
42
68
  node.paramName = json.paramName;
43
69
  if (json.regex) {
44
70
  node.regex = new RegExp(json.regex);
45
71
  }
46
72
  if (json.children) {
47
73
  for (const [key, childJson] of json.children) {
48
- node.children.set(key, _RadixNode.fromJSON(childJson));
74
+ node.children.set(key, RadixNode.fromJSON(childJson));
49
75
  }
50
76
  }
51
77
  if (json.paramChild) {
52
- node.paramChild = _RadixNode.fromJSON(json.paramChild);
78
+ node.paramChild = RadixNode.fromJSON(json.paramChild);
53
79
  }
54
80
  if (json.wildcardChild) {
55
- node.wildcardChild = _RadixNode.fromJSON(json.wildcardChild);
81
+ node.wildcardChild = RadixNode.fromJSON(json.wildcardChild);
56
82
  }
57
83
  return node;
58
84
  }
59
- };
85
+ }
60
86
 
61
87
  // src/adapters/bun/RadixRouter.ts
62
- var RadixRouter = class _RadixRouter {
63
- root = new RadixNode();
64
- // Global parameter constraints (e.g., id => /^\d+$/)
65
- globalConstraints = /* @__PURE__ */ new Map();
66
- /**
67
- * Add a generic parameter constraint
68
- */
88
+ class RouteCache {
89
+ cache = new Map;
90
+ maxSize = 1e4;
91
+ get(key) {
92
+ return this.cache.get(key);
93
+ }
94
+ set(key, value) {
95
+ if (this.cache.size >= this.maxSize) {
96
+ const firstKey = this.cache.keys().next().value;
97
+ if (firstKey) {
98
+ this.cache.delete(firstKey);
99
+ }
100
+ }
101
+ this.cache.set(key, value);
102
+ }
103
+ clear() {
104
+ this.cache.clear();
105
+ }
106
+ has(key) {
107
+ return this.cache.has(key);
108
+ }
109
+ }
110
+
111
+ class RadixRouter {
112
+ root = new RadixNode;
113
+ globalConstraints = new Map;
114
+ routeCache = new RouteCache;
69
115
  where(param, regex) {
70
116
  this.globalConstraints.set(param, regex);
71
117
  }
72
- /**
73
- * Register a route
74
- */
75
118
  add(method, path, handlers) {
76
119
  let node = this.root;
77
120
  const segments = this.splitPath(path);
78
- for (let i = 0; i < segments.length; i++) {
121
+ for (let i = 0;i < segments.length; i++) {
79
122
  const segment = segments[i];
80
123
  if (segment === "*") {
81
124
  if (!node.wildcardChild) {
@@ -103,10 +146,8 @@ var RadixRouter = class _RadixRouter {
103
146
  }
104
147
  }
105
148
  node.handlers.set(method.toLowerCase(), handlers);
149
+ this.routeCache.clear();
106
150
  }
107
- /**
108
- * Match a request
109
- */
110
151
  match(method, path) {
111
152
  const normalizedMethod = method.toLowerCase();
112
153
  if (path === "/" || path === "") {
@@ -116,9 +157,15 @@ var RadixRouter = class _RadixRouter {
116
157
  }
117
158
  return null;
118
159
  }
160
+ const cacheKey = `${normalizedMethod}:${path}`;
161
+ if (this.routeCache.has(cacheKey)) {
162
+ return this.routeCache.get(cacheKey) ?? null;
163
+ }
119
164
  const searchPath = path.startsWith("/") ? path.slice(1) : path;
120
165
  const segments = searchPath.split("/");
121
- return this.matchRecursive(this.root, segments, 0, {}, normalizedMethod);
166
+ const result = this.matchRecursive(this.root, segments, 0, {}, normalizedMethod);
167
+ this.routeCache.set(cacheKey, result);
168
+ return result;
122
169
  }
123
170
  matchRecursive(node, segments, depth, params, method) {
124
171
  if (depth >= segments.length) {
@@ -141,8 +188,7 @@ var RadixRouter = class _RadixRouter {
141
188
  }
142
189
  const paramChild = node.paramChild;
143
190
  if (paramChild) {
144
- if (paramChild.regex && !paramChild.regex.test(segment)) {
145
- } else {
191
+ if (paramChild.regex && !paramChild.regex.test(segment)) {} else {
146
192
  if (paramChild.paramName) {
147
193
  params[paramChild.paramName] = decodeURIComponent(segment);
148
194
  const match = this.matchRecursive(paramChild, segments, depth + 1, params, method);
@@ -177,9 +223,6 @@ var RadixRouter = class _RadixRouter {
177
223
  }
178
224
  return p.split("/");
179
225
  }
180
- /**
181
- * Serialize the router to a JSON string
182
- */
183
226
  serialize() {
184
227
  return JSON.stringify({
185
228
  root: this.root.toJSON(),
@@ -189,12 +232,9 @@ var RadixRouter = class _RadixRouter {
189
232
  ])
190
233
  });
191
234
  }
192
- /**
193
- * Restore a router from a serialized JSON string
194
- */
195
235
  static fromSerialized(json) {
196
236
  const data = JSON.parse(json);
197
- const router = new _RadixRouter();
237
+ const router = new RadixRouter;
198
238
  router.root = RadixNode.fromJSON(data.root);
199
239
  if (data.globalConstraints) {
200
240
  for (const [key, source] of data.globalConstraints) {
@@ -203,42 +243,22 @@ var RadixRouter = class _RadixRouter {
203
243
  }
204
244
  return router;
205
245
  }
206
- };
246
+ }
207
247
 
208
248
  // src/engine/AOTRouter.ts
209
- var AOTRouter = class {
210
- // Static route cache: "METHOD:PATH" -> RouteMetadata
211
- /** @internal */
212
- staticRoutes = /* @__PURE__ */ new Map();
213
- // Dynamic route handler (Radix Tree)
214
- dynamicRouter = new RadixRouter();
215
- // Store all route definitions to support mounting/merging
216
- /** @internal */
249
+ class AOTRouter {
250
+ staticRoutes = new Map;
251
+ dynamicRouter = new RadixRouter;
217
252
  routeDefinitions = [];
218
- // Global middleware (applies to all routes)
219
- /** @internal */
220
253
  globalMiddleware = [];
221
- // Path-based middleware: pattern -> middleware[]
222
- /** @internal */
223
- pathMiddleware = /* @__PURE__ */ new Map();
224
- // Dynamic route patterns: handler function -> route pattern
225
- // 用於追蹤動態路由的模式,防止高基數問題
226
- dynamicRoutePatterns = /* @__PURE__ */ new Map();
227
- middlewareCache = /* @__PURE__ */ new Map();
228
- cacheMaxSize = 1e3;
229
- version = 0;
230
- /**
231
- * Register a route
232
- *
233
- * Automatically determines if route is static or dynamic.
234
- * Static routes are stored in a Map for O(1) lookup.
235
- * Dynamic routes use the Radix Tree.
236
- *
237
- * @param method - HTTP method
238
- * @param path - Route path
239
- * @param handler - Route handler
240
- * @param middleware - Route-specific middleware
241
- */
254
+ pathMiddleware = new Map;
255
+ dynamicRoutePatterns = new Map;
256
+ middlewareCache = new Map;
257
+ cacheMaxSize = 1000;
258
+ _version = 0;
259
+ get version() {
260
+ return this._version;
261
+ }
242
262
  add(method, path, handler, middleware = []) {
243
263
  this.routeDefinitions.push({ method, path, handler, middleware });
244
264
  const normalizedMethod = method.toLowerCase();
@@ -254,9 +274,6 @@ var AOTRouter = class {
254
274
  }
255
275
  }
256
276
  }
257
- /**
258
- * Mount another router at a prefix
259
- */
260
277
  mount(prefix, other) {
261
278
  if (other.globalMiddleware.length > 0) {
262
279
  this.usePattern(prefix, ...other.globalMiddleware);
@@ -264,7 +281,8 @@ var AOTRouter = class {
264
281
  this.usePattern(wildcard, ...other.globalMiddleware);
265
282
  }
266
283
  for (const [pattern, mws] of other.pathMiddleware) {
267
- if (pattern.includes(":")) {
284
+ const hasMethodPrefix = /^(get|post|put|delete|patch|options|head):/.test(pattern);
285
+ if (hasMethodPrefix) {
268
286
  continue;
269
287
  }
270
288
  let newPattern;
@@ -289,25 +307,10 @@ var AOTRouter = class {
289
307
  this.add(def.method, newPath, def.handler, def.middleware);
290
308
  }
291
309
  }
292
- /**
293
- * Add global middleware
294
- *
295
- * These run for every request, before route-specific middleware.
296
- *
297
- * @param middleware - Middleware functions
298
- */
299
310
  use(...middleware) {
300
311
  this.globalMiddleware.push(...middleware);
301
- this.version++;
302
- }
303
- /**
304
- * Add path-based middleware
305
- *
306
- * Supports wildcard patterns like '/api/*'
307
- *
308
- * @param pattern - Path pattern
309
- * @param middleware - Middleware functions
310
- */
312
+ this._version++;
313
+ }
311
314
  usePattern(pattern, ...middleware) {
312
315
  if (pattern === "*") {
313
316
  this.globalMiddleware.push(...middleware);
@@ -315,17 +318,8 @@ var AOTRouter = class {
315
318
  const existing = this.pathMiddleware.get(pattern) ?? [];
316
319
  this.pathMiddleware.set(pattern, [...existing, ...middleware]);
317
320
  }
318
- this.version++;
319
- }
320
- /**
321
- * Match a request to a route
322
- *
323
- * Returns the handler, params, and all applicable middleware.
324
- *
325
- * @param method - HTTP method
326
- * @param path - Request path
327
- * @returns Route match or null if not found
328
- */
321
+ this._version++;
322
+ }
329
323
  match(method, path) {
330
324
  const normalizedMethod = method.toLowerCase();
331
325
  const staticKey = `${normalizedMethod}:${path}`;
@@ -358,28 +352,16 @@ var AOTRouter = class {
358
352
  middleware: []
359
353
  };
360
354
  }
361
- /**
362
- * Public wrapper for collectMiddleware (used by Gravito for optimization)
363
- */
364
355
  collectMiddlewarePublic(path, routeMiddleware) {
365
356
  return this.collectMiddleware(path, routeMiddleware);
366
357
  }
367
- /**
368
- * Collect all applicable middleware for a path
369
- *
370
- * Order: global -> pattern-based -> route-specific
371
- *
372
- * @param path - Request path
373
- * @param routeMiddleware - Route-specific middleware
374
- * @returns Combined middleware array
375
- */
376
358
  collectMiddleware(path, routeMiddleware) {
377
359
  if (this.globalMiddleware.length === 0 && this.pathMiddleware.size === 0 && routeMiddleware.length === 0) {
378
360
  return [];
379
361
  }
380
- const cacheKey = `${path}:${routeMiddleware.length}`;
362
+ const cacheKey = path;
381
363
  const cached = this.middlewareCache.get(cacheKey);
382
- if (cached !== void 0 && cached.version === this.version) {
364
+ if (cached !== undefined && cached.version === this._version) {
383
365
  return cached.data;
384
366
  }
385
367
  const middleware = [];
@@ -400,27 +382,27 @@ var AOTRouter = class {
400
382
  middleware.push(...routeMiddleware);
401
383
  }
402
384
  if (this.middlewareCache.size < this.cacheMaxSize) {
403
- this.middlewareCache.set(cacheKey, { data: middleware, version: this.version });
385
+ this.middlewareCache.set(cacheKey, { data: middleware, version: this._version });
386
+ } else if (this.middlewareCache.has(cacheKey)) {
387
+ this.middlewareCache.set(cacheKey, { data: middleware, version: this._version });
404
388
  }
405
389
  return middleware;
406
390
  }
407
- /**
408
- * Check if a path is static (no parameters or wildcards)
409
- */
391
+ getNativeRoutes(onMatch) {
392
+ const routes = {};
393
+ for (const [key, metadata] of this.staticRoutes) {
394
+ const [method, path] = key.split(":");
395
+ if (method !== "get") {
396
+ continue;
397
+ }
398
+ const allMiddleware = this.collectMiddleware(path, metadata.middleware);
399
+ routes[path] = onMatch(metadata.handler, allMiddleware, path);
400
+ }
401
+ return routes;
402
+ }
410
403
  isStaticPath(path) {
411
404
  return !path.includes(":") && !path.includes("*");
412
405
  }
413
- /**
414
- * Match a pattern against a path
415
- *
416
- * Supports:
417
- * - Exact match: '/api/users'
418
- * - Wildcard suffix: '/api/*'
419
- *
420
- * @param pattern - Pattern to match
421
- * @param path - Path to test
422
- * @returns True if pattern matches
423
- */
424
406
  matchPattern(pattern, path) {
425
407
  if (pattern === "*") {
426
408
  return true;
@@ -434,9 +416,6 @@ var AOTRouter = class {
434
416
  }
435
417
  return false;
436
418
  }
437
- /**
438
- * Get all registered routes (for debugging)
439
- */
440
419
  getRoutes() {
441
420
  const routes = [];
442
421
  for (const key of this.staticRoutes.keys()) {
@@ -445,11 +424,107 @@ var AOTRouter = class {
445
424
  }
446
425
  return routes;
447
426
  }
448
- };
427
+ }
449
428
 
450
- // src/engine/analyzer.ts
451
- function analyzeHandler(handler) {
452
- const source = handler.toString();
429
+ // src/transpiler-utils.ts
430
+ class TranspilerCache {
431
+ static instance = null;
432
+ transpiler;
433
+ cache;
434
+ maxSize;
435
+ ttlMs;
436
+ constructor(maxSize = 512, ttlMs = 5 * 60 * 1000) {
437
+ this.transpiler = new Bun.Transpiler({ loader: "ts" });
438
+ this.cache = new Map;
439
+ this.maxSize = maxSize;
440
+ this.ttlMs = ttlMs;
441
+ }
442
+ static getInstance() {
443
+ TranspilerCache.instance ??= new TranspilerCache;
444
+ return TranspilerCache.instance;
445
+ }
446
+ static resetInstance() {
447
+ TranspilerCache.instance = null;
448
+ }
449
+ transform(source) {
450
+ const cached = this.cache.get(source);
451
+ if (cached !== undefined) {
452
+ if (Date.now() - cached.createdAt < this.ttlMs) {
453
+ return cached.transformed;
454
+ }
455
+ this.cache.delete(source);
456
+ }
457
+ const transformed = this.doTransform(source);
458
+ if (transformed === null) {
459
+ return null;
460
+ }
461
+ if (this.cache.size >= this.maxSize) {
462
+ const firstKey = this.cache.keys().next().value;
463
+ if (firstKey !== undefined) {
464
+ this.cache.delete(firstKey);
465
+ }
466
+ }
467
+ this.cache.set(source, { transformed, createdAt: Date.now() });
468
+ return transformed;
469
+ }
470
+ doTransform(source) {
471
+ try {
472
+ const out = this.transpiler.transformSync(source);
473
+ if (out.trim().length > 0) {
474
+ return out;
475
+ }
476
+ return this.transformWrapped(source);
477
+ } catch {
478
+ return this.transformWrapped(source);
479
+ }
480
+ }
481
+ transformWrapped(source) {
482
+ try {
483
+ const wrapped = `const __fn = ${source}`;
484
+ const out = this.transpiler.transformSync(wrapped);
485
+ return out.trim().length > 0 ? out : null;
486
+ } catch {
487
+ return null;
488
+ }
489
+ }
490
+ get size() {
491
+ return this.cache.size;
492
+ }
493
+ clear() {
494
+ this.cache.clear();
495
+ }
496
+ }
497
+ var PATTERNS = {
498
+ HEADERS_CALL: /\.req\.headers?\s*\(/,
499
+ HEADERS_DESTR: /\{[^}]*\bheaders?\b[^}]*\}\s*=\s*\w+\.req/,
500
+ QUERY_CALL: /\.req\.quer(?:y|ies)\s*\(/,
501
+ QUERY_DESTR: /\{[^}]*\bquer(?:y|ies)\b[^}]*\}\s*=\s*\w+\.req/,
502
+ BODY_CALL: /\.req\.(?:json|text|formData|blob|arrayBuffer)\s*\(/,
503
+ BODY_DESTR: /\{[^}]*\bbody\b[^}]*\}\s*=\s*\w+\.req/,
504
+ BODY_PROP: /\.req\.body\b/,
505
+ PARAMS_CALL: /\.req\.params?\s*\(/,
506
+ PARAMS_DESTR: /\{[^}]*\bparams?\b[^}]*\}\s*=\s*\w+\.req/,
507
+ IS_ASYNC: /\basync\b/
508
+ };
509
+ function analyzeHandlerWithTranspiler(source) {
510
+ const cache = TranspilerCache.getInstance();
511
+ const transformed = cache.transform(source);
512
+ const isAsync = PATTERNS.IS_ASYNC.test(source);
513
+ if (transformed !== null) {
514
+ return { ...analyzeTransformedCode(transformed), isAsync };
515
+ }
516
+ return { ...fallbackStringAnalysis(source), isAsync };
517
+ }
518
+ function analyzeTransformedCode(code) {
519
+ return {
520
+ usesHeaders: PATTERNS.HEADERS_CALL.test(code) || PATTERNS.HEADERS_DESTR.test(code),
521
+ usesQuery: PATTERNS.QUERY_CALL.test(code) || PATTERNS.QUERY_DESTR.test(code),
522
+ usesBody: PATTERNS.BODY_CALL.test(code) || PATTERNS.BODY_DESTR.test(code) || PATTERNS.BODY_PROP.test(code),
523
+ usesParams: PATTERNS.PARAMS_CALL.test(code) || PATTERNS.PARAMS_DESTR.test(code),
524
+ isAsync: PATTERNS.IS_ASYNC.test(code)
525
+ };
526
+ }
527
+ function fallbackStringAnalysis(source) {
453
528
  return {
454
529
  usesHeaders: source.includes(".header(") || source.includes(".header)") || source.includes(".headers(") || source.includes(".headers)"),
455
530
  usesQuery: source.includes(".query(") || source.includes(".query)") || source.includes(".queries(") || source.includes(".queries)"),
@@ -458,6 +533,12 @@ function analyzeHandler(handler) {
458
533
  isAsync: source.includes("async") || source.includes("await")
459
534
  };
460
535
  }
536
+
537
+ // src/engine/analyzer.ts
538
+ function analyzeHandler(handler) {
539
+ const source = handler.toString();
540
+ return analyzeHandlerWithTranspiler(source);
541
+ }
461
542
  function getOptimalContextType(analysis) {
462
543
  if (analysis.usesHeaders) {
463
544
  return "fast";
@@ -475,7 +556,7 @@ function getOptimalContextType(analysis) {
475
556
  }
476
557
 
477
558
  // src/engine/constants.ts
478
- var encoder = new TextEncoder();
559
+ var encoder = new TextEncoder;
479
560
  var CACHED_RESPONSES = {
480
561
  NOT_FOUND: encoder.encode('{"error":"Not Found"}'),
481
562
  INTERNAL_ERROR: encoder.encode('{"error":"Internal Server Error"}'),
@@ -488,8 +569,154 @@ var HEADERS = {
488
569
  HTML: { "Content-Type": "text/html; charset=utf-8" }
489
570
  };
490
571
 
572
+ // src/Container/RequestScopeMetrics.ts
573
+ class RequestScopeMetrics {
574
+ cleanupStartTime = null;
575
+ cleanupDuration = null;
576
+ scopeSize = 0;
577
+ servicesCleaned = 0;
578
+ errorsOccurred = 0;
579
+ recordCleanupStart() {
580
+ this.cleanupStartTime = performance.now();
581
+ }
582
+ recordCleanupEnd(scopeSize, servicesCleaned, errorsOccurred = 0) {
583
+ if (this.cleanupStartTime !== null) {
584
+ this.cleanupDuration = performance.now() - this.cleanupStartTime;
585
+ this.cleanupStartTime = null;
586
+ }
587
+ this.scopeSize = scopeSize;
588
+ this.servicesCleaned = servicesCleaned;
589
+ this.errorsOccurred = errorsOccurred;
590
+ }
591
+ getCleanupDuration() {
592
+ return this.cleanupDuration;
593
+ }
594
+ isSlowCleanup(thresholdMs = 2) {
595
+ if (this.cleanupDuration === null) {
596
+ return false;
597
+ }
598
+ return this.cleanupDuration > thresholdMs;
599
+ }
600
+ toJSON() {
601
+ return {
602
+ cleanupDuration: this.cleanupDuration,
603
+ scopeSize: this.scopeSize,
604
+ servicesCleaned: this.servicesCleaned,
605
+ errorsOccurred: this.errorsOccurred,
606
+ hasErrors: this.errorsOccurred > 0,
607
+ isSlowCleanup: this.isSlowCleanup()
608
+ };
609
+ }
610
+ toString() {
611
+ const duration = this.cleanupDuration ?? "pending";
612
+ return `cleanup: ${duration}ms, ` + `scope: ${this.scopeSize}, ` + `cleaned: ${this.servicesCleaned}, ` + `errors: ${this.errorsOccurred}`;
613
+ }
614
+ }
615
+
616
+ class RequestScopeMetricsCollector {
617
+ metrics = [];
618
+ record(metrics) {
619
+ this.metrics.push(metrics);
620
+ }
621
+ getStats() {
622
+ if (this.metrics.length === 0) {
623
+ return {
624
+ count: 0,
625
+ averageCleanupTime: null,
626
+ maxCleanupTime: null,
627
+ minCleanupTime: null,
628
+ totalErrorCount: 0,
629
+ errorRate: 0
630
+ };
631
+ }
632
+ const durations = this.metrics.map((m) => m.getCleanupDuration()).filter((d) => d !== null);
633
+ const errorCounts = this.metrics.map((m) => m.toJSON().errorsOccurred);
634
+ const totalErrors = errorCounts.reduce((a, b) => a + b, 0);
635
+ return {
636
+ count: this.metrics.length,
637
+ averageCleanupTime: durations.length > 0 ? durations.reduce((a, b) => a + b) / durations.length : null,
638
+ maxCleanupTime: durations.length > 0 ? Math.max(...durations) : null,
639
+ minCleanupTime: durations.length > 0 ? Math.min(...durations) : null,
640
+ totalErrorCount: totalErrors,
641
+ errorRate: totalErrors / this.metrics.length
642
+ };
643
+ }
644
+ clear() {
645
+ this.metrics = [];
646
+ }
647
+ size() {
648
+ return this.metrics.length;
649
+ }
650
+ toJSON() {
651
+ return this.metrics.map((m) => m.toJSON());
652
+ }
653
+ }
654
+
655
+ // src/Container/RequestScopeManager.ts
656
+ class RequestScopeManager {
657
+ scoped = new Map;
658
+ metadata = new Map;
659
+ metrics = new RequestScopeMetrics;
660
+ observer = null;
661
+ constructor(observer) {
662
+ this.observer = observer || null;
663
+ }
664
+ setObserver(observer) {
665
+ this.observer = observer;
666
+ }
667
+ getMetrics() {
668
+ return this.metrics;
669
+ }
670
+ resolve(key, factory) {
671
+ const keyStr = String(key);
672
+ const isFromCache = this.scoped.has(keyStr);
673
+ if (!isFromCache) {
674
+ const instance = factory();
675
+ this.scoped.set(keyStr, instance);
676
+ if (instance && typeof instance === "object" && "cleanup" in instance) {
677
+ this.metadata.set(keyStr, { hasCleanup: true });
678
+ }
679
+ }
680
+ this.observer?.onServiceResolved?.(key, isFromCache);
681
+ return this.scoped.get(keyStr);
682
+ }
683
+ async cleanup() {
684
+ this.metrics.recordCleanupStart();
685
+ this.observer?.onCleanupStart?.();
686
+ const errors = [];
687
+ let servicesCleaned = 0;
688
+ for (const [, instance] of this.scoped) {
689
+ if (instance && typeof instance === "object" && "cleanup" in instance) {
690
+ const fn = instance.cleanup;
691
+ if (typeof fn === "function") {
692
+ try {
693
+ await fn.call(instance);
694
+ servicesCleaned++;
695
+ } catch (error) {
696
+ errors.push(error);
697
+ this.observer?.onCleanupError?.(error instanceof Error ? error : new Error(String(error)));
698
+ }
699
+ }
700
+ }
701
+ }
702
+ const scopeSize = this.scoped.size;
703
+ this.scoped.clear();
704
+ this.metadata.clear();
705
+ this.metrics.recordCleanupEnd(scopeSize, servicesCleaned, errors.length);
706
+ this.observer?.onCleanupEnd?.(this.metrics);
707
+ if (errors.length > 0) {
708
+ console.error("RequestScope cleanup errors:", errors);
709
+ }
710
+ }
711
+ size() {
712
+ return this.scoped.size;
713
+ }
714
+ }
715
+
491
716
  // src/engine/FastContext.ts
492
- var FastRequestImpl = class {
717
+ var bunEscapeHTML = globalThis.Bun.escapeHTML;
718
+
719
+ class FastRequestImpl {
493
720
  _request;
494
721
  _params;
495
722
  _path;
@@ -497,16 +724,18 @@ var FastRequestImpl = class {
497
724
  _url = null;
498
725
  _query = null;
499
726
  _headers = null;
500
- _cachedJson = void 0;
727
+ _cachedJson = undefined;
501
728
  _jsonParsed = false;
502
- // Back-reference for release check optimization
729
+ _cachedText = undefined;
730
+ _textParsed = false;
731
+ _cachedFormData = undefined;
732
+ _formDataParsed = false;
733
+ _cachedQueries = null;
734
+ _cachedCookies = null;
503
735
  _ctx;
504
736
  constructor(ctx) {
505
737
  this._ctx = ctx;
506
738
  }
507
- /**
508
- * Initialize for new request
509
- */
510
739
  init(request, params = {}, path = "", routePattern) {
511
740
  this._request = request;
512
741
  this._params = params;
@@ -515,27 +744,34 @@ var FastRequestImpl = class {
515
744
  this._url = null;
516
745
  this._query = null;
517
746
  this._headers = null;
518
- this._cachedJson = void 0;
747
+ this._cachedJson = undefined;
519
748
  this._jsonParsed = false;
749
+ this._cachedText = undefined;
750
+ this._textParsed = false;
751
+ this._cachedFormData = undefined;
752
+ this._formDataParsed = false;
753
+ this._cachedQueries = null;
754
+ this._cachedCookies = null;
520
755
  return this;
521
756
  }
522
- /**
523
- * Reset for pooling
524
- */
525
757
  reset() {
526
- this._request = void 0;
527
- this._params = void 0;
758
+ this._request = undefined;
759
+ this._params = undefined;
528
760
  this._url = null;
529
761
  this._query = null;
530
762
  this._headers = null;
531
- this._cachedJson = void 0;
763
+ this._cachedJson = undefined;
532
764
  this._jsonParsed = false;
765
+ this._cachedText = undefined;
766
+ this._textParsed = false;
767
+ this._cachedFormData = undefined;
768
+ this._formDataParsed = false;
769
+ this._cachedQueries = null;
770
+ this._cachedCookies = null;
533
771
  }
534
772
  checkReleased() {
535
773
  if (this._ctx._isReleased) {
536
- throw new Error(
537
- "FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)"
538
- );
774
+ throw new Error("FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)");
539
775
  }
540
776
  }
541
777
  get url() {
@@ -573,17 +809,20 @@ var FastRequestImpl = class {
573
809
  if (!this._query) {
574
810
  this._query = this.getUrl().searchParams;
575
811
  }
576
- return this._query.get(name) ?? void 0;
812
+ return this._query.get(name) ?? undefined;
577
813
  }
578
814
  queries() {
579
815
  this.checkReleased();
816
+ if (this._cachedQueries !== null) {
817
+ return this._cachedQueries;
818
+ }
580
819
  if (!this._query) {
581
820
  this._query = this.getUrl().searchParams;
582
821
  }
583
822
  const result = {};
584
823
  for (const [key, value] of this._query.entries()) {
585
824
  const existing = result[key];
586
- if (existing === void 0) {
825
+ if (existing === undefined) {
587
826
  result[key] = value;
588
827
  } else if (Array.isArray(existing)) {
589
828
  existing.push(value);
@@ -591,11 +830,12 @@ var FastRequestImpl = class {
591
830
  result[key] = [existing, value];
592
831
  }
593
832
  }
833
+ this._cachedQueries = result;
594
834
  return result;
595
835
  }
596
836
  header(name) {
597
837
  this.checkReleased();
598
- return this._request.headers.get(name) ?? void 0;
838
+ return this._request.headers.get(name) ?? undefined;
599
839
  }
600
840
  headers() {
601
841
  this.checkReleased();
@@ -607,6 +847,39 @@ var FastRequestImpl = class {
607
847
  }
608
848
  return { ...this._headers };
609
849
  }
850
+ get cookies() {
851
+ this.checkReleased();
852
+ if (this._cachedCookies !== null) {
853
+ return this._cachedCookies;
854
+ }
855
+ const nativeCookies = this._request.cookies;
856
+ if (nativeCookies) {
857
+ this._cachedCookies = nativeCookies;
858
+ return nativeCookies;
859
+ }
860
+ const cookieHeader = this._request.headers.get("cookie");
861
+ if (!cookieHeader) {
862
+ this._cachedCookies = {};
863
+ return {};
864
+ }
865
+ const cookies = {};
866
+ const pairs = cookieHeader.split(/;\s*/);
867
+ for (let i = 0;i < pairs.length; i++) {
868
+ const pair = pairs[i];
869
+ const idx = pair.indexOf("=");
870
+ if (idx > 0) {
871
+ const name = pair.substring(0, idx);
872
+ const value = pair.substring(idx + 1);
873
+ try {
874
+ cookies[name] = decodeURIComponent(value);
875
+ } catch {
876
+ cookies[name] = value;
877
+ }
878
+ }
879
+ }
880
+ this._cachedCookies = cookies;
881
+ return cookies;
882
+ }
610
883
  async json() {
611
884
  this.checkReleased();
612
885
  if (!this._jsonParsed) {
@@ -617,89 +890,75 @@ var FastRequestImpl = class {
617
890
  }
618
891
  async text() {
619
892
  this.checkReleased();
620
- return this._request.text();
893
+ if (!this._textParsed) {
894
+ this._cachedText = await this._request.text();
895
+ this._textParsed = true;
896
+ }
897
+ return this._cachedText;
621
898
  }
622
899
  async formData() {
623
900
  this.checkReleased();
624
- return this._request.formData();
901
+ if (!this._formDataParsed) {
902
+ this._cachedFormData = await this._request.formData();
903
+ this._formDataParsed = true;
904
+ }
905
+ return this._cachedFormData;
625
906
  }
626
907
  get raw() {
627
908
  this.checkReleased();
628
909
  return this._request;
629
910
  }
630
- };
631
- var FastContext = class {
911
+ }
912
+
913
+ class FastContext {
632
914
  req = new FastRequestImpl(this);
633
- // private _statusCode = 200
634
- _headers = new Headers();
635
- // Reuse this object
915
+ _headers = new Headers;
636
916
  _isReleased = false;
637
- // Made public for internal check access
638
- /**
639
- * Initialize context for a new request
640
- *
641
- * This is called when acquiring from the pool.
642
- */
917
+ _requestScope = null;
643
918
  init(request, params = {}, path = "", routePattern) {
644
919
  this._isReleased = false;
645
920
  this.req.init(request, params, path, routePattern);
646
- this._headers = new Headers();
921
+ this._headers = new Headers;
922
+ this._requestScope = new RequestScopeManager;
647
923
  return this;
648
924
  }
649
- /**
650
- * Reset context for pooling (Cleanup)
651
- *
652
- * This is called when releasing back to the pool.
653
- * Implements "Deep-Reset Protocol" and "Release Guard".
654
- */
655
925
  reset() {
656
926
  this._isReleased = true;
657
927
  this.req.reset();
658
928
  this._store.clear();
929
+ this._requestScope = null;
659
930
  }
660
- /**
661
- * Check if context is released
662
- */
663
931
  checkReleased() {
664
932
  if (this._isReleased) {
665
- throw new Error(
666
- "FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)"
667
- );
933
+ throw new Error("FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)");
668
934
  }
669
935
  }
670
- // ─────────────────────────────────────────────────────────────────────────
671
- // Response Helpers
672
- // ─────────────────────────────────────────────────────────────────────────
673
936
  json(data, status = 200) {
674
937
  this.checkReleased();
675
- this._headers.set("Content-Type", "application/json; charset=utf-8");
676
- return new Response(JSON.stringify(data), {
677
- status,
678
- headers: this._headers
679
- });
938
+ const headers = new Headers(this._headers);
939
+ headers.set("Content-Type", "application/json; charset=utf-8");
940
+ return Response.json(data, { status, headers });
680
941
  }
681
942
  text(text, status = 200) {
682
943
  this.checkReleased();
683
- this._headers.set("Content-Type", "text/plain; charset=utf-8");
684
- return new Response(text, {
685
- status,
686
- headers: this._headers
687
- });
944
+ const headers = new Headers(this._headers);
945
+ headers.set("Content-Type", "text/plain; charset=utf-8");
946
+ return new Response(text, { status, headers });
688
947
  }
689
948
  html(html, status = 200) {
690
949
  this.checkReleased();
691
- this._headers.set("Content-Type", "text/html; charset=utf-8");
692
- return new Response(html, {
693
- status,
694
- headers: this._headers
695
- });
950
+ const headers = new Headers(this._headers);
951
+ headers.set("Content-Type", "text/html; charset=utf-8");
952
+ return new Response(html, { status, headers });
953
+ }
954
+ escape(html) {
955
+ return bunEscapeHTML(html);
696
956
  }
697
957
  redirect(url, status = 302) {
698
958
  this.checkReleased();
699
- this._headers.set("Location", url);
700
959
  return new Response(null, {
701
960
  status,
702
- headers: this._headers
961
+ headers: { Location: url }
703
962
  });
704
963
  }
705
964
  body(data, status = 200) {
@@ -709,12 +968,19 @@ var FastContext = class {
709
968
  headers: this._headers
710
969
  });
711
970
  }
971
+ binary(data, status = 200) {
972
+ this.checkReleased();
973
+ const body = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
974
+ return new Response(body, {
975
+ status,
976
+ headers: { "Content-Type": "application/octet-stream" }
977
+ });
978
+ }
712
979
  stream(stream, status = 200) {
713
980
  this.checkReleased();
714
- this._headers.set("Content-Type", "application/octet-stream");
715
981
  return new Response(stream, {
716
982
  status,
717
- headers: this._headers
983
+ headers: { "Content-Type": "application/octet-stream" }
718
984
  });
719
985
  }
720
986
  notFound(message = "Not Found") {
@@ -732,9 +998,7 @@ var FastContext = class {
732
998
  async forward(target, _options = {}) {
733
999
  this.checkReleased();
734
1000
  const url = new URL(this.req.url);
735
- const targetUrl = new URL(
736
- target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`
737
- );
1001
+ const targetUrl = new URL(target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`);
738
1002
  const searchParams = new URLSearchParams(url.search);
739
1003
  searchParams.forEach((v, k) => {
740
1004
  targetUrl.searchParams.set(k, v);
@@ -743,13 +1007,12 @@ var FastContext = class {
743
1007
  method: this.req.method,
744
1008
  headers: this.req.raw.headers,
745
1009
  body: this.req.method !== "GET" && this.req.method !== "HEAD" ? this.req.raw.body : null,
746
- // @ts-expect-error - Bun/Fetch specific
747
1010
  duplex: "half"
748
1011
  });
749
1012
  }
750
1013
  header(name, value) {
751
1014
  this.checkReleased();
752
- if (value !== void 0) {
1015
+ if (value !== undefined) {
753
1016
  this._headers.set(name, value);
754
1017
  return;
755
1018
  }
@@ -758,34 +1021,47 @@ var FastContext = class {
758
1021
  status(_code) {
759
1022
  this.checkReleased();
760
1023
  }
761
- // ─────────────────────────────────────────────────────────────────────────
762
- // Context Variables
763
- // ─────────────────────────────────────────────────────────────────────────
764
- _store = /* @__PURE__ */ new Map();
1024
+ _store = new Map;
765
1025
  get(key) {
766
1026
  return this._store.get(key);
767
1027
  }
768
1028
  set(key, value) {
769
1029
  this._store.set(key, value);
770
1030
  }
771
- // ─────────────────────────────────────────────────────────────────────────
772
- // Lifecycle helpers
773
- // ─────────────────────────────────────────────────────────────────────────
1031
+ requestScope() {
1032
+ if (!this._requestScope) {
1033
+ throw new Error("RequestScope not initialized. Call init() first.");
1034
+ }
1035
+ return this._requestScope;
1036
+ }
1037
+ scoped(key, factory) {
1038
+ return this.requestScope().resolve(key, factory);
1039
+ }
774
1040
  route = () => "";
775
1041
  get native() {
776
1042
  return this;
777
1043
  }
778
- };
1044
+ }
779
1045
 
780
1046
  // src/engine/MinimalContext.ts
781
- var MinimalRequest = class {
1047
+ var bunEscapeHTML2 = globalThis.Bun.escapeHTML;
1048
+
1049
+ class MinimalRequest {
1050
+ _request;
1051
+ _params;
1052
+ _path;
1053
+ _routePattern;
1054
+ _searchParams = null;
1055
+ _cachedQueries = null;
1056
+ _cachedJsonPromise = null;
1057
+ _cachedTextPromise = null;
1058
+ _cachedFormDataPromise = null;
782
1059
  constructor(_request, _params, _path, _routePattern) {
783
1060
  this._request = _request;
784
1061
  this._params = _params;
785
1062
  this._path = _path;
786
1063
  this._routePattern = _routePattern;
787
1064
  }
788
- _searchParams = null;
789
1065
  get url() {
790
1066
  return this._request.url;
791
1067
  }
@@ -804,15 +1080,12 @@ var MinimalRequest = class {
804
1080
  params() {
805
1081
  return { ...this._params };
806
1082
  }
807
- /**
808
- * Lazy-initialize searchParams, only parse once
809
- */
810
1083
  getSearchParams() {
811
1084
  if (this._searchParams === null) {
812
1085
  const url = this._request.url;
813
1086
  const queryStart = url.indexOf("?");
814
1087
  if (queryStart === -1) {
815
- this._searchParams = new URLSearchParams();
1088
+ this._searchParams = new URLSearchParams;
816
1089
  } else {
817
1090
  const hashStart = url.indexOf("#", queryStart);
818
1091
  const queryString = hashStart === -1 ? url.slice(queryStart + 1) : url.slice(queryStart + 1, hashStart);
@@ -822,14 +1095,17 @@ var MinimalRequest = class {
822
1095
  return this._searchParams;
823
1096
  }
824
1097
  query(name) {
825
- return this.getSearchParams().get(name) ?? void 0;
1098
+ return this.getSearchParams().get(name) ?? undefined;
826
1099
  }
827
1100
  queries() {
1101
+ if (this._cachedQueries !== null) {
1102
+ return this._cachedQueries;
1103
+ }
828
1104
  const params = this.getSearchParams();
829
1105
  const result = {};
830
1106
  for (const [key, value] of params.entries()) {
831
1107
  const existing = result[key];
832
- if (existing === void 0) {
1108
+ if (existing === undefined) {
833
1109
  result[key] = value;
834
1110
  } else if (Array.isArray(existing)) {
835
1111
  existing.push(value);
@@ -837,10 +1113,11 @@ var MinimalRequest = class {
837
1113
  result[key] = [existing, value];
838
1114
  }
839
1115
  }
1116
+ this._cachedQueries = result;
840
1117
  return result;
841
1118
  }
842
1119
  header(name) {
843
- return this._request.headers.get(name) ?? void 0;
1120
+ return this._request.headers.get(name) ?? undefined;
844
1121
  }
845
1122
  headers() {
846
1123
  const result = {};
@@ -850,33 +1127,65 @@ var MinimalRequest = class {
850
1127
  return result;
851
1128
  }
852
1129
  async json() {
853
- return this._request.json();
1130
+ if (this._cachedJsonPromise === null) {
1131
+ this._cachedJsonPromise = this._request.json();
1132
+ }
1133
+ return this._cachedJsonPromise;
854
1134
  }
855
1135
  async text() {
856
- return this._request.text();
1136
+ if (this._cachedTextPromise === null) {
1137
+ this._cachedTextPromise = this._request.text();
1138
+ }
1139
+ return this._cachedTextPromise;
857
1140
  }
858
1141
  async formData() {
859
- return this._request.formData();
1142
+ if (this._cachedFormDataPromise === null) {
1143
+ this._cachedFormDataPromise = this._request.formData();
1144
+ }
1145
+ return this._cachedFormDataPromise;
1146
+ }
1147
+ get cookies() {
1148
+ const nativeCookies = this._request.cookies;
1149
+ if (nativeCookies) {
1150
+ return nativeCookies;
1151
+ }
1152
+ const cookieHeader = this._request.headers.get("cookie");
1153
+ if (!cookieHeader) {
1154
+ return {};
1155
+ }
1156
+ const cookies = {};
1157
+ const pairs = cookieHeader.split(/;\s*/);
1158
+ for (let i = 0;i < pairs.length; i++) {
1159
+ const pair = pairs[i];
1160
+ const idx = pair.indexOf("=");
1161
+ if (idx > 0) {
1162
+ const name = pair.substring(0, idx);
1163
+ const value = pair.substring(idx + 1);
1164
+ try {
1165
+ cookies[name] = decodeURIComponent(value);
1166
+ } catch {
1167
+ cookies[name] = value;
1168
+ }
1169
+ }
1170
+ }
1171
+ return cookies;
860
1172
  }
861
1173
  get raw() {
862
1174
  return this._request;
863
1175
  }
864
- };
865
- var MinimalContext = class {
1176
+ }
1177
+
1178
+ class MinimalContext {
866
1179
  req;
867
1180
  _resHeaders = {};
1181
+ _requestScope;
868
1182
  constructor(request, params, path, routePattern) {
869
1183
  this.req = new MinimalRequest(request, params, path, routePattern);
1184
+ this._requestScope = new RequestScopeManager;
870
1185
  }
871
- // get req(): FastRequest {
872
- // return this._req
873
- // }
874
- // Response helpers - merge custom headers with defaults
875
1186
  getHeaders(contentType) {
876
- return {
877
- ...this._resHeaders,
878
- "Content-Type": contentType
879
- };
1187
+ const headers = Object.assign({ "Content-Type": contentType }, this._resHeaders);
1188
+ return headers;
880
1189
  }
881
1190
  json(data, status = 200) {
882
1191
  return new Response(JSON.stringify(data), {
@@ -909,14 +1218,13 @@ var MinimalContext = class {
909
1218
  });
910
1219
  }
911
1220
  header(name, value) {
912
- if (value !== void 0) {
1221
+ if (value !== undefined) {
913
1222
  this._resHeaders[name] = value;
914
1223
  return;
915
1224
  }
916
1225
  return this.req.header(name);
917
1226
  }
918
- status(_code) {
919
- }
1227
+ status(_code) {}
920
1228
  stream(stream, status = 200) {
921
1229
  return new Response(stream, {
922
1230
  status,
@@ -937,31 +1245,34 @@ var MinimalContext = class {
937
1245
  }
938
1246
  async forward(target, _options = {}) {
939
1247
  const url = new URL(this.req.url);
940
- const targetUrl = new URL(
941
- target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`
942
- );
1248
+ const targetUrl = new URL(target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`);
943
1249
  return fetch(targetUrl.toString(), {
944
1250
  method: this.req.method,
945
1251
  headers: this.req.raw.headers
946
1252
  });
947
1253
  }
1254
+ escape(html) {
1255
+ return bunEscapeHTML2(html);
1256
+ }
948
1257
  get(_key) {
949
- return void 0;
1258
+ return;
950
1259
  }
951
- set(_key, _value) {
1260
+ set(_key, _value) {}
1261
+ requestScope() {
1262
+ return this._requestScope;
1263
+ }
1264
+ scoped(key, factory) {
1265
+ return this._requestScope.resolve(key, factory);
952
1266
  }
953
1267
  route = () => "";
954
1268
  get native() {
955
1269
  return this;
956
1270
  }
957
- // Required for interface compatibility
958
1271
  init(_request, _params, _path) {
959
1272
  throw new Error("MinimalContext does not support init. Create a new instance instead.");
960
1273
  }
961
- // Required for interface compatibility
962
- reset() {
963
- }
964
- };
1274
+ reset() {}
1275
+ }
965
1276
 
966
1277
  // src/engine/path.ts
967
1278
  function extractPath(url) {
@@ -979,79 +1290,38 @@ function extractPath(url) {
979
1290
  }
980
1291
 
981
1292
  // src/engine/pool.ts
982
- var ObjectPool = class {
1293
+ class ObjectPool {
983
1294
  pool = [];
984
1295
  factory;
985
1296
  reset;
986
1297
  maxSize;
987
- /**
988
- * Create a new object pool
989
- *
990
- * @param factory - Function to create new objects
991
- * @param reset - Function to reset objects before reuse
992
- * @param maxSize - Maximum pool size (default: 256)
993
- */
994
1298
  constructor(factory, reset, maxSize = 256) {
995
1299
  this.factory = factory;
996
1300
  this.reset = reset;
997
1301
  this.maxSize = maxSize;
998
1302
  }
999
- /**
1000
- * Acquire an object from the pool
1001
- *
1002
- * If the pool is empty, creates a new object (overflow strategy).
1003
- * This ensures the pool never blocks under high load.
1004
- *
1005
- * @returns Object from pool or newly created
1006
- */
1007
1303
  acquire() {
1008
1304
  const obj = this.pool.pop();
1009
- if (obj !== void 0) {
1305
+ if (obj !== undefined) {
1010
1306
  return obj;
1011
1307
  }
1012
1308
  return this.factory();
1013
1309
  }
1014
- /**
1015
- * Release an object back to the pool
1016
- *
1017
- * If the pool is full, the object is discarded (will be GC'd).
1018
- * This prevents unbounded memory growth.
1019
- *
1020
- * @param obj - Object to release
1021
- */
1022
1310
  release(obj) {
1023
1311
  if (this.pool.length < this.maxSize) {
1024
1312
  this.reset(obj);
1025
1313
  this.pool.push(obj);
1026
1314
  }
1027
1315
  }
1028
- /**
1029
- * Clear all objects from the pool
1030
- *
1031
- * Useful for testing or when you need to force a clean slate.
1032
- */
1033
1316
  clear() {
1034
1317
  this.pool = [];
1035
1318
  }
1036
- /**
1037
- * Get current pool size
1038
- */
1039
1319
  get size() {
1040
1320
  return this.pool.length;
1041
1321
  }
1042
- /**
1043
- * Get maximum pool size
1044
- */
1045
1322
  get capacity() {
1046
1323
  return this.maxSize;
1047
1324
  }
1048
- /**
1049
- * Pre-warm the pool by creating objects in advance
1050
- *
1051
- * This can reduce latency for the first N requests.
1052
- *
1053
- * @param count - Number of objects to pre-create
1054
- */
1055
1325
  prewarm(count) {
1056
1326
  const targetSize = Math.min(count, this.maxSize);
1057
1327
  while (this.pool.length < targetSize) {
@@ -1060,55 +1330,88 @@ var ObjectPool = class {
1060
1330
  this.pool.push(obj);
1061
1331
  }
1062
1332
  }
1063
- };
1333
+ }
1064
1334
 
1065
1335
  // src/engine/Gravito.ts
1336
+ var bunPeek = globalThis.Bun.peek;
1066
1337
  function compileMiddlewareChain(middleware, handler) {
1067
1338
  if (middleware.length === 0) {
1068
1339
  return handler;
1069
1340
  }
1341
+ if (middleware.length === 1) {
1342
+ const mw = middleware[0];
1343
+ return async (ctx) => {
1344
+ let nextCalled = false;
1345
+ const result = mw(ctx, async () => {
1346
+ nextCalled = true;
1347
+ return;
1348
+ });
1349
+ let finalResult;
1350
+ if (result instanceof Promise) {
1351
+ const peeked = bunPeek(result);
1352
+ finalResult = peeked === result ? await result : peeked;
1353
+ } else {
1354
+ finalResult = result;
1355
+ }
1356
+ if (finalResult instanceof Response) {
1357
+ return finalResult;
1358
+ }
1359
+ if (nextCalled) {
1360
+ const hResult = handler(ctx);
1361
+ if (hResult instanceof Promise) {
1362
+ const p = bunPeek(hResult);
1363
+ return p === hResult ? await hResult : p;
1364
+ }
1365
+ return hResult;
1366
+ }
1367
+ return ctx.json({ error: "Middleware did not call next or return response" }, 500);
1368
+ };
1369
+ }
1070
1370
  let compiled = handler;
1071
- for (let i = middleware.length - 1; i >= 0; i--) {
1371
+ for (let i = middleware.length - 1;i >= 0; i--) {
1072
1372
  const mw = middleware[i];
1073
1373
  const nextHandler = compiled;
1074
1374
  compiled = async (ctx) => {
1075
- let nextResult;
1076
- const next = async () => {
1077
- nextResult = await nextHandler(ctx);
1375
+ let nextCalled = false;
1376
+ const result = mw(ctx, async () => {
1377
+ nextCalled = true;
1378
+ return;
1379
+ });
1380
+ let finalResult;
1381
+ if (result instanceof Promise) {
1382
+ const peeked = bunPeek(result);
1383
+ finalResult = peeked === result ? await result : peeked;
1384
+ } else {
1385
+ finalResult = result;
1386
+ }
1387
+ if (finalResult instanceof Response) {
1388
+ return finalResult;
1389
+ }
1390
+ if (nextCalled) {
1391
+ const nextResult = nextHandler(ctx);
1392
+ if (nextResult instanceof Promise) {
1393
+ const p = bunPeek(nextResult);
1394
+ return p === nextResult ? await nextResult : p;
1395
+ }
1078
1396
  return nextResult;
1079
- };
1080
- const result = await mw(ctx, next);
1081
- return result ?? nextResult;
1397
+ }
1398
+ return ctx.json({ error: "Middleware did not call next or return response" }, 500);
1082
1399
  };
1083
1400
  }
1084
1401
  return compiled;
1085
1402
  }
1086
- var Gravito = class {
1087
- router = new AOTRouter();
1403
+
1404
+ class Gravito {
1405
+ router = new AOTRouter;
1088
1406
  contextPool;
1089
1407
  errorHandler;
1090
1408
  notFoundHandler;
1091
- // Direct reference to static routes Map (O(1) access)
1092
- /** @internal */
1093
1409
  staticRoutes;
1094
- // Flag: pure static app (no middleware at all) allows ultra-fast path
1095
1410
  isPureStaticApp = true;
1096
- // Cache for precompiled dynamic routes
1097
- compiledDynamicRoutes = /* @__PURE__ */ new Map();
1098
- // Version tracking for cache invalidation
1099
- middlewareVersion = 0;
1100
- /**
1101
- * Create a new Gravito instance
1102
- *
1103
- * @param options - Engine configuration options
1104
- */
1411
+ compiledDynamicRoutes = new Map;
1105
1412
  constructor(options = {}) {
1106
1413
  const poolSize = options.poolSize ?? 256;
1107
- this.contextPool = new ObjectPool(
1108
- () => new FastContext(),
1109
- (ctx) => ctx.reset(),
1110
- poolSize
1111
- );
1414
+ this.contextPool = new ObjectPool(() => new FastContext, (ctx) => ctx.reset(), poolSize);
1112
1415
  this.contextPool.prewarm(Math.min(32, poolSize));
1113
1416
  if (options.onError) {
1114
1417
  this.errorHandler = options.onError;
@@ -1118,58 +1421,27 @@ var Gravito = class {
1118
1421
  }
1119
1422
  this.compileRoutes();
1120
1423
  }
1121
- // ─────────────────────────────────────────────────────────────────────────
1122
- // HTTP Method Registration
1123
- // ─────────────────────────────────────────────────────────────────────────
1124
- /**
1125
- * Register a GET route
1126
- *
1127
- * @param path - Route path (e.g., '/users/:id')
1128
- * @param handlers - Handler and optional middleware
1129
- * @returns This instance for chaining
1130
- */
1131
1424
  get(path, ...handlers) {
1132
1425
  return this.addRoute("get", path, handlers);
1133
1426
  }
1134
- /**
1135
- * Register a POST route
1136
- */
1137
1427
  post(path, ...handlers) {
1138
1428
  return this.addRoute("post", path, handlers);
1139
1429
  }
1140
- /**
1141
- * Register a PUT route
1142
- */
1143
1430
  put(path, ...handlers) {
1144
1431
  return this.addRoute("put", path, handlers);
1145
1432
  }
1146
- /**
1147
- * Register a DELETE route
1148
- */
1149
1433
  delete(path, ...handlers) {
1150
1434
  return this.addRoute("delete", path, handlers);
1151
1435
  }
1152
- /**
1153
- * Register a PDF route
1154
- */
1155
1436
  patch(path, ...handlers) {
1156
1437
  return this.addRoute("patch", path, handlers);
1157
1438
  }
1158
- /**
1159
- * Register an OPTIONS route
1160
- */
1161
1439
  options(path, ...handlers) {
1162
1440
  return this.addRoute("options", path, handlers);
1163
1441
  }
1164
- /**
1165
- * Register a HEAD route
1166
- */
1167
1442
  head(path, ...handlers) {
1168
1443
  return this.addRoute("head", path, handlers);
1169
1444
  }
1170
- /**
1171
- * Register a route for all HTTP methods
1172
- */
1173
1445
  all(path, ...handlers) {
1174
1446
  const methods = ["get", "post", "put", "delete", "patch", "options", "head"];
1175
1447
  for (const method of methods) {
@@ -1184,49 +1456,22 @@ var Gravito = class {
1184
1456
  } else {
1185
1457
  this.router.use(pathOrMiddleware, ...middleware);
1186
1458
  }
1187
- this.middlewareVersion++;
1188
1459
  this.compileRoutes();
1189
1460
  return this;
1190
1461
  }
1191
- // ─────────────────────────────────────────────────────────────────────────
1192
- // Route Grouping
1193
- // ─────────────────────────────────────────────────────────────────────────
1194
- /**
1195
- * Mount a sub-application at a path prefix
1196
- */
1197
1462
  route(path, app) {
1198
1463
  this.router.mount(path, app.router);
1199
1464
  this.compileRoutes();
1200
1465
  return this;
1201
1466
  }
1202
- // ─────────────────────────────────────────────────────────────────────────
1203
- // Error Handling
1204
- // ─────────────────────────────────────────────────────────────────────────
1205
- /**
1206
- * Set custom error handler
1207
- */
1208
1467
  onError(handler) {
1209
1468
  this.errorHandler = handler;
1210
1469
  return this;
1211
1470
  }
1212
- /**
1213
- * Set custom 404 handler
1214
- */
1215
1471
  notFound(handler) {
1216
1472
  this.notFoundHandler = handler;
1217
1473
  return this;
1218
1474
  }
1219
- // ─────────────────────────────────────────────────────────────────────────
1220
- // Request Handling (Bun.serve integration)
1221
- // ─────────────────────────────────────────────────────────────────────────
1222
- /**
1223
- * Predictive Route Warming (JIT Optimization)
1224
- *
1225
- * Simulates requests to specified routes to trigger JIT compilation (FTL)
1226
- * before real traffic arrives.
1227
- *
1228
- * @param paths List of paths to warm up (e.g. ['/api/users', '/health'])
1229
- */
1230
1475
  async warmup(paths) {
1231
1476
  const dummyReqOpts = { headers: { "User-Agent": "Gravito-Warmup/1.0" } };
1232
1477
  for (const path of paths) {
@@ -1234,86 +1479,135 @@ var Gravito = class {
1234
1479
  await this.fetch(req);
1235
1480
  }
1236
1481
  }
1237
- /**
1238
- * Handle an incoming request
1239
- */
1482
+ serveConfig(baseConfig = {}) {
1483
+ const nativeRoutes = this.router.getNativeRoutes((handler, middleware, path) => {
1484
+ const compiled = compileMiddlewareChain(middleware, handler);
1485
+ return async (req) => {
1486
+ const ctx = this.contextPool.acquire();
1487
+ ctx.init(req, {}, path, path);
1488
+ try {
1489
+ const result = compiled(ctx);
1490
+ let response;
1491
+ if (result instanceof Promise) {
1492
+ const peeked = bunPeek(result);
1493
+ response = peeked === result ? await result : peeked;
1494
+ } else {
1495
+ response = result;
1496
+ }
1497
+ const cleanup = ctx.requestScope().cleanup();
1498
+ if (cleanup instanceof Promise)
1499
+ await cleanup;
1500
+ this.contextPool.release(ctx);
1501
+ return response;
1502
+ } catch (error) {
1503
+ const cleanup = ctx.requestScope().cleanup();
1504
+ if (cleanup instanceof Promise)
1505
+ await cleanup;
1506
+ this.contextPool.release(ctx);
1507
+ return this.handleErrorSync(error, req, path);
1508
+ }
1509
+ };
1510
+ });
1511
+ return {
1512
+ ...baseConfig,
1513
+ routes: nativeRoutes,
1514
+ fetch: this.fetch,
1515
+ tls: baseConfig.tls ? this.optimizeTLS(baseConfig.tls) : undefined,
1516
+ error: (error) => {
1517
+ console.error("Native route error:", error);
1518
+ return new Response(CACHED_RESPONSES.INTERNAL_ERROR, {
1519
+ status: 500,
1520
+ headers: HEADERS.JSON
1521
+ });
1522
+ }
1523
+ };
1524
+ }
1525
+ optimizeTLS(tls) {
1526
+ const isProd = false;
1527
+ const optimizeEntry = (entry) => {
1528
+ const optimized = { ...entry };
1529
+ if (typeof optimized.key === "string" && !optimized.key.startsWith("-----BEGIN")) {
1530
+ optimized.key = globalThis.Bun.file(optimized.key);
1531
+ }
1532
+ if (typeof optimized.cert === "string" && !optimized.cert.startsWith("-----BEGIN")) {
1533
+ optimized.cert = globalThis.Bun.file(optimized.cert);
1534
+ }
1535
+ if (isProd && optimized.lowMemoryMode === undefined) {
1536
+ optimized.lowMemoryMode = true;
1537
+ }
1538
+ return optimized;
1539
+ };
1540
+ return Array.isArray(tls) ? tls.map(optimizeEntry) : optimizeEntry(tls);
1541
+ }
1240
1542
  fetch = async (request) => {
1241
1543
  const path = extractPath(request.url);
1242
1544
  const method = request.method.toLowerCase();
1243
1545
  const staticKey = `${method}:${path}`;
1244
1546
  const staticRoute = this.staticRoutes.get(staticKey);
1245
1547
  if (staticRoute) {
1246
- if (staticRoute.useMinimal) {
1247
- const ctx = new MinimalContext(request, {}, path, path);
1248
- try {
1249
- const result = staticRoute.handler(ctx);
1250
- if (result instanceof Response) {
1251
- return result;
1252
- }
1253
- return await result;
1254
- } catch (error) {
1255
- return this.handleErrorSync(error, request, path);
1548
+ const ctx = this.contextPool.acquire();
1549
+ ctx.init(request, {}, path, path);
1550
+ try {
1551
+ const compiled = staticRoute.compiled || compileMiddlewareChain(staticRoute.middleware, staticRoute.handler);
1552
+ const result = compiled(ctx);
1553
+ let response;
1554
+ if (result instanceof Promise) {
1555
+ const peeked = bunPeek(result);
1556
+ response = peeked === result ? await result : peeked;
1557
+ } else {
1558
+ response = result;
1256
1559
  }
1560
+ const cleanup = ctx.requestScope().cleanup();
1561
+ if (cleanup instanceof Promise)
1562
+ await cleanup;
1563
+ this.contextPool.release(ctx);
1564
+ return response;
1565
+ } catch (error) {
1566
+ const cleanup = ctx.requestScope().cleanup();
1567
+ if (cleanup instanceof Promise)
1568
+ await cleanup;
1569
+ this.contextPool.release(ctx);
1570
+ return this.handleErrorSync(error, request, path);
1257
1571
  }
1258
- return await this.handleWithMiddleware(request, path, staticRoute);
1259
1572
  }
1260
1573
  return await this.handleDynamicRoute(request, method, path);
1261
1574
  };
1262
- /**
1263
- * Handle routes with middleware (async path)
1264
- */
1265
- async handleWithMiddleware(request, path, route) {
1266
- const ctx = this.contextPool.acquire();
1267
- try {
1268
- ctx.init(request, {}, path, path);
1269
- if (route.compiled) {
1270
- return await route.compiled(ctx);
1271
- }
1272
- const middleware = this.collectMiddlewareForPath(path, route.middleware);
1273
- if (middleware.length === 0) {
1274
- return await route.handler(ctx);
1275
- }
1276
- return await this.executeMiddleware(ctx, middleware, route.handler);
1277
- } catch (error) {
1278
- return await this.handleError(error, ctx);
1279
- } finally {
1280
- this.contextPool.release(ctx);
1281
- }
1282
- }
1283
- /**
1284
- * Handle dynamic routes (Radix Tree lookup)
1285
- */
1286
- handleDynamicRoute(request, method, path) {
1287
- const match = this.router.match(method.toUpperCase(), path);
1288
- if (!match.handler) {
1289
- return this.handleNotFoundSync(request, path);
1290
- }
1291
- const cacheKey = `${method}:${match.routePattern ?? path}`;
1292
- let entry = this.compiledDynamicRoutes.get(cacheKey);
1293
- if (!entry || entry.version !== this.middlewareVersion) {
1294
- const compiled = compileMiddlewareChain(match.middleware, match.handler);
1295
- if (this.compiledDynamicRoutes.size > 1e3) {
1296
- this.compiledDynamicRoutes.clear();
1297
- }
1298
- entry = { compiled, version: this.middlewareVersion };
1299
- this.compiledDynamicRoutes.set(cacheKey, entry);
1300
- }
1301
- const ctx = this.contextPool.acquire();
1302
- const execute = async () => {
1575
+ async handleDynamicRoute(request, method, path) {
1576
+ const match = this.router.match(method, path);
1577
+ if (match.handler) {
1578
+ const ctx = this.contextPool.acquire();
1579
+ ctx.init(request, match.params, path, match.routePattern);
1303
1580
  try {
1304
- ctx.init(request, match.params, path, match.routePattern);
1305
- return await entry?.compiled(ctx);
1581
+ const routeKey = `${method}:${match.routePattern}`;
1582
+ let compiledObj = this.compiledDynamicRoutes.get(routeKey);
1583
+ if (!compiledObj || compiledObj.version !== this.router.version) {
1584
+ const compiled = compileMiddlewareChain(match.middleware, match.handler);
1585
+ compiledObj = { compiled, version: this.router.version };
1586
+ this.compiledDynamicRoutes.set(routeKey, compiledObj);
1587
+ }
1588
+ const result = compiledObj.compiled(ctx);
1589
+ let response;
1590
+ if (result instanceof Promise) {
1591
+ const peeked = bunPeek(result);
1592
+ response = peeked === result ? await result : peeked;
1593
+ } else {
1594
+ response = result;
1595
+ }
1596
+ const cleanup = ctx.requestScope().cleanup();
1597
+ if (cleanup instanceof Promise)
1598
+ await cleanup;
1599
+ this.contextPool.release(ctx);
1600
+ return response;
1306
1601
  } catch (error) {
1307
- return await this.handleError(error, ctx);
1308
- } finally {
1602
+ const cleanup = ctx.requestScope().cleanup();
1603
+ if (cleanup instanceof Promise)
1604
+ await cleanup;
1309
1605
  this.contextPool.release(ctx);
1606
+ return this.handleErrorSync(error, request, path);
1310
1607
  }
1311
- };
1312
- return execute();
1608
+ }
1609
+ return this.handleNotFoundSync(request, path);
1313
1610
  }
1314
- /**
1315
- * Sync error handler (for ultra-fast path)
1316
- */
1317
1611
  handleErrorSync(error, request, path) {
1318
1612
  if (this.errorHandler) {
1319
1613
  const ctx = new MinimalContext(request, {}, path);
@@ -1329,9 +1623,6 @@ var Gravito = class {
1329
1623
  headers: HEADERS.JSON
1330
1624
  });
1331
1625
  }
1332
- /**
1333
- * Sync 404 handler (for ultra-fast path)
1334
- */
1335
1626
  handleNotFoundSync(request, path) {
1336
1627
  if (this.notFoundHandler) {
1337
1628
  const ctx = new MinimalContext(request, {}, path);
@@ -1346,25 +1637,19 @@ var Gravito = class {
1346
1637
  headers: HEADERS.JSON
1347
1638
  });
1348
1639
  }
1349
- /**
1350
- * Collect middleware for a specific path
1351
- */
1352
1640
  collectMiddlewareForPath(path, routeMiddleware) {
1353
1641
  if (this.router.globalMiddleware.length === 0 && this.router.pathMiddleware.size === 0) {
1354
1642
  return routeMiddleware;
1355
1643
  }
1356
1644
  return this.router.collectMiddlewarePublic(path, routeMiddleware);
1357
1645
  }
1358
- /**
1359
- * Compile routes for optimization
1360
- */
1361
1646
  compileRoutes() {
1362
1647
  this.staticRoutes = this.router.staticRoutes;
1363
1648
  const hasGlobalMiddleware = this.router.globalMiddleware.length > 0;
1364
1649
  const hasPathMiddleware = this.router.pathMiddleware.size > 0;
1365
1650
  this.isPureStaticApp = !hasGlobalMiddleware && !hasPathMiddleware;
1366
1651
  for (const [key, route] of this.staticRoutes) {
1367
- if (route.compiledVersion === this.middlewareVersion) {
1652
+ if (route.compiledVersion === this.router.version) {
1368
1653
  continue;
1369
1654
  }
1370
1655
  const analysis = analyzeHandler(route.handler);
@@ -1374,12 +1659,9 @@ var Gravito = class {
1374
1659
  const allMiddleware = this.collectMiddlewareForPath(key.split(":")[1], route.middleware);
1375
1660
  route.compiled = compileMiddlewareChain(allMiddleware, route.handler);
1376
1661
  }
1377
- route.compiledVersion = this.middlewareVersion;
1662
+ route.compiledVersion = this.router.version;
1378
1663
  }
1379
1664
  }
1380
- /**
1381
- * Add a route to the router
1382
- */
1383
1665
  addRoute(method, path, handlers) {
1384
1666
  if (handlers.length === 0) {
1385
1667
  throw new Error(`No handler provided for ${method.toUpperCase()} ${path}`);
@@ -1390,46 +1672,14 @@ var Gravito = class {
1390
1672
  this.compileRoutes();
1391
1673
  return this;
1392
1674
  }
1393
- /**
1394
- * Execute middleware chain followed by handler
1395
- */
1396
- async executeMiddleware(ctx, middleware, handler) {
1397
- let index = 0;
1398
- const next = async () => {
1399
- if (index < middleware.length) {
1400
- const mw = middleware[index++];
1401
- return await mw(ctx, next);
1402
- }
1403
- return void 0;
1404
- };
1405
- const result = await next();
1406
- if (result instanceof Response) {
1407
- return result;
1408
- }
1409
- return await handler(ctx);
1410
- }
1411
- /**
1412
- * Handle errors (Async version for dynamic/middleware paths)
1413
- */
1414
- async handleError(error, ctx) {
1415
- if (this.errorHandler) {
1416
- return await this.errorHandler(error, ctx);
1417
- }
1418
- console.error("Unhandled error:", error);
1419
- return ctx.json(
1420
- {
1421
- error: "Internal Server Error",
1422
- message: error.message
1423
- },
1424
- 500
1425
- );
1426
- }
1427
- };
1675
+ }
1428
1676
  export {
1429
- AOTRouter,
1430
- FastContext as FastContextImpl,
1431
- Gravito,
1432
- MinimalContext,
1677
+ extractPath,
1433
1678
  ObjectPool,
1434
- extractPath
1679
+ MinimalContext,
1680
+ Gravito,
1681
+ FastContext as FastContextImpl,
1682
+ AOTRouter
1435
1683
  };
1684
+
1685
+ //# debugId=13A90DBD3E511D5864756E2164756E21