elysia 2.0.0-beta.13 → 2.0.0-beta.15

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 (90) hide show
  1. package/dist/adapter/bun/index.d.ts +4 -2
  2. package/dist/adapter/bun/index.js +35 -38
  3. package/dist/adapter/bun/index.mjs +35 -39
  4. package/dist/adapter/utils.js +16 -21
  5. package/dist/adapter/utils.mjs +16 -21
  6. package/dist/base.d.ts +28 -0
  7. package/dist/base.js +109 -59
  8. package/dist/base.mjs +110 -60
  9. package/dist/compile/aot.js +14 -21
  10. package/dist/compile/aot.mjs +14 -21
  11. package/dist/compile/handler/frozen-validator.js +51 -42
  12. package/dist/compile/handler/frozen-validator.mjs +51 -42
  13. package/dist/compile/handler/index.js +57 -50
  14. package/dist/compile/handler/index.mjs +57 -50
  15. package/dist/compile/handler/jit.js +36 -26
  16. package/dist/compile/handler/jit.mjs +37 -27
  17. package/dist/compile/handler/params.js +2 -0
  18. package/dist/compile/handler/params.mjs +3 -1
  19. package/dist/compile/handler/utils.d.ts +2 -2
  20. package/dist/compile/handler/utils.js +115 -111
  21. package/dist/compile/handler/utils.mjs +115 -113
  22. package/dist/context.d.ts +3 -1
  23. package/dist/context.js +2 -0
  24. package/dist/context.mjs +3 -1
  25. package/dist/cookie/config.js +6 -7
  26. package/dist/cookie/config.mjs +6 -7
  27. package/dist/error.d.ts +6 -3
  28. package/dist/error.js +26 -28
  29. package/dist/error.mjs +26 -28
  30. package/dist/handler/fetch.js +2 -1
  31. package/dist/handler/fetch.mjs +3 -2
  32. package/dist/handler/utils.d.ts +3 -1
  33. package/dist/handler/utils.js +19 -1
  34. package/dist/handler/utils.mjs +17 -1
  35. package/dist/index.d.ts +3 -3
  36. package/dist/package.js +1 -1
  37. package/dist/package.mjs +1 -1
  38. package/dist/plugin/aot/core.js +4 -0
  39. package/dist/plugin/aot/core.mjs +4 -0
  40. package/dist/sucrose.js +60 -59
  41. package/dist/sucrose.mjs +60 -59
  42. package/dist/trace.js +6 -9
  43. package/dist/trace.mjs +6 -9
  44. package/dist/type/coerce-plan.js +41 -36
  45. package/dist/type/coerce-plan.mjs +41 -36
  46. package/dist/type/coerce.d.ts +1 -1
  47. package/dist/type/constants.d.ts +1 -1
  48. package/dist/type/elysia/cookie.js +8 -17
  49. package/dist/type/elysia/cookie.mjs +8 -17
  50. package/dist/type/elysia/date.js +6 -7
  51. package/dist/type/elysia/date.mjs +6 -7
  52. package/dist/type/elysia/numeric.js +8 -9
  53. package/dist/type/elysia/numeric.mjs +8 -9
  54. package/dist/type/elysia/problem.d.ts +20 -0
  55. package/dist/type/elysia/problem.js +25 -0
  56. package/dist/type/elysia/problem.mjs +24 -0
  57. package/dist/type/exports.d.ts +3 -2
  58. package/dist/type/exports.js +2 -0
  59. package/dist/type/exports.mjs +2 -1
  60. package/dist/type/index.js +2 -0
  61. package/dist/type/index.mjs +2 -0
  62. package/dist/type/validator/clean-safe.d.ts +1 -2
  63. package/dist/type/validator/clean-safe.js +0 -2
  64. package/dist/type/validator/clean-safe.mjs +1 -2
  65. package/dist/type/validator/custom-error.js +37 -26
  66. package/dist/type/validator/custom-error.mjs +37 -26
  67. package/dist/type/validator/default-precompute.js +24 -26
  68. package/dist/type/validator/default-precompute.mjs +24 -26
  69. package/dist/type/validator/exact-mirror.js +6 -8
  70. package/dist/type/validator/exact-mirror.mjs +6 -8
  71. package/dist/type/validator/index.js +64 -66
  72. package/dist/type/validator/index.mjs +65 -67
  73. package/dist/type/validator/validator-cache.d.ts +2 -2
  74. package/dist/type/validator/validator-cache.js +7 -10
  75. package/dist/type/validator/validator-cache.mjs +6 -9
  76. package/dist/types.d.ts +4 -3
  77. package/dist/universal/file.js +2 -6
  78. package/dist/universal/file.mjs +2 -6
  79. package/dist/utils.d.ts +11 -2
  80. package/dist/utils.js +85 -47
  81. package/dist/utils.mjs +82 -48
  82. package/dist/validator/index.js +14 -18
  83. package/dist/validator/index.mjs +14 -18
  84. package/dist/ws/context.js +9 -11
  85. package/dist/ws/context.mjs +9 -11
  86. package/dist/ws/parser.js +23 -20
  87. package/dist/ws/parser.mjs +23 -20
  88. package/dist/ws/route.js +76 -87
  89. package/dist/ws/route.mjs +76 -87
  90. package/package.json +5 -2
