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