@gravito/core 1.6.1 → 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 (173) 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 +576 -647
  53. package/dist/engine/index.cjs.map +22 -0
  54. package/dist/engine/index.d.ts +14 -910
  55. package/dist/engine/index.js +576 -623
  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-CI8hiulX.d.cts → http/types.d.ts} +29 -16
  129. package/dist/index.browser.d.ts +34 -0
  130. package/dist/index.cjs +10525 -11171
  131. package/dist/index.cjs.map +168 -0
  132. package/dist/index.d.ts +58 -10981
  133. package/dist/index.js +10861 -10997
  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 +21 -52
  167. package/src/ffi/native/cbor.c +1148 -0
  168. package/dist/Metrics-VOWWRNNR.js +0 -219
  169. package/dist/chunk-R5U7XKVJ.js +0 -16
  170. package/dist/compat-CI8hiulX.d.ts +0 -376
  171. package/dist/compat.d.cts +0 -1
  172. package/dist/engine/index.d.cts +0 -922
  173. package/dist/index.d.cts +0 -11008
@@ -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,49 +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;
269
+ pathMiddleware = new Map;
270
+ dynamicRoutePatterns = new Map;
271
+ middlewareCache = new Map;
272
+ cacheMaxSize = 1000;
260
273
  _version = 0;
261
- /**
262
- * Get the current version for cache invalidation
263
- * Incremented whenever middleware or routes are modified
264
- */
265
274
  get version() {
266
275
  return this._version;
267
276
  }
268
- /**
269
- * Register a route
270
- *
271
- * Automatically determines if route is static or dynamic.
272
- * Static routes are stored in a Map for O(1) lookup.
273
- * Dynamic routes use the Radix Tree.
274
- *
275
- * @param method - HTTP method
276
- * @param path - Route path
277
- * @param handler - Route handler
278
- * @param middleware - Route-specific middleware
279
- */
280
277
  add(method, path, handler, middleware = []) {
281
278
  this.routeDefinitions.push({ method, path, handler, middleware });
282
279
  const normalizedMethod = method.toLowerCase();
@@ -292,9 +289,6 @@ var AOTRouter = class {
292
289
  }
293
290
  }
294
291
  }