@@ -65,7 +65,7 @@ function parse(adapter, parsers, bodyVali, hasHeaders, link, report, arm) {
65
65
  break;
66
66
  }
67
67
  }
68
- const bodyKind = hasFn ? void 0 : bodyMediaKind(bodyVali);
68
+ const bodyKind = hasFn ? void 0 : schemaMediaKind(bodyVali?.schema);
69
69
  let code = `let ct=((${hasHeaders ? "c.headers['content-type']" : "c.request.headers.get('content-type')"})||'')\nlet cti=ct.indexOf(";")
70
70
  if(cti!==-1)ct=ct.slice(0,cti)
71
71
  ` + (hasFn ? "c.contentType=ct\n" : "");
@@ -111,7 +111,6 @@ if(cti!==-1)ct=ct.slice(0,cti)
111
111
  }
112
112
  return hasFn ? "let hasBody=false,_bp\n" + code : code;
113
113
  }
114
- const bodyMediaKind = (bodyVali) => schemaMediaKind(bodyVali?.schema);
115
114
  function schemaMediaKind(schema) {
116
115
  if (!schema || typeof schema !== "object" || "~standard" in schema) return;
117
116
  const elyType = schema["~elyTyp"];
@@ -144,23 +143,11 @@ const createInlineHandler = (map, h) => ((c) => {
144
143
  if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(require_handler_utils.forwardError(v), c.request, true));
145
144
  return map(r, c.request, true);
146
145
  });
147
- const createInlineHandlerWithSet = (map, h) => ((c) => {
148
- const r = h(c);
149
- if (r instanceof Error) throw r;
150
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(require_handler_utils.forwardError(v), c.set, c.request, true));
151
- return map(r, c.set, c.request, true);
152
- });
153
- const createInlineHandlerWithDefaultHeaders = (map, h) => ((c) => {
154
- require_adapter_utils.materializeSetHeaders(c.set);
155
- const r = h(c);
156
- if (r instanceof Error) throw r;
157
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(require_handler_utils.forwardError(v), c.set, c.request, true));
158
- return map(r, c.set, c.request, true);
159
- });
160
146
  function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapter, isHandleFunction, isStaticResponse, isPromiseHandler, state }) {
161
147
  const { vali, inference, cookieConfig, beforeHandlePrefix, traceHandlers, tracePhases, hasAnyPhase, traceHandleOn, descriptor: { async: isAsync, responseMode, hasBody, bodyValiIsAsync, headersValiIsAsync, paramsValiIsAsync, queryValiIsAsync, cookieValiIsAsync: cookieValidIsAsync, responseValiAsync, hasCookieSign, syncCookieSign, asyncCookieSign, lazyCookieVerify, hasErrorHook, hasAfterResponse, hasBeforeHandle, hasAfterHandle, hasMapResponse, hasResponseValidator, hasTrace, traceCount, hasLifecycleHook, syncErrorHook, syncAfterResponse } } = state;
162
148
  const hasStaticAfterResponse = !!hook?.afterResponse?.length;
163
- const hasDynamicAfterResponse = !!inference.afterResponse;
149
+ const hasDeriveDispose = !!hook?.["~deriveEntries"]?.length;
150
+ const hasDynamicAfterResponse = !!inference.afterResponse || hasDeriveDispose;
164
151
  const seenKeys = new Set(["rt", "fre"]);
165
152
  const paramValues = [errorRoot, require_handler_utils.finalizeRouteError];
166
153
  const aliasKeys = [];
@@ -182,7 +169,8 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
182
169
  const abortOn = hasLifecycleHook && root["~config"]?.abortSignal !== false;
183
170
  const abortPeek = "c['~sig']?.aborted";
184
171
  const arm = abortOn ? "_as??=(c['~sig']??=c.request.signal)" : "";
185
- const abortCheck = () => abortOn ? `if(${abortPeek})return emp.clone()\n` : "";
172
+ let abortSchedule = "";
173
+ const abortCheck = () => abortOn ? abortSchedule ? `if(${abortPeek}){${abortSchedule}return emp.clone()}\n` : `if(${abortPeek})return emp.clone()\n` : "";
186
174
  const abortChainGuard = () => abortOn ? abortPeek : void 0;
187
175
  const abortCatch = abortOn ? `if((${arm}).aborted)return emp.clone()\n` : "";
188
176
  const phaseOn = (phase) => hasTrace && (tracePhases === null || tracePhases.has(phase));
@@ -224,7 +212,7 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
224
212
  link(require_compile_handler_utils.armEntryAbort, "ea");
225
213
  code += `if(ea(c))return emp.clone()\n`;
226
214
  }
227
- if ((hasAfterResponse || hasTrace) && !syncAfterResponse) code += "let _stl\n";
215
+ if ((hasAfterResponse || hasTrace || hasDeriveDispose) && !syncAfterResponse) code += "let _stl\n";
228
216
  if (asyncCookieSign) code += "let _sg\n";
229
217
  if (hasTrace) {
230
218
  const traceProvider = require_generation.resolvedTraceOf(root) ?? require_generation.resolvedTraceOf(errorRoot);
@@ -371,18 +359,22 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
371
359
  return s;
372
360
  })() : "";
373
361
  const traceNeedsSchedule = traceHandleOn || phaseOn("afterResponse");
374
- const scheduleAfterResponse = hasAfterResponse || traceNeedsSchedule ? "c._arf=true\nqueueMicrotask(async()=>{if(_stl){try{for await(const v of _stl){}}catch{}}\n" + drainTraceStream + resolveHandlePostDrain + beginTrace("afterResponse", hook?.afterResponse?.length ?? 0) + (hasStaticAfterResponse ? require_compile_handler_utils.mapAfterResponse(hook.afterResponse, [buildReport("afterResponse")]) : "") + (hasDynamicAfterResponse ? "let _q=c['~afterResponse']\nif(_q){let _l=_q.length\nfor(let _i=0;_i<_l;_i++){try{await _q[_i](c)}catch(_e){console.error(_e)}}\n" + (!require_universal_is_production.isProduction() ? `if(_q.length!==_l)console.warn('[elysia] defer() called from inside the afterResponse drain is ignored')\n` : "") + `}\n` : "") + endTrace("afterResponse") + `})\n` : "";
362
+ if (hasDeriveDispose) link(require_handler_utils.drainDisposables, "dds");
363
+ const deriveDisposeOnly = hasDeriveDispose && !hasAfterResponse && !hasTrace;
364
+ const disposeGuard = deriveDisposeOnly ? "c['~dispose']&&" : "";
365
+ const scheduleAfterResponse = hasAfterResponse || traceNeedsSchedule || hasDeriveDispose ? (deriveDisposeOnly ? `if(c['~dispose']){\n` : "") + "c._arf=true\nqueueMicrotask(async()=>{if(_stl){try{for await(const v of _stl){}}catch{}}\n" + drainTraceStream + resolveHandlePostDrain + beginTrace("afterResponse", hook?.afterResponse?.length ?? 0) + (hasStaticAfterResponse ? require_compile_handler_utils.mapAfterResponse(hook.afterResponse, [buildReport("afterResponse")]) : "") + (hasDynamicAfterResponse ? "let _q=c['~afterResponse']\nif(_q){let _l=_q.length\nfor(let _i=0;_i<_l;_i++){try{await _q[_i](c)}catch(_e){console.error(_e)}}\n" + (!require_universal_is_production.isProduction() ? `if(_q.length!==_l)console.warn('[elysia] defer() called from inside the afterResponse drain is ignored')\n` : "") + `}\n` : "") + (hasDeriveDispose ? `await dds(c)\n` : "") + endTrace("afterResponse") + `})\n` + (deriveDisposeOnly ? `}\n` : "") : "";
375
366
  const dedupSchedule = !!scheduleAfterResponse && !syncAfterResponse && !syncErrorHook;
376
367
  const scheduleDecl = dedupSchedule ? `function _sc(){\n${scheduleAfterResponse}}\n` : "";
377
368
  const schedule = dedupSchedule ? `_sc()\n` : scheduleAfterResponse;
378
369
  const syncScheduleDecl = syncAfterResponse && scheduleAfterResponse ? `function _scf(c,_stl){\n${scheduleAfterResponse}}\n` : "";
379
370
  const catchSchedule = dedupSchedule ? `_sc()\n` : syncScheduleDecl ? `_scf(c)\n` : "";
380
- const freThenSchedule = (arg) => catchSchedule ? `if(c._arf)return fre(rt,c,${arg})\nc._arf=true\nconst _fr=fre(rt,c,${arg})\nreturn typeof _fr?.then==='function'?_fr.then((_v)=>{${catchSchedule}return _v\n}):(${catchSchedule.trim()},_fr)\n` : `return fre(rt,c,${arg})\n`;
371
+ abortSchedule = hasDeriveDispose ? syncAfterResponse ? catchSchedule : schedule : "";
372
+ const freThenSchedule = (arg) => catchSchedule ? `if(c._arf)return fre(rt,c,${arg})\n${deriveDisposeOnly ? `if(c['~dispose'])` : ""}c._arf=true\nconst _fr=fre(rt,c,${arg})\nreturn typeof _fr?.then==='function'?_fr.then((_v)=>{${catchSchedule}return _v\n}):(${catchSchedule.trim()},_fr)\n` : `return fre(rt,c,${arg})\n`;
381
373
  const signPrefix = syncCookieSign ? `scv(c.set.cookie,cc)\n` : asyncCookieSign ? `_sg=scv(c.set.cookie,cc)\nif(_sg){${arm ? `${arm}\n` : ""}await _sg}\n` : "";