295
- /**
296
- * Mount another router at a prefix
297
- */
298
292
  mount(prefix, other) {
299
293
  if (other.globalMiddleware.length > 0) {
300
294
  this.usePattern(prefix, ...other.globalMiddleware);
@@ -302,7 +296,8 @@ var AOTRouter = class {
302
296
  this.usePattern(wildcard, ...other.globalMiddleware);
303
297
  }
304
298
  for (const [pattern, mws] of other.pathMiddleware) {
305
- if (pattern.includes(":")) {
299
+ const hasMethodPrefix = /^(get|post|put|delete|patch|options|head):/.test(pattern);
300
+ if (hasMethodPrefix) {
306
301
  continue;
307
302
  }
308
303
  let newPattern;
@@ -327,25 +322,10 @@ var AOTRouter = class {
327
322
  this.add(def.method, newPath, def.handler, def.middleware);
328
323
  }
329
324
  }
330
- /**
331
- * Add global middleware
332
- *
333
- * These run for every request, before route-specific middleware.
334
- *
335
- * @param middleware - Middleware functions
336
- */
337
325
  use(...middleware) {
338
326
  this.globalMiddleware.push(...middleware);
339
327
  this._version++;
340
328
  }
341
- /**
342
- * Add path-based middleware
343
- *
344
- * Supports wildcard patterns like '/api/*'
345
- *
346
- * @param pattern - Path pattern
347
- * @param middleware - Middleware functions
348
- */
349
329
  usePattern(pattern, ...middleware) {
350
330
  if (pattern === "*") {
351
331
  this.globalMiddleware.push(...middleware);
@@ -355,15 +335,6 @@ var AOTRouter = class {
355
335
  }
356
336
  this._version++;
357
337
  }
358
- /**
359
- * Match a request to a route
360
- *
361
- * Returns the handler, params, and all applicable middleware.
362
- *
363
- * @param method - HTTP method
364
- * @param path - Request path
365
- * @returns Route match or null if not found
366
- */
367
338
  match(method, path) {
368
339
  const normalizedMethod = method.toLowerCase();
369
340
  const staticKey = `${normalizedMethod}:${path}`;
@@ -396,28 +367,16 @@ var AOTRouter = class {
396
367
  middleware: []
397
368
  };
398
369
  }
399
- /**
400
- * Public wrapper for collectMiddleware (used by Gravito for optimization)
401
- */
402
370
  collectMiddlewarePublic(path, routeMiddleware) {
403
371
  return this.collectMiddleware(path, routeMiddleware);
404
372
  }
405
- /**
406
- * Collect all applicable middleware for a path
407
- *
408
- * Order: global -> pattern-based -> route-specific
409
- *
410
- * @param path - Request path
411
- * @param routeMiddleware - Route-specific middleware
412
- * @returns Combined middleware array
413
- */
414
373
  collectMiddleware(path, routeMiddleware) {
415
374
  if (this.globalMiddleware.length === 0 && this.pathMiddleware.size === 0 && routeMiddleware.length === 0) {
416
375
  return [];
417
376
  }
418
377
  const cacheKey = path;
419
378
  const cached = this.middlewareCache.get(cacheKey);
420
- if (cached !== void 0 && cached.version === this._version) {
379
+ if (cached !== undefined && cached.version === this._version) {
421
380
  return cached.data;
422
381
  }
423
382
  const middleware = [];
@@ -444,23 +403,21 @@ var AOTRouter = class {
444
403
  }
445
404
  return middleware;
446
405
  }
447
- /**
448
- * Check if a path is static (no parameters or wildcards)
449
- */
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
+ }
450
418
  isStaticPath(path) {
451
419
  return !path.includes(":") && !path.includes("*");
452
420
  }
453
- /**
454
- * Match a pattern against a path
455
- *
456
- * Supports:
457
- * - Exact match: '/api/users'
458
- * - Wildcard suffix: '/api/*'
459
- *
460
- * @param pattern - Pattern to match
461
- * @param path - Path to test
462
- * @returns True if pattern matches
463
- */
464
421
  matchPattern(pattern, path) {
465
422
  if (pattern === "*") {
466
423
  return true;
@@ -474,9 +431,6 @@ var AOTRouter = class {
474
431
  }
475
432
  return false;
476
433
  }
477
- /**
478
- * Get all registered routes (for debugging)
479
- */
480
434
  getRoutes() {
481
435
  const routes = [];
482
436
  for (const key of this.staticRoutes.keys()) {
@@ -485,11 +439,107 @@ var AOTRouter = class {
485
439
  }
486
440
  return routes;
487
441
  }
488
- };
442
+ }
489
443
 
490
- // src/engine/analyzer.ts
491
- function analyzeHandler(handler) {
492
- 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) {
493
543
  return {
494
544
  usesHeaders: source.includes(".header(") || source.includes(".header)") || source.includes(".headers(") || source.includes(".headers)"),
495
545
  usesQuery: source.includes(".query(") || source.includes(".query)") || source.includes(".queries(") || source.includes(".queries)"),
@@ -498,6 +548,12 @@ function analyzeHandler(handler) {
498
548
  isAsync: source.includes("async") || source.includes("await")
499
549
  };
500
550
  }
551
+
552
+ // src/engine/analyzer.ts
553
+ function analyzeHandler(handler) {
554
+ const source = handler.toString();
555
+ return analyzeHandlerWithTranspiler(source);
556
+ }
501
557
  function getOptimalContextType(analysis) {
502
558
  if (analysis.usesHeaders) {
503
559
  return "fast";
@@ -515,7 +571,7 @@ function getOptimalContextType(analysis) {
515
571
  }
516
572
 
517
573
  // src/engine/constants.ts
518
- var encoder = new TextEncoder();
574
+ var encoder = new TextEncoder;
519
575
  var CACHED_RESPONSES = {
520
576
  NOT_FOUND: encoder.encode('{"error":"Not Found"}'),
521
577
  INTERNAL_ERROR: encoder.encode('{"error":"Internal Server Error"}'),
@@ -529,25 +585,15 @@ var HEADERS = {
529
585
  };
530
586
 
531
587
  // src/Container/RequestScopeMetrics.ts
532
- var RequestScopeMetrics = class {
588
+ class RequestScopeMetrics {
533
589
  cleanupStartTime = null;
534
590
  cleanupDuration = null;
535
591
  scopeSize = 0;
536
592
  servicesCleaned = 0;
537
593
  errorsOccurred = 0;
538
- /**
539
- * Record start of cleanup operation
540
- */
541
594
  recordCleanupStart() {
542
595
  this.cleanupStartTime = performance.now();
543
596
  }
544
- /**
545
- * Record end of cleanup operation
546
- *
547
- * @param scopeSize - Number of services in the scope
548
- * @param servicesCleaned - Number of services that had cleanup called
549
- * @param errorsOccurred - Number of cleanup errors
550
- */
551
597
  recordCleanupEnd(scopeSize, servicesCleaned, errorsOccurred = 0) {
552
598
  if (this.cleanupStartTime !== null) {
553
599
  this.cleanupDuration = performance.now() - this.cleanupStartTime;
@@ -557,28 +603,15 @@ var RequestScopeMetrics = class {
557
603
  this.servicesCleaned = servicesCleaned;
558
604
  this.errorsOccurred = errorsOccurred;
559
605
  }
560
- /**
561
- * Get cleanup duration in milliseconds
562
- *
563
- * @returns Duration in ms, or null if cleanup not completed
564
- */
565
606
  getCleanupDuration() {
566
607
  return this.cleanupDuration;
567
608
  }
568
- /**
569
- * Check if cleanup took longer than threshold (default 2ms)
570
- * Useful for detecting slow cleanups
571
- *
572
- * @param thresholdMs - Threshold in milliseconds
573
- * @returns True if cleanup exceeded threshold
574
- */
575
609
  isSlowCleanup(thresholdMs = 2) {
576
- if (this.cleanupDuration === null) return false;
610
+ if (this.cleanupDuration === null) {
611
+ return false;
612
+ }
577
613
  return this.cleanupDuration > thresholdMs;
578
614
  }
579
- /**
580
- * Export metrics as JSON for logging/monitoring
581
- */
582
615
  toJSON() {
583
616
  return {
584
617
  cleanupDuration: this.cleanupDuration,
@@ -589,49 +622,66 @@ var RequestScopeMetrics = class {
589
622
  isSlowCleanup: this.isSlowCleanup()
590
623
  };
591
624
  }
592
- /**
593
- * Export metrics as compact string for logging
594
- */
595
625
  toString() {
596
626
  const duration = this.cleanupDuration ?? "pending";
597
- return `cleanup: ${duration}ms, scope: ${this.scopeSize}, cleaned: ${this.servicesCleaned}, errors: ${this.errorsOccurred}`;
627
+ return `cleanup: ${duration}ms, ` + `scope: ${this.scopeSize}, ` + `cleaned: ${this.servicesCleaned}, ` + `errors: ${this.errorsOccurred}`;
598
628
  }
599
- };
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
+ }
600
669
 
601
670
  // src/Container/RequestScopeManager.ts
602
- var RequestScopeManager = class {
603
- scoped = /* @__PURE__ */ new Map();
604
- metadata = /* @__PURE__ */ new Map();
605
- metrics = new RequestScopeMetrics();
671
+ class RequestScopeManager {
672
+ scoped = new Map;
673
+ metadata = new Map;
674
+ metrics = new RequestScopeMetrics;
606
675
  observer = null;
607
676
  constructor(observer) {
608
677
  this.observer = observer || null;
609
678
  }
610
- /**
611
- * Set observer for monitoring scope lifecycle
612
- */
613
679
  setObserver(observer) {
614
680
  this.observer = observer;
615
681
  }
616
- /**
617
- * Get metrics for this scope
618
- */
619
682
  getMetrics() {
620
683
  return this.metrics;
621
684
  }
622
- /**
623
- * Resolve or retrieve a request-scoped service instance.
624
- *
625
- * If the service already exists in this scope, returns the cached instance.
626
- * Otherwise, calls the factory function to create a new instance and caches it.
627
- *
628
- * Automatically detects and records services with cleanup methods.
629
- *
630
- * @template T - The type of the service.
631
- * @param key - The service key (for caching).
632
- * @param factory - Factory function to create the instance if not cached.
633
- * @returns The cached or newly created instance.
634
- */
635
685
  resolve(key, factory) {
636
686
  const keyStr = String(key);
637
687
  const isFromCache = this.scoped.has(keyStr);
@@ -645,15 +695,6 @@ var RequestScopeManager = class {
645
695
  this.observer?.onServiceResolved?.(key, isFromCache);
646
696
  return this.scoped.get(keyStr);
647
697
  }
648
- /**
649
- * Clean up all request-scoped instances.
650
- *
651
- * Calls the cleanup() method on each service that has one.
652
- * Silently ignores cleanup errors to prevent cascading failures.
653
- * Called automatically by the Gravito engine in the request finally block.
654
- *
655
- * @returns Promise that resolves when all cleanup is complete.
656
- */
657
698
  async cleanup() {
658
699
  this.metrics.recordCleanupStart();
659
700
  this.observer?.onCleanupStart?.();
@@ -668,9 +709,7 @@ var RequestScopeManager = class {
668
709
  servicesCleaned++;
669
710
  } catch (error) {
670
711
  errors.push(error);
671
- this.observer?.onCleanupError?.(
672
- error instanceof Error ? error : new Error(String(error))
673
- );
712
+ this.observer?.onCleanupError?.(error instanceof Error ? error : new Error(String(error)));
674
713
  }
675
714
  }
676
715
  }
@@ -684,18 +723,15 @@ var RequestScopeManager = class {
684
723
  console.error("RequestScope cleanup errors:", errors);
685
724
  }
686
725
  }
687
- /**
688
- * Get the number of services in this scope (for monitoring).
689
- *
690
- * @returns The count of cached services.
691
- */
692
726
  size() {
693
727
  return this.scoped.size;
694
728
  }
695
- };
729
+ }
696
730
 
697
731
  // src/engine/FastContext.ts
698
- var FastRequestImpl = class {
732
+ var bunEscapeHTML = globalThis.Bun.escapeHTML;
733
+
734
+ class FastRequestImpl {
699
735
  _request;
700
736
  _params;
701
737
  _path;
@@ -703,21 +739,18 @@ var FastRequestImpl = class {
703
739
  _url = null;
704
740
  _query = null;
705
741
  _headers = null;
706
- _cachedJson = void 0;
742
+ _cachedJson = undefined;
707
743
  _jsonParsed = false;
708
- _cachedText = void 0;
744
+ _cachedText = undefined;
709
745
  _textParsed = false;
710
- _cachedFormData = void 0;
746
+ _cachedFormData = undefined;
711
747
  _formDataParsed = false;
712
748
  _cachedQueries = null;
713
- // Back-reference for release check optimization
749
+ _cachedCookies = null;
714
750
  _ctx;
715
751
  constructor(ctx) {
716
752
  this._ctx = ctx;
717
753
  }
718
- /**
719
- * Initialize for new request
720
- */
721
754
  init(request, params = {}, path = "", routePattern) {
722
755
  this._request = request;
723
756
  this._params = params;
@@ -726,37 +759,34 @@ var FastRequestImpl = class {
726
759
  this._url = null;
727
760
  this._query = null;
728
761
  this._headers = null;
729
- this._cachedJson = void 0;
762
+ this._cachedJson = undefined;
730
763
  this._jsonParsed = false;
731
- this._cachedText = void 0;
764
+ this._cachedText = undefined;
732
765
  this._textParsed = false;
733
- this._cachedFormData = void 0;
766
+ this._cachedFormData = undefined;
734
767
  this._formDataParsed = false;
735
768
  this._cachedQueries = null;
769
+ this._cachedCookies = null;
736
770
  return this;
737
771
  }
738
- /**
739
- * Reset for pooling
740
- */
741
772
  reset() {
742
- this._request = void 0;
743
- this._params = void 0;
773
+ this._request = undefined;
774
+ this._params = undefined;
744
775
  this._url = null;
745
776
  this._query = null;
746
777
  this._headers = null;
747
- this._cachedJson = void 0;
778
+ this._cachedJson = undefined;
748
779
  this._jsonParsed = false;
749
- this._cachedText = void 0;
780
+ this._cachedText = undefined;
750
781
  this._textParsed = false;
751
- this._cachedFormData = void 0;
782
+ this._cachedFormData = undefined;
752
783
  this._formDataParsed = false;
753
784
  this._cachedQueries = null;
785
+ this._cachedCookies = null;
754
786
  }
755
787
  checkReleased() {
756
788
  if (this._ctx._isReleased) {
757
- throw new Error(
758
- "FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)"
759
- );
789
+ throw new Error("FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)");
760
790
  }
761
791
  }
762
792
  get url() {
@@ -794,7 +824,7 @@ var FastRequestImpl = class {
794
824
  if (!this._query) {
795
825
  this._query = this.getUrl().searchParams;
796
826
  }
797
- return this._query.get(name) ?? void 0;
827
+ return this._query.get(name) ?? undefined;
798
828
  }
799
829
  queries() {
800
830
  this.checkReleased();
@@ -807,7 +837,7 @@ var FastRequestImpl = class {
807
837
  const result = {};
808
838
  for (const [key, value] of this._query.entries()) {
809
839
  const existing = result[key];
810
- if (existing === void 0) {
840
+ if (existing === undefined) {
811
841
  result[key] = value;
812
842
  } else if (Array.isArray(existing)) {
813
843
  existing.push(value);
@@ -820,7 +850,7 @@ var FastRequestImpl = class {
820
850
  }
821
851
  header(name) {
822
852
  this.checkReleased();
823
- return this._request.headers.get(name) ?? void 0;
853
+ return this._request.headers.get(name) ?? undefined;
824
854
  }
825
855
  headers() {
826
856
  this.checkReleased();
@@ -832,6 +862,39 @@ var FastRequestImpl = class {
832
862
  }
833
863
  return { ...this._headers };
834
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
+ }
835
898
  async json() {
836
899
  this.checkReleased();
837
900
  if (!this._jsonParsed) {
@@ -860,82 +923,57 @@ var FastRequestImpl = class {
860
923
  this.checkReleased();
861
924
  return this._request;
862
925
  }
863
- };
864
- var FastContext = class {
926
+ }
927
+
928
+ class FastContext {
865
929
  req = new FastRequestImpl(this);
866
- // private _statusCode = 200
867
- _headers = new Headers();
868
- // Reuse this object
930
+ _headers = new Headers;
869
931
  _isReleased = false;
870
- // Made public for internal check access
871
932
  _requestScope = null;
872
- // Request-scoped services
873
- /**
874
- * Initialize context for a new request
875
- *
876
- * This is called when acquiring from the pool.
877
- */
878
933
  init(request, params = {}, path = "", routePattern) {
879
934
  this._isReleased = false;
880
935
  this.req.init(request, params, path, routePattern);
881
- this._headers = new Headers();
882
- this._requestScope = new RequestScopeManager();
936
+ this._headers = new Headers;
937
+ this._requestScope = new RequestScopeManager;
883
938
  return this;
884
939
  }
885
- /**
886
- * Reset context for pooling (Cleanup)
887
- *
888
- * This is called when releasing back to the pool.
889
- * Implements "Deep-Reset Protocol" and "Release Guard".
890
- */
891
940
  reset() {
892
941
  this._isReleased = true;
893
942
  this.req.reset();
894
943
  this._store.clear();
944
+ this._requestScope = null;
895
945
  }
896
- /**
897
- * Check if context is released
898
- */
899
946
  checkReleased() {
900
947
  if (this._isReleased) {
901
- throw new Error(
902
- "FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)"
903
- );
948
+ throw new Error("FastContext usage after release detected! (Object Pool Strict Lifecycle Guard)");
904
949
  }
905
950
  }
906
- // ─────────────────────────────────────────────────────────────────────────
907
- // Response Helpers
908
- // ─────────────────────────────────────────────────────────────────────────
909
951
  json(data, status = 200) {
910
952
  this.checkReleased();
911
- this._headers.set("Content-Type", "application/json; charset=utf-8");
912
- return new Response(JSON.stringify(data), {
913
- status,
914
- headers: this._headers
915
- });
953
+ const headers = new Headers(this._headers);
954
+ headers.set("Content-Type", "application/json; charset=utf-8");
955
+ return Response.json(data, { status, headers });
916
956
  }
917
957
  text(text, status = 200) {
918
958
  this.checkReleased();
919
- this._headers.set("Content-Type", "text/plain; charset=utf-8");
920
- return new Response(text, {
921
- status,
922
- headers: this._headers
923
- });
959
+ const headers = new Headers(this._headers);
960
+ headers.set("Content-Type", "text/plain; charset=utf-8");
961
+ return new Response(text, { status, headers });
924
962
  }
925
963
  html(html, status = 200) {
926
964
  this.checkReleased();
927
- this._headers.set("Content-Type", "text/html; charset=utf-8");
928
- return new Response(html, {
929
- status,
930
- headers: this._headers
931
- });
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);
932
971
  }
933
972
  redirect(url, status = 302) {
934
973
  this.checkReleased();
935
- this._headers.set("Location", url);
936
974
  return new Response(null, {
937
975
  status,
938
- headers: this._headers
976
+ headers: { Location: url }
939
977
  });
940
978
  }
941
979
  body(data, status = 200) {
@@ -945,12 +983,19 @@ var FastContext = class {
945
983
  headers: this._headers
946
984
  });
947
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
+ }
948
994
  stream(stream, status = 200) {
949
995
  this.checkReleased();
950
- this._headers.set("Content-Type", "application/octet-stream");
951
996
  return new Response(stream, {
952
997
  status,
953
- headers: this._headers
998
+ headers: { "Content-Type": "application/octet-stream" }
954
999
  });
955
1000
  }
956
1001
  notFound(message = "Not Found") {
@@ -968,9 +1013,7 @@ var FastContext = class {
968
1013
  async forward(target, _options = {}) {
969
1014
  this.checkReleased();
970
1015
  const url = new URL(this.req.url);
971
- const targetUrl = new URL(
972
- target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`
973
- );
1016
+ const targetUrl = new URL(target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`);
974
1017
  const searchParams = new URLSearchParams(url.search);
975
1018
  searchParams.forEach((v, k) => {
976
1019
  targetUrl.searchParams.set(k, v);
@@ -979,13 +1022,12 @@ var FastContext = class {
979
1022
  method: this.req.method,
980
1023
  headers: this.req.raw.headers,
981
1024
  body: this.req.method !== "GET" && this.req.method !== "HEAD" ? this.req.raw.body : null,
982
- // @ts-expect-error - Bun/Fetch specific
983
1025
  duplex: "half"
984
1026
  });
985
1027
  }
986
1028
  header(name, value) {
987
1029
  this.checkReleased();
988
- if (value !== void 0) {
1030
+ if (value !== undefined) {
989
1031
  this._headers.set(name, value);
990
1032
  return;
991
1033
  }
@@ -994,64 +1036,47 @@ var FastContext = class {
994
1036
  status(_code) {
995
1037
  this.checkReleased();
996
1038
  }
997
- // ─────────────────────────────────────────────────────────────────────────
998
- // Context Variables
999
- // ─────────────────────────────────────────────────────────────────────────
1000
- _store = /* @__PURE__ */ new Map();
1039
+ _store = new Map;
1001
1040
  get(key) {
1002
1041
  return this._store.get(key);
1003
1042
  }
1004
1043
  set(key, value) {
1005
1044
  this._store.set(key, value);
1006
1045
  }
1007
- // ─────────────────────────────────────────────────────────────────────────
1008
- // Request Scope Management
1009
- // ─────────────────────────────────────────────────────────────────────────
1010
- /**
1011
- * Get the request-scoped service manager for this request.
1012
- *
1013
- * @returns The RequestScopeManager for this request.
1014
- * @throws Error if called before init() or after reset().
1015
- */
1016
1046
  requestScope() {
1017
1047
  if (!this._requestScope) {
1018
1048
  throw new Error("RequestScope not initialized. Call init() first.");
1019
1049
  }
1020
1050
  return this._requestScope;
1021
1051
  }
1022
- /**
1023
- * Resolve a request-scoped service (convenience method).
1024
- *
1025
- * @template T - The service type.
1026
- * @param key - The service key for caching.
1027
- * @param factory - Factory function to create the service.
1028
- * @returns The cached or newly created service instance.
1029
- */
1030
1052
  scoped(key, factory) {
1031
1053
  return this.requestScope().resolve(key, factory);
1032
1054
  }
1033
- // ─────────────────────────────────────────────────────────────────────────
1034
- // Lifecycle helpers
1035
- // ─────────────────────────────────────────────────────────────────────────
1036
1055
  route = () => "";
1037
1056
  get native() {
1038
1057
  return this;
1039
1058
  }
1040
- };
1059
+ }
1041
1060
 
1042
1061
  // src/engine/MinimalContext.ts
1043
- 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;
1044
1074
  constructor(_request, _params, _path, _routePattern) {
1045
1075
  this._request = _request;
1046
1076
  this._params = _params;
1047
1077
  this._path = _path;
1048
1078
  this._routePattern = _routePattern;
1049
1079
  }
1050
- _searchParams = null;
1051
- _cachedQueries = null;
1052
- _cachedJsonPromise = null;
1053
- _cachedTextPromise = null;
1054
- _cachedFormDataPromise = null;
1055
1080
  get url() {
1056
1081
  return this._request.url;
1057
1082
  }
@@ -1070,15 +1095,12 @@ var MinimalRequest = class {
1070
1095
  params() {
1071
1096
  return { ...this._params };
1072
1097
  }
1073
- /**
1074
- * Lazy-initialize searchParams, only parse once
1075
- */
1076
1098
  getSearchParams() {
1077
1099
  if (this._searchParams === null) {
1078
1100
  const url = this._request.url;
1079
1101
  const queryStart = url.indexOf("?");
1080
1102
  if (queryStart === -1) {
1081
- this._searchParams = new URLSearchParams();
1103
+ this._searchParams = new URLSearchParams;
1082
1104
  } else {
1083
1105
  const hashStart = url.indexOf("#", queryStart);
1084
1106
  const queryString = hashStart === -1 ? url.slice(queryStart + 1) : url.slice(queryStart + 1, hashStart);
@@ -1088,7 +1110,7 @@ var MinimalRequest = class {
1088
1110
  return this._searchParams;
1089
1111
  }
1090
1112
  query(name) {
1091
- return this.getSearchParams().get(name) ?? void 0;
1113
+ return this.getSearchParams().get(name) ?? undefined;
1092
1114
  }
1093
1115
  queries() {
1094
1116
  if (this._cachedQueries !== null) {
@@ -1098,7 +1120,7 @@ var MinimalRequest = class {
1098
1120
  const result = {};
1099
1121
  for (const [key, value] of params.entries()) {
1100
1122
  const existing = result[key];
1101
- if (existing === void 0) {
1123
+ if (existing === undefined) {
1102
1124
  result[key] = value;
1103
1125
  } else if (Array.isArray(existing)) {
1104
1126
  existing.push(value);
@@ -1110,7 +1132,7 @@ var MinimalRequest = class {
1110
1132
  return result;
1111
1133
  }
1112
1134
  header(name) {
1113
- return this._request.headers.get(name) ?? void 0;
1135
+ return this._request.headers.get(name) ?? undefined;
1114
1136
  }
1115
1137
  headers() {
1116
1138
  const result = {};
@@ -1137,23 +1159,45 @@ var MinimalRequest = class {
1137
1159
  }
1138
1160
  return this._cachedFormDataPromise;
1139
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;
1187
+ }
1140
1188
  get raw() {
1141
1189
  return this._request;
1142
1190
  }
1143
- };
1144
- var MinimalContext = class {
1191
+ }
1192
+
1193
+ class MinimalContext {
1145
1194
  req;
1146
1195
  _resHeaders = {};
1147
1196
  _requestScope;
1148
1197
  constructor(request, params, path, routePattern) {
1149
1198
  this.req = new MinimalRequest(request, params, path, routePattern);
1150
- this._requestScope = new RequestScopeManager();
1199
+ this._requestScope = new RequestScopeManager;
1151
1200
  }
1152
- // get req(): FastRequest {
1153
- // return this._req
1154
- // }
1155
- // Response helpers - merge custom headers with defaults
1156
- // Optimized: use Object.assign instead of spread to avoid shallow copy overhead
1157
1201
  getHeaders(contentType) {
1158
1202
  const headers = Object.assign({ "Content-Type": contentType }, this._resHeaders);
1159
1203
  return headers;
@@ -1189,14 +1233,13 @@ var MinimalContext = class {
1189
1233
  });
1190
1234
  }
1191
1235
  header(name, value) {
1192
- if (value !== void 0) {
1236
+ if (value !== undefined) {
1193
1237
  this._resHeaders[name] = value;
1194
1238
  return;
1195
1239
  }
1196
1240
  return this.req.header(name);
1197
1241
  }
1198
- status(_code) {
1199
- }
1242
+ status(_code) {}
1200
1243
  stream(stream, status = 200) {
1201
1244
  return new Response(stream, {
1202
1245
  status,
@@ -1217,35 +1260,22 @@ var MinimalContext = class {
1217
1260
  }
1218
1261
  async forward(target, _options = {}) {
1219
1262
  const url = new URL(this.req.url);
1220
- const targetUrl = new URL(
1221
- target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`
1222
- );
1263
+ const targetUrl = new URL(target.startsWith("http") ? target : `${url.protocol}//${target}${this.req.path}`);
1223
1264
  return fetch(targetUrl.toString(), {
1224
1265
  method: this.req.method,
1225
1266
  headers: this.req.raw.headers
1226
1267
  });
1227
1268
  }
1228
- get(_key) {
1229
- return void 0;
1269
+ escape(html) {
1270
+ return bunEscapeHTML2(html);
1230
1271
  }
1231
- set(_key, _value) {
1272
+ get(_key) {
1273
+ return;
1232
1274
  }
1233
- /**
1234
- * Get the request-scoped service manager for this request.
1235
- *
1236
- * @returns The RequestScopeManager for this request.
1237
- */
1275
+ set(_key, _value) {}
1238
1276
  requestScope() {
1239
1277
  return this._requestScope;
1240
1278
  }
1241
- /**
1242
- * Resolve a request-scoped service (convenience method).
1243
- *
1244
- * @template T - The service type.
1245
- * @param key - The service key for caching.
1246
- * @param factory - Factory function to create the service.
1247
- * @returns The cached or newly created service instance.
1248
- */
1249
1279
  scoped(key, factory) {
1250
1280
  return this._requestScope.resolve(key, factory);
1251
1281
  }
@@ -1253,14 +1283,11 @@ var MinimalContext = class {
1253
1283
  get native() {
1254
1284
  return this;
1255
1285
  }
1256
- // Required for interface compatibility
1257
1286
  init(_request, _params, _path) {
1258
1287
  throw new Error("MinimalContext does not support init. Create a new instance instead.");
1259
1288
  }
1260
- // Required for interface compatibility
1261
- reset() {
1262
- }
1263
- };
1289
+ reset() {}
1290
+ }
1264
1291
 
1265
1292
  // src/engine/path.ts
1266
1293
  function extractPath(url) {
@@ -1278,79 +1305,38 @@ function extractPath(url) {
1278
1305
  }
1279
1306
 
1280
1307
  // src/engine/pool.ts
1281
- var ObjectPool = class {
1308
+ class ObjectPool {
1282
1309
  pool = [];
1283
1310
  factory;
1284
1311
  reset;
1285
1312
  maxSize;
1286
- /**
1287
- * Create a new object pool
1288
- *
1289
- * @param factory - Function to create new objects
1290
- * @param reset - Function to reset objects before reuse
1291
- * @param maxSize - Maximum pool size (default: 256)
1292
- */
1293
1313
  constructor(factory, reset, maxSize = 256) {
1294
1314
  this.factory = factory;
1295
1315
  this.reset = reset;
1296
1316
  this.maxSize = maxSize;
1297
1317
  }
1298
- /**
1299
- * Acquire an object from the pool
1300
- *
1301
- * If the pool is empty, creates a new object (overflow strategy).
1302
- * This ensures the pool never blocks under high load.
1303
- *
1304
- * @returns Object from pool or newly created
1305
- */
1306
1318
  acquire() {
1307
1319
  const obj = this.pool.pop();
1308
- if (obj !== void 0) {
1320
+ if (obj !== undefined) {
1309
1321
  return obj;
1310
1322
  }
1311
1323
  return this.factory();
1312
1324
  }
1313
- /**
1314
- * Release an object back to the pool
1315
- *
1316
- * If the pool is full, the object is discarded (will be GC'd).
1317
- * This prevents unbounded memory growth.
1318
- *
1319
- * @param obj - Object to release
1320
- */
1321
1325
  release(obj) {
1322
1326
  if (this.pool.length < this.maxSize) {
1323
1327
  this.reset(obj);
1324
1328
  this.pool.push(obj);
1325
1329
  }
1326
1330
  }
1327
- /**
1328
- * Clear all objects from the pool
1329
- *
1330
- * Useful for testing or when you need to force a clean slate.
1331
- */
1332
1331
  clear() {
1333
1332
  this.pool = [];
1334
1333
  }
1335
- /**
1336
- * Get current pool size
1337
- */
1338
1334
  get size() {
1339
1335
  return this.pool.length;
1340
1336
  }
1341
- /**
1342
- * Get maximum pool size
1343
- */
1344
1337
  get capacity() {
1345
1338
  return this.maxSize;
1346
1339
  }
1347
- /**
1348
- * Pre-warm the pool by creating objects in advance
1349
- *
1350
- * This can reduce latency for the first N requests.
1351
- *
1352
- * @param count - Number of objects to pre-create
1353
- */
1354
1340
  prewarm(count) {
1355
1341
  const targetSize = Math.min(count, this.maxSize);
1356
1342
  while (this.pool.length < targetSize) {
@@ -1359,9 +1345,10 @@ var ObjectPool = class {
1359
1345
  this.pool.push(obj);
1360
1346
  }
1361
1347
  }
1362
- };
1348
+ }
1363
1349
 
1364
1350
  // src/engine/Gravito.ts
1351
+ var bunPeek = globalThis.Bun.peek;
1365
1352
  function compileMiddlewareChain(middleware, handler) {
1366
1353
  if (middleware.length === 0) {
1367
1354
  return handler;
@@ -1370,64 +1357,76 @@ function compileMiddlewareChain(middleware, handler) {
1370
1357
  const mw = middleware[0];
1371
1358
  return async (ctx) => {
1372
1359
  let nextCalled = false;
1373
- const result = await mw(ctx, async () => {
1360
+ const result = mw(ctx, async () => {
1374
1361
  nextCalled = true;
1375
- return void 0;
1362
+ return;
1376
1363
  });
1377
- if (result instanceof Response) {
1378
- return result;
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;
1379
1373
  }
1380
1374
  if (nextCalled) {
1381
- return await handler(ctx);
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;
1382
1381
  }
1383
1382
  return ctx.json({ error: "Middleware did not call next or return response" }, 500);
1384
1383
  };
1385
1384
  }
1386
1385
  let compiled = handler;
1387
- for (let i = middleware.length - 1; i >= 0; i--) {
1386
+ for (let i = middleware.length - 1;i >= 0; i--) {
1388
1387
  const mw = middleware[i];
1389
1388
  const nextHandler = compiled;
1390
1389
  compiled = async (ctx) => {
1391
1390
  let nextCalled = false;
1392
- const result = await mw(ctx, async () => {
1391
+ const result = mw(ctx, async () => {
1393
1392
  nextCalled = true;
1394
- return void 0;
1393
+ return;
1395
1394
  });
1396
- if (result instanceof Response) {
1397
- return result;
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;
1398
1404
  }
1399
1405
  if (nextCalled) {
1400
- return await nextHandler(ctx);
1406
+ const nextResult = nextHandler(ctx);
1407
+ if (nextResult instanceof Promise) {
1408
+ const p = bunPeek(nextResult);
1409
+ return p === nextResult ? await nextResult : p;
1410
+ }
1411
+ return nextResult;
1401
1412
  }
1402
1413
  return ctx.json({ error: "Middleware did not call next or return response" }, 500);
1403
1414
  };
1404
1415
  }
1405
1416
  return compiled;
1406
1417
  }
1407
- var Gravito = class {
1408
- router = new AOTRouter();
1418
+
1419
+ class Gravito {
1420
+ router = new AOTRouter;
1409
1421
  contextPool;
1410
1422
  errorHandler;
1411
1423
  notFoundHandler;
1412
- // Direct reference to static routes Map (O(1) access)
1413
- /** @internal */
1414
1424
  staticRoutes;
1415
- // Flag: pure static app (no middleware at all) allows ultra-fast path
1416
1425
  isPureStaticApp = true;
1417
- // Cache for precompiled dynamic routes
1418
- compiledDynamicRoutes = /* @__PURE__ */ new Map();
1419
- /**
1420
- * Create a new Gravito instance
1421
- *
1422
- * @param options - Engine configuration options
1423
- */
1426
+ compiledDynamicRoutes = new Map;
1424
1427
  constructor(options = {}) {
1425
1428
  const poolSize = options.poolSize ?? 256;
1426
- this.contextPool = new ObjectPool(
1427
- () => new FastContext(),
1428
- (ctx) => ctx.reset(),
1429
- poolSize
1430
- );
1429
+ this.contextPool = new ObjectPool(() => new FastContext, (ctx) => ctx.reset(), poolSize);
1431
1430
  this.contextPool.prewarm(Math.min(32, poolSize));
1432
1431
  if (options.onError) {
1433
1432
  this.errorHandler = options.onError;
@@ -1437,58 +1436,27 @@ var Gravito = class {
1437
1436
  }
1438
1437
  this.compileRoutes();
1439
1438
  }
1440
- // ─────────────────────────────────────────────────────────────────────────
1441
- // HTTP Method Registration
1442
- // ─────────────────────────────────────────────────────────────────────────
1443
- /**
1444
- * Register a GET route
1445
- *
1446
- * @param path - Route path (e.g., '/users/:id')
1447
- * @param handlers - Handler and optional middleware
1448
- * @returns This instance for chaining
1449
- */
1450
1439
  get(path, ...handlers) {
1451
1440
  return this.addRoute("get", path, handlers);
1452
1441
  }
1453
- /**
1454
- * Register a POST route
1455
- */
1456
1442
  post(path, ...handlers) {
1457
1443
  return this.addRoute("post", path, handlers);
1458
1444
  }
1459
- /**
1460
- * Register a PUT route
1461
- */
1462
1445
  put(path, ...handlers) {
1463
1446
  return this.addRoute("put", path, handlers);
1464
1447
  }
1465
- /**
1466
- * Register a DELETE route
1467
- */
1468
1448
  delete(path, ...handlers) {
1469
1449
  return this.addRoute("delete", path, handlers);
1470
1450
  }
1471
- /**
1472
- * Register a PDF route
1473
- */
1474
1451
  patch(path, ...handlers) {
1475
1452
  return this.addRoute("patch", path, handlers);
1476
1453
  }
1477
- /**
1478
- * Register an OPTIONS route
1479
- */
1480
1454
  options(path, ...handlers) {
1481
1455
  return this.addRoute("options", path, handlers);
1482
1456
  }
1483
- /**
1484
- * Register a HEAD route
1485
- */
1486
1457
  head(path, ...handlers) {
1487
1458
  return this.addRoute("head", path, handlers);
1488
1459
  }
1489
- /**
1490
- * Register a route for all HTTP methods
1491
- */
1492
1460
  all(path, ...handlers) {
1493
1461
  const methods = ["get", "post", "put", "delete", "patch", "options", "head"];
1494
1462
  for (const method of methods) {
@@ -1506,45 +1474,19 @@ var Gravito = class {
1506
1474
  this.compileRoutes();
1507
1475
  return this;
1508
1476
  }
1509
- // ─────────────────────────────────────────────────────────────────────────
1510
- // Route Grouping
1511
- // ─────────────────────────────────────────────────────────────────────────
1512
- /**
1513
- * Mount a sub-application at a path prefix
1514
- */
1515
1477
  route(path, app) {
1516
1478
  this.router.mount(path, app.router);
1517
1479
  this.compileRoutes();
1518
1480
  return this;
1519
1481
  }
1520
- // ─────────────────────────────────────────────────────────────────────────
1521
- // Error Handling
1522
- // ─────────────────────────────────────────────────────────────────────────
1523
- /**
1524
- * Set custom error handler
1525
- */
1526
1482
  onError(handler) {
1527
1483
  this.errorHandler = handler;
1528
1484
  return this;
1529
1485
  }
1530
- /**
1531
- * Set custom 404 handler
1532
- */
1533
1486
  notFound(handler) {
1534
1487
  this.notFoundHandler = handler;
1535
1488
  return this;
1536
1489
  }
1537
- // ─────────────────────────────────────────────────────────────────────────
1538
- // Request Handling (Bun.serve integration)
1539
- // ─────────────────────────────────────────────────────────────────────────
1540
- /**
1541
- * Predictive Route Warming (JIT Optimization)
1542
- *
1543
- * Simulates requests to specified routes to trigger JIT compilation (FTL)
1544
- * before real traffic arrives.
1545
- *
1546
- * @param paths List of paths to warm up (e.g. ['/api/users', '/health'])
1547
- */
1548
1490
  async warmup(paths) {
1549
1491
  const dummyReqOpts = { headers: { "User-Agent": "Gravito-Warmup/1.0" } };
1550
1492
  for (const path of paths) {
@@ -1552,96 +1494,135 @@ var Gravito = class {
1552
1494
  await this.fetch(req);
1553
1495
  }
1554
1496
  }
1555
- /**
1556
- * Handle an incoming request
1557
- */
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
+ }
1558
1557
  fetch = async (request) => {
1559
1558
  const path = extractPath(request.url);
1560
1559
  const method = request.method.toLowerCase();
1561
1560
  const staticKey = `${method}:${path}`;
1562
1561
  const staticRoute = this.staticRoutes.get(staticKey);
1563
1562
  if (staticRoute) {
1564
- if (staticRoute.useMinimal) {
1565
- const ctx = new MinimalContext(request, {}, path, path);
1566
- try {
1567
- const result = staticRoute.handler(ctx);
1568
- if (result instanceof Response) {
1569
- return result;
1570
- }
1571
- return await result;
1572
- } catch (error) {
1573
- 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;
1574
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);
1575
1586
  }
1576
- return await this.handleWithMiddleware(request, path, staticRoute);
1577
1587
  }
1578
1588
  return await this.handleDynamicRoute(request, method, path);
1579
1589
  };
1580
- /**
1581
- * Handle routes with middleware (async path)
1582
- */
1583
- async handleWithMiddleware(request, path, route) {
1584
- const ctx = this.contextPool.acquire();
1585
- try {
1586
- ctx.init(request, {}, path, path);
1587
- if (route.compiled) {
1588
- return await route.compiled(ctx);
1589
- }
1590
- const middleware = this.collectMiddlewareForPath(path, route.middleware);
1591
- if (middleware.length === 0) {
1592
- return await route.handler(ctx);
1593
- }
1594
- return await this.executeMiddleware(ctx, middleware, route.handler);
1595
- } catch (error) {
1596
- return await this.handleError(error, ctx);
1597
- } finally {
1598
- try {
1599
- await ctx.requestScope().cleanup();
1600
- } catch (cleanupError) {
1601
- console.error("RequestScope cleanup failed:", cleanupError);
1602
- }
1603
- this.contextPool.release(ctx);
1604
- }
1605
- }
1606
- /**
1607
- * Handle dynamic routes (Radix Tree lookup)
1608
- */
1609
- handleDynamicRoute(request, method, path) {
1610
- const match = this.router.match(method.toUpperCase(), path);
1611
- if (!match.handler) {
1612
- return this.handleNotFoundSync(request, path);
1613
- }
1614
- const cacheKey = `${method}:${match.routePattern ?? path}`;
1615
- let entry = this.compiledDynamicRoutes.get(cacheKey);
1616
- if (!entry || entry.version !== this.router.version) {
1617
- const compiled = compileMiddlewareChain(match.middleware, match.handler);
1618
- if (this.compiledDynamicRoutes.size > 1e3) {
1619
- this.compiledDynamicRoutes.clear();
1620
- }
1621
- entry = { compiled, version: this.router.version };
1622
- this.compiledDynamicRoutes.set(cacheKey, entry);
1623
- }
1624
- const ctx = this.contextPool.acquire();
1625
- 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);
1626
1595
  try {
1627
- ctx.init(request, match.params, path, match.routePattern);
1628
- return await entry?.compiled(ctx);
1629
- } catch (error) {
1630
- return await this.handleError(error, ctx);
1631
- } finally {
1632
- try {
1633
- await ctx.requestScope().cleanup();
1634
- } catch (cleanupError) {
1635
- console.error("RequestScope cleanup failed:", cleanupError);
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;
1636
1610
  }
1611
+ const cleanup = ctx.requestScope().cleanup();
1612
+ if (cleanup instanceof Promise)
1613
+ await cleanup;
1637
1614
  this.contextPool.release(ctx);
1615
+ return response;
1616
+ } catch (error) {
1617
+ const cleanup = ctx.requestScope().cleanup();
1618
+ if (cleanup instanceof Promise)
1619
+ await cleanup;
1620
+ this.contextPool.release(ctx);
1621
+ return this.handleErrorSync(error, request, path);
1638
1622
  }
1639
- };
1640
- return execute();
1623
+ }
1624
+ return this.handleNotFoundSync(request, path);
1641
1625
  }
1642
- /**
1643
- * Sync error handler (for ultra-fast path)
1644
- */
1645
1626
  handleErrorSync(error, request, path) {
1646
1627
  if (this.errorHandler) {
1647
1628
  const ctx = new MinimalContext(request, {}, path);
@@ -1657,9 +1638,6 @@ var Gravito = class {
1657
1638
  headers: HEADERS.JSON
1658
1639
  });
1659
1640
  }
1660
- /**
1661
- * Sync 404 handler (for ultra-fast path)
1662
- */
1663
1641
  handleNotFoundSync(request, path) {
1664
1642
  if (this.notFoundHandler) {
1665
1643
  const ctx = new MinimalContext(request, {}, path);
@@ -1674,18 +1652,12 @@ var Gravito = class {
1674
1652
  headers: HEADERS.JSON
1675
1653
  });
1676
1654
  }
1677
- /**
1678
- * Collect middleware for a specific path
1679
- */
1680
1655
  collectMiddlewareForPath(path, routeMiddleware) {
1681
1656
  if (this.router.globalMiddleware.length === 0 && this.router.pathMiddleware.size === 0) {
1682
1657
  return routeMiddleware;
1683
1658
  }
1684
1659
  return this.router.collectMiddlewarePublic(path, routeMiddleware);
1685
1660
  }
1686
- /**
1687
- * Compile routes for optimization
1688
- */
1689
1661
  compileRoutes() {
1690
1662
  this.staticRoutes = this.router.staticRoutes;
1691
1663
  const hasGlobalMiddleware = this.router.globalMiddleware.length > 0;
@@ -1705,9 +1677,6 @@ var Gravito = class {
1705
1677
  route.compiledVersion = this.router.version;
1706
1678
  }
1707
1679
  }
1708
- /**
1709
- * Add a route to the router
1710
- */
1711
1680
  addRoute(method, path, handlers) {
1712
1681
  if (handlers.length === 0) {
1713
1682
  throw new Error(`No handler provided for ${method.toUpperCase()} ${path}`);
@@ -1718,47 +1687,7 @@ var Gravito = class {
1718
1687
  this.compileRoutes();
1719
1688
  return this;
1720
1689
  }
1721
- /**
1722
- * Execute middleware chain followed by handler
1723
- */
1724
- async executeMiddleware(ctx, middleware, handler) {
1725
- let index = 0;
1726
- const next = async () => {
1727
- if (index < middleware.length) {
1728
- const mw = middleware[index++];
1729
- return await mw(ctx, next);
1730
- }
1731
- return void 0;
1732
- };
1733
- const result = await next();
1734
- if (result instanceof Response) {
1735
- return result;
1736
- }
1737
- return await handler(ctx);
1738
- }
1739
- /**
1740
- * Handle errors (Async version for dynamic/middleware paths)
1741
- */
1742
- async handleError(error, ctx) {
1743
- if (this.errorHandler) {
1744
- return await this.errorHandler(error, ctx);
1745
- }
1746
- console.error("Unhandled error:", error);
1747
- return ctx.json(
1748
- {
1749
- error: "Internal Server Error",
1750
- message: error.message
1751
- },
1752
- 500
1753
- );
1754
- }
1755
- };
1756
- // Annotate the CommonJS export names for ESM import in node:
1757
- 0 && (module.exports = {
1758
- AOTRouter,
1759
- FastContextImpl,
1760
- Gravito,
1761
- MinimalContext,
1762
- ObjectPool,
1763
- extractPath
1764
- });
1690
+ }
1691
+ })
1692
+
1693
+ //# debugId=46FB5CAED852799864756E2164756E21