382
374
  if (syncCookieSign || asyncCookieSign) link(require_cookie_utils.signCookieValues, "scv");
383
375
  let factoryHelpers = "";
384
376
  if (hasBeforeHandle || hasAfterHandle || hasMapResponse || hasAfterResponse || hasResponseValidator || hasCookieSign || hasTrace) {
385
- code += `let _r,tmp\n`;
377
+ code += `let _r,tmp${hasDeriveDispose ? ",_v" : ""}\n`;
386
378
  if (hasBeforeHandle || hasTrace) {
387
379
  const bfLen = (beforeHandlePrefix?.length ?? 0) + (hook?.beforeHandle?.length ?? 0);
388
380
  code += beginTrace("beforeHandle", bfLen);
@@ -410,8 +402,8 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
410
402
  code += endTrace("beforeHandle");
411
403
  if (hasBeforeHandle) code += abortCheck();
412
404
  }
413
- if (hasAfterResponse || traceHandleOn) link(require_adapter_utils.tee, "tee");
414
- const teeBlock = (hasAfterResponse || traceHandleOn) && !syncAfterResponse ? "if(_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\n_r=_s[0]\n" + (traceHandleOn ? `_trs=_s[1]\n` : `_stl=_s[1]\n`) + `}\n` : "";
405
+ if (hasAfterResponse || traceHandleOn || hasDeriveDispose) link(require_adapter_utils.tee, "tee");
406
+ const teeBlock = (hasAfterResponse || traceHandleOn || hasDeriveDispose) && !syncAfterResponse ? `if(${disposeGuard}_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\n_r=_s[0]\n` + (traceHandleOn ? `_trs=_s[1]\n` : `_stl=_s[1]\n`) + `}\n` : "";
415
407
  if (traceHandleOn) {
416
408
  const handleName = handler?.name && typeof handler.name === "string" ? handler.name : "anonymous";
417
409
  code += beginTrace("handle", 1, handleName);
@@ -503,11 +495,11 @@ let _r${hasMapResponse ? ",tmp" : ""}\n` + require_compile_handler_utils.mapErro
503
495
  map,
504
496
  link,
505
497
  responseMap,
506
- (hasMapResponse ? `c.responseValue=_r\n` + require_compile_handler_utils.mapMapResponse(hook.mapResponse, isAsync, void 0, abortChainGuard(), arm) : "") + endTrace("error") + abortCatch + schedule,
498
+ (hasMapResponse ? `c.responseValue=_r\n` + require_compile_handler_utils.mapMapResponse(hook.mapResponse, isAsync, void 0, abortChainGuard(), arm) : "") + endTrace("error") + (hasDeriveDispose ? schedule + abortCatch : abortCatch + schedule),
507
499
  signPrefix,
508
500
  isAsync,
509
501
  arm
510
- ], abortChainGuard()) + endTrace("error") + abortCatch + schedule + `return _efb(e,c)\n`;
502
+ ], abortChainGuard()) + endTrace("error") + (hasDeriveDispose ? schedule + abortCatch : abortCatch + schedule) + `return _efb(e,c)\n`;
511
503
  } else body += endTrace("error") + freThenSchedule("e");
512
504
  if (syncErrorHook) {
513
505
  factoryHelpers += `function _ce(e,c){${abortOn ? "let _as\n" : ""}try{\n${body}}catch(_ee){return fre(rt,c,_ee)}}\n`;
@@ -528,7 +520,25 @@ let _r${hasMapResponse ? ",tmp" : ""}\n` + require_compile_handler_utils.mapErro
528
520
  const isGeneratorHandler = isHandleFunction && handler.constructor.name.endsWith("GeneratorFunction");
529
521
  if (!hasTrace && isHandleFunction && !isGeneratorHandler && !inlineUnsafe) {
530
522
  if (alias === "rc" || !isAsync && !syncErrorHook && alias === "rc,fe") return createInlineHandler(responseCompact, handler);
531
- else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) return responseMode === "set-with-default-headers" && inference.set ? createInlineHandlerWithDefaultHeaders(responseMap, handler) : createInlineHandlerWithSet(responseMap, handler);
523
+ else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) {
524
+ const rmap = responseMap;
525
+ const h = handler;
526
+ let inlineHandler;
527
+ if (responseMode === "set-with-default-headers" && inference.set) inlineHandler = ((c) => {
528
+ require_adapter_utils.materializeSetHeaders(c.set);
529
+ const r = h(c);
530
+ if (r instanceof Error) throw r;
531
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(require_handler_utils.forwardError(v), c.set, c.request, true));
532
+ return rmap(r, c.set, c.request, true);
533
+ });
534
+ else inlineHandler = ((c) => {
535
+ const r = h(c);
536
+ if (r instanceof Error) throw r;
537
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(require_handler_utils.forwardError(v), c.set, c.request, true));
538
+ return rmap(r, c.set, c.request, true);
539
+ });
540
+ return inlineHandler;
541
+ }
532
542
  }
533
543
  require_compile_jit_probe.JITProbe.record("handler:new-function");
534
544
  return new Function("h", fullAlias, `return ${code}`)(handler, ...paramValues);
@@ -9,7 +9,7 @@ import { parseQueryFromURL } from "../../parse-query.mjs";
9
9
  import { Capture } from "../aot.mjs";
10
10
  import { resolvedTraceOf, traceCapabilityRequired } from "../../generation.mjs";
11
11
  import { buildCookieJar, parseCookieRaw, parseCookieRawDeferred, parseCookieRawLazy, parseCookieRawSigned, parseCookieRawSync, signCookieValues } from "../../cookie/utils.mjs";
12
- import { emptyResponse, finalizeRouteError, forwardError } from "../../handler/utils.mjs";
12
+ import { drainDisposables, emptyResponse, finalizeRouteError, forwardError } from "../../handler/utils.mjs";
13
13
  import { fallbackResponse } from "../../handler/error.mjs";
14
14
  import { armEntryAbort, awaitGuard, cloneResponse, cloneStaticValue, getQueryParseChannels, hasRequestBody, mapAfterHandle, mapAfterResponse, mapBeforeHandle, mapError, mapMapResponse, mapTransform, runBeforeHandlePrefix, runBeforeHandlePrefixAsync } from "./utils.mjs";
15
15
  import { JITProbe } from "../jit-probe.mjs";
@@ -64,7 +64,7 @@ function parse(adapter, parsers, bodyVali, hasHeaders, link, report, arm) {
64
64
  break;
65
65
  }
66
66
  }
67
- const bodyKind = hasFn ? void 0 : bodyMediaKind(bodyVali);
67
+ const bodyKind = hasFn ? void 0 : schemaMediaKind(bodyVali?.schema);
68
68
  let code = `let ct=((${hasHeaders ? "c.headers['content-type']" : "c.request.headers.get('content-type')"})||'')\nlet cti=ct.indexOf(";")
69
69
  if(cti!==-1)ct=ct.slice(0,cti)
70
70
  ` + (hasFn ? "c.contentType=ct\n" : "");
@@ -110,7 +110,6 @@ if(cti!==-1)ct=ct.slice(0,cti)
110
110
  }
111
111
  return hasFn ? "let hasBody=false,_bp\n" + code : code;
112
112
  }
113
- const bodyMediaKind = (bodyVali) => schemaMediaKind(bodyVali?.schema);
114
113
  function schemaMediaKind(schema) {
115
114
  if (!schema || typeof schema !== "object" || "~standard" in schema) return;
116
115
  const elyType = schema["~elyTyp"];
@@ -143,23 +142,11 @@ const createInlineHandler = (map, h) => ((c) => {
143
142
  if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(forwardError(v), c.request, true));
144
143
  return map(r, c.request, true);
145
144
  });
146
- const createInlineHandlerWithSet = (map, h) => ((c) => {
147
- const r = h(c);
148
- if (r instanceof Error) throw r;
149
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(forwardError(v), c.set, c.request, true));
150
- return map(r, c.set, c.request, true);
151
- });
152
- const createInlineHandlerWithDefaultHeaders = (map, h) => ((c) => {
153
- materializeSetHeaders(c.set);
154
- const r = h(c);
155
- if (r instanceof Error) throw r;
156
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(forwardError(v), c.set, c.request, true));
157
- return map(r, c.set, c.request, true);
158
- });
159
145
  function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapter, isHandleFunction, isStaticResponse, isPromiseHandler, state }) {
160
146
  const { vali, inference, cookieConfig, beforeHandlePrefix, traceHandlers, tracePhases, hasAnyPhase, traceHandleOn, descriptor: { async: isAsync, responseMode, hasBody, bodyValiIsAsync, headersValiIsAsync, paramsValiIsAsync, queryValiIsAsync, cookieValiIsAsync: cookieValidIsAsync, responseValiAsync, hasCookieSign, syncCookieSign, asyncCookieSign, lazyCookieVerify, hasErrorHook, hasAfterResponse, hasBeforeHandle, hasAfterHandle, hasMapResponse, hasResponseValidator, hasTrace, traceCount, hasLifecycleHook, syncErrorHook, syncAfterResponse } } = state;
161
147
  const hasStaticAfterResponse = !!hook?.afterResponse?.length;
162
- const hasDynamicAfterResponse = !!inference.afterResponse;
148
+ const hasDeriveDispose = !!hook?.["~deriveEntries"]?.length;
149
+ const hasDynamicAfterResponse = !!inference.afterResponse || hasDeriveDispose;
163
150
  const seenKeys = new Set(["rt", "fre"]);
164
151
  const paramValues = [errorRoot, finalizeRouteError];
165
152
  const aliasKeys = [];
@@ -181,7 +168,8 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
181
168
  const abortOn = hasLifecycleHook && root["~config"]?.abortSignal !== false;
182
169
  const abortPeek = "c['~sig']?.aborted";
183
170
  const arm = abortOn ? "_as??=(c['~sig']??=c.request.signal)" : "";
184
- const abortCheck = () => abortOn ? `if(${abortPeek})return emp.clone()\n` : "";
171
+ let abortSchedule = "";
172
+ const abortCheck = () => abortOn ? abortSchedule ? `if(${abortPeek}){${abortSchedule}return emp.clone()}\n` : `if(${abortPeek})return emp.clone()\n` : "";
185
173
  const abortChainGuard = () => abortOn ? abortPeek : void 0;
186
174
  const abortCatch = abortOn ? `if((${arm}).aborted)return emp.clone()\n` : "";
187
175
  const phaseOn = (phase) => hasTrace && (tracePhases === null || tracePhases.has(phase));
@@ -223,7 +211,7 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
223
211
  link(armEntryAbort, "ea");
224
212
  code += `if(ea(c))return emp.clone()\n`;
225
213
  }
226
- if ((hasAfterResponse || hasTrace) && !syncAfterResponse) code += "let _stl\n";
214
+ if ((hasAfterResponse || hasTrace || hasDeriveDispose) && !syncAfterResponse) code += "let _stl\n";
227
215
  if (asyncCookieSign) code += "let _sg\n";
228
216
  if (hasTrace) {
229
217
  const traceProvider = resolvedTraceOf(root) ?? resolvedTraceOf(errorRoot);
@@ -370,18 +358,22 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
370
358
  return s;
371
359
  })() : "";
372
360
  const traceNeedsSchedule = traceHandleOn || phaseOn("afterResponse");
373
- const scheduleAfterResponse = hasAfterResponse || traceNeedsSchedule ? "c._arf=true\nqueueMicrotask(async()=>{if(_stl){try{for await(const v of _stl){}}catch{}}\n" + drainTraceStream + resolveHandlePostDrain + beginTrace("afterResponse", hook?.afterResponse?.length ?? 0) + (hasStaticAfterResponse ? mapAfterResponse(hook.afterResponse, [buildReport("afterResponse")]) : "") + (hasDynamicAfterResponse ? "let _q=c['~afterResponse']\nif(_q){let _l=_q.length\nfor(let _i=0;_i<_l;_i++){try{await _q[_i](c)}catch(_e){console.error(_e)}}\n" + (!isProduction() ? `if(_q.length!==_l)console.warn('[elysia] defer() called from inside the afterResponse drain is ignored')\n` : "") + `}\n` : "") + endTrace("afterResponse") + `})\n` : "";
361
+ if (hasDeriveDispose) link(drainDisposables, "dds");
362
+ const deriveDisposeOnly = hasDeriveDispose && !hasAfterResponse && !hasTrace;
363
+ const disposeGuard = deriveDisposeOnly ? "c['~dispose']&&" : "";
364
+ const scheduleAfterResponse = hasAfterResponse || traceNeedsSchedule || hasDeriveDispose ? (deriveDisposeOnly ? `if(c['~dispose']){\n` : "") + "c._arf=true\nqueueMicrotask(async()=>{if(_stl){try{for await(const v of _stl){}}catch{}}\n" + drainTraceStream + resolveHandlePostDrain + beginTrace("afterResponse", hook?.afterResponse?.length ?? 0) + (hasStaticAfterResponse ? mapAfterResponse(hook.afterResponse, [buildReport("afterResponse")]) : "") + (hasDynamicAfterResponse ? "let _q=c['~afterResponse']\nif(_q){let _l=_q.length\nfor(let _i=0;_i<_l;_i++){try{await _q[_i](c)}catch(_e){console.error(_e)}}\n" + (!isProduction() ? `if(_q.length!==_l)console.warn('[elysia] defer() called from inside the afterResponse drain is ignored')\n` : "") + `}\n` : "") + (hasDeriveDispose ? `await dds(c)\n` : "") + endTrace("afterResponse") + `})\n` + (deriveDisposeOnly ? `}\n` : "") : "";
374
365
  const dedupSchedule = !!scheduleAfterResponse && !syncAfterResponse && !syncErrorHook;
375
366
  const scheduleDecl = dedupSchedule ? `function _sc(){\n${scheduleAfterResponse}}\n` : "";
376
367
  const schedule = dedupSchedule ? `_sc()\n` : scheduleAfterResponse;
377
368
  const syncScheduleDecl = syncAfterResponse && scheduleAfterResponse ? `function _scf(c,_stl){\n${scheduleAfterResponse}}\n` : "";
378
369
  const catchSchedule = dedupSchedule ? `_sc()\n` : syncScheduleDecl ? `_scf(c)\n` : "";
379
- const freThenSchedule = (arg) => catchSchedule ? `if(c._arf)return fre(rt,c,${arg})\nc._arf=true\nconst _fr=fre(rt,c,${arg})\nreturn typeof _fr?.then==='function'?_fr.then((_v)=>{${catchSchedule}return _v\n}):(${catchSchedule.trim()},_fr)\n` : `return fre(rt,c,${arg})\n`;
370
+ abortSchedule = hasDeriveDispose ? syncAfterResponse ? catchSchedule : schedule : "";
371
+ const freThenSchedule = (arg) => catchSchedule ? `if(c._arf)return fre(rt,c,${arg})\n${deriveDisposeOnly ? `if(c['~dispose'])` : ""}c._arf=true\nconst _fr=fre(rt,c,${arg})\nreturn typeof _fr?.then==='function'?_fr.then((_v)=>{${catchSchedule}return _v\n}):(${catchSchedule.trim()},_fr)\n` : `return fre(rt,c,${arg})\n`;
380
372
  const signPrefix = syncCookieSign ? `scv(c.set.cookie,cc)\n` : asyncCookieSign ? `_sg=scv(c.set.cookie,cc)\nif(_sg){${arm ? `${arm}\n` : ""}await _sg}\n` : "";
381
373
  if (syncCookieSign || asyncCookieSign) link(signCookieValues, "scv");
382
374
  let factoryHelpers = "";
383
375
  if (hasBeforeHandle || hasAfterHandle || hasMapResponse || hasAfterResponse || hasResponseValidator || hasCookieSign || hasTrace) {
384
- code += `let _r,tmp\n`;
376
+ code += `let _r,tmp${hasDeriveDispose ? ",_v" : ""}\n`;
385
377
  if (hasBeforeHandle || hasTrace) {
386
378
  const bfLen = (beforeHandlePrefix?.length ?? 0) + (hook?.beforeHandle?.length ?? 0);
387
379
  code += beginTrace("beforeHandle", bfLen);
@@ -409,8 +401,8 @@ function compileHandlerJit({ method, path, handler, root, errorRoot, hook, adapt
409
401
  code += endTrace("beforeHandle");
410
402
  if (hasBeforeHandle) code += abortCheck();
411
403
  }
412
- if (hasAfterResponse || traceHandleOn) link(tee, "tee");
413
- const teeBlock = (hasAfterResponse || traceHandleOn) && !syncAfterResponse ? "if(_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\n_r=_s[0]\n" + (traceHandleOn ? `_trs=_s[1]\n` : `_stl=_s[1]\n`) + `}\n` : "";
404
+ if (hasAfterResponse || traceHandleOn || hasDeriveDispose) link(tee, "tee");
405
+ const teeBlock = (hasAfterResponse || traceHandleOn || hasDeriveDispose) && !syncAfterResponse ? `if(${disposeGuard}_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\n_r=_s[0]\n` + (traceHandleOn ? `_trs=_s[1]\n` : `_stl=_s[1]\n`) + `}\n` : "";
414
406
  if (traceHandleOn) {
415
407
  const handleName = handler?.name && typeof handler.name === "string" ? handler.name : "anonymous";
416
408
  code += beginTrace("handle", 1, handleName);
@@ -502,11 +494,11 @@ let _r${hasMapResponse ? ",tmp" : ""}\n` + mapError(hook.error, [
502
494
  map,
503
495
  link,
504
496
  responseMap,
505
- (hasMapResponse ? `c.responseValue=_r\n` + mapMapResponse(hook.mapResponse, isAsync, void 0, abortChainGuard(), arm) : "") + endTrace("error") + abortCatch + schedule,
497
+ (hasMapResponse ? `c.responseValue=_r\n` + mapMapResponse(hook.mapResponse, isAsync, void 0, abortChainGuard(), arm) : "") + endTrace("error") + (hasDeriveDispose ? schedule + abortCatch : abortCatch + schedule),
506
498
  signPrefix,
507
499
  isAsync,
508
500
  arm
509
- ], abortChainGuard()) + endTrace("error") + abortCatch + schedule + `return _efb(e,c)\n`;
501
+ ], abortChainGuard()) + endTrace("error") + (hasDeriveDispose ? schedule + abortCatch : abortCatch + schedule) + `return _efb(e,c)\n`;
510
502
  } else body += endTrace("error") + freThenSchedule("e");
511
503
  if (syncErrorHook) {
512
504
  factoryHelpers += `function _ce(e,c){${abortOn ? "let _as\n" : ""}try{\n${body}}catch(_ee){return fre(rt,c,_ee)}}\n`;
@@ -527,7 +519,25 @@ let _r${hasMapResponse ? ",tmp" : ""}\n` + mapError(hook.error, [
527
519
  const isGeneratorHandler = isHandleFunction && handler.constructor.name.endsWith("GeneratorFunction");
528
520
  if (!hasTrace && isHandleFunction && !isGeneratorHandler && !inlineUnsafe) {
529
521
  if (alias === "rc" || !isAsync && !syncErrorHook && alias === "rc,fe") return createInlineHandler(responseCompact, handler);
530
- else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) return responseMode === "set-with-default-headers" && inference.set ? createInlineHandlerWithDefaultHeaders(responseMap, handler) : createInlineHandlerWithSet(responseMap, handler);
522
+ else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) {
523
+ const rmap = responseMap;
524
+ const h = handler;
525
+ let inlineHandler;
526
+ if (responseMode === "set-with-default-headers" && inference.set) inlineHandler = ((c) => {
527
+ materializeSetHeaders(c.set);
528
+ const r = h(c);
529
+ if (r instanceof Error) throw r;
530
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(forwardError(v), c.set, c.request, true));
531
+ return rmap(r, c.set, c.request, true);
532
+ });
533
+ else inlineHandler = ((c) => {
534
+ const r = h(c);
535
+ if (r instanceof Error) throw r;
536
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(forwardError(v), c.set, c.request, true));
537
+ return rmap(r, c.set, c.request, true);
538
+ });
539
+ return inlineHandler;
540
+ }
531
541
  }
532
542
  JITProbe.record("handler:new-function");
533
543
  return new Function("h", fullAlias, `return ${code}`)(handler, ...paramValues);
@@ -29,6 +29,8 @@ const handlerParams = () => _handlerParams ??= {
29
29
  pe: () => require_error.ParseError,
30
30
  es: () => require_error.ElysiaStatus,
31
31
  rdc: () => require_compile_handler_utils.replaceDeriveContext,
32
+ dsp: () => require_handler_utils.registerDeriveDisposable,
33
+ dds: () => require_handler_utils.drainDisposables,
32
34
  emp: () => require_handler_utils.emptyResponse,
33
35
  ea: () => require_compile_handler_utils.armEntryAbort,
34
36
  verr: () => require_error.ValidationError,
@@ -3,7 +3,7 @@ import { ElysiaStatus, ParseError, ValidationError } from "../../error.mjs";
3
3
  import { materializeSetHeaders, normalizeContentType, tee } from "../../adapter/utils.mjs";
4
4
  import { parseQueryFromURL } from "../../parse-query.mjs";
5
5
  import { buildCookieJar, parseCookieRaw, parseCookieRawDeferred, parseCookieRawLazy, parseCookieRawSigned, parseCookieRawSync, signCookieValues } from "../../cookie/utils.mjs";
6
- import { emptyResponse, finalizeRouteError, forwardError } from "../../handler/utils.mjs";
6
+ import { drainDisposables, emptyResponse, finalizeRouteError, forwardError, registerDeriveDisposable } from "../../handler/utils.mjs";
7
7
  import { adoptErrorType, fallbackResponse } from "../../handler/error.mjs";
8
8
  import { armEntryAbort, cloneResponse, getQueryParseChannels, hasRequestBody, replaceDeriveContext, runBeforeHandlePrefix } from "./utils.mjs";
9
9
  import { staticCloneResolver } from "./static-clone-resolver.mjs";
@@ -28,6 +28,8 @@ const handlerParams = () => _handlerParams ??= {
28
28
  pe: () => ParseError,
29
29
  es: () => ElysiaStatus,
30
30
  rdc: () => replaceDeriveContext,
31
+ dsp: () => registerDeriveDisposable,
32
+ dds: () => drainDisposables,
31
33
  emp: () => emptyResponse,
32
34
  ea: () => armEntryAbort,
33
35
  verr: () => ValidationError,
@@ -1,7 +1,7 @@
1
1
  import { CompactBeforeHandlePrefix, DeriveEntry } from "../../utils.js";
2
2
  import { AfterResponseHandler, AppHook, ErrorHandler, MaybeArray, TransformHandler } from "../../types.js";
3
3
  import { Context } from "../../context.js";
4
- import { emptyResponse } from "../../handler/utils.js";
4
+ import { drainDisposables, emptyResponse, registerDeriveDisposable } from "../../handler/utils.js";
5
5
 
6
6
  //#region src/compile/handler/utils.d.ts
7
7
  type Link = (v: unknown, key: string) => void;
@@ -43,4 +43,4 @@ interface QueryWalkState {
43
43
  declare function getQueryParseChannels(querySchema: any): QueryWalkState | undefined;
44
44
  declare function awaitGuard(fn: Function, isAsync: boolean, target: string, arm?: string): string;
45
45
  //#endregion
46
- export { Link, TraceReporter, armEntryAbort, awaitGuard, cloneResponse, cloneStaticValue, deriveModes, emptyResponse, getQueryParseChannels, hasRequestBody, mapAfterHandle, mapAfterResponse, mapBeforeHandle, mapError, mapMapResponse, mapTransform, replaceDeriveContext, runBeforeHandlePrefix, runBeforeHandlePrefixAsync };
46
+ export { Link, TraceReporter, armEntryAbort, awaitGuard, cloneResponse, cloneStaticValue, deriveModes, drainDisposables, emptyResponse, getQueryParseChannels, hasRequestBody, mapAfterHandle, mapAfterResponse, mapBeforeHandle, mapError, mapMapResponse, mapTransform, registerDeriveDisposable, replaceDeriveContext, runBeforeHandlePrefix, runBeforeHandlePrefixAsync };