elysia 2.0.0-beta.20 → 2.0.0-beta.21

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 (50) hide show
  1. package/dist/compile/aot.d.ts +8 -8
  2. package/dist/compile/aot.js +16 -14
  3. package/dist/compile/aot.mjs +14 -14
  4. package/dist/compile/handler/descriptor.js +2 -3
  5. package/dist/compile/handler/descriptor.mjs +2 -3
  6. package/dist/compile/handler/index.d.ts +2 -1
  7. package/dist/compile/handler/index.js +144 -24
  8. package/dist/compile/handler/index.mjs +146 -27
  9. package/dist/compile/handler/jit.d.ts +2 -0
  10. package/dist/compile/handler/jit.js +3 -2
  11. package/dist/compile/handler/jit.mjs +3 -2
  12. package/dist/compile/handler/reconstruct.js +3 -2
  13. package/dist/compile/handler/reconstruct.mjs +3 -2
  14. package/dist/cookie/config.d.ts +6 -2
  15. package/dist/cookie/config.js +68 -8
  16. package/dist/cookie/config.mjs +69 -10
  17. package/dist/cookie/utils.js +3 -3
  18. package/dist/cookie/utils.mjs +4 -4
  19. package/dist/package.js +1 -1
  20. package/dist/package.mjs +1 -1
  21. package/dist/plugin/aot/core.d.ts +5 -0
  22. package/dist/plugin/aot/core.js +37 -1
  23. package/dist/plugin/aot/core.mjs +37 -1
  24. package/dist/plugin/aot/source.js +24 -9
  25. package/dist/plugin/aot/source.mjs +24 -9
  26. package/dist/schema-snapshot.js +4 -3
  27. package/dist/schema-snapshot.mjs +4 -3
  28. package/dist/type/coerce.d.ts +1 -1
  29. package/dist/type/constants.d.ts +1 -1
  30. package/dist/type/elysia/keep-config.d.ts +14 -0
  31. package/dist/type/elysia/keep-config.js +62 -0
  32. package/dist/type/elysia/keep-config.mjs +53 -0
  33. package/dist/type/exports.d.ts +3 -2
  34. package/dist/type/exports.js +10 -0
  35. package/dist/type/exports.mjs +2 -1
  36. package/dist/type/index.js +10 -0
  37. package/dist/type/index.mjs +10 -0
  38. package/dist/type/typebox-type-live.d.ts +2 -2
  39. package/dist/type/typebox-type-live.js +8 -0
  40. package/dist/type/typebox-type-live.mjs +2 -2
  41. package/dist/type/typebox-type.d.ts +10 -2
  42. package/dist/type/typebox-type.js +64 -0
  43. package/dist/type/typebox-type.mjs +17 -1
  44. package/dist/types.d.ts +3 -2
  45. package/dist/utils.d.ts +3 -1
  46. package/dist/utils.js +23 -0
  47. package/dist/utils.mjs +22 -1
  48. package/dist/ws/route.js +33 -5
  49. package/dist/ws/route.mjs +35 -7
  50. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { CoerceNode } from "../type/coerce-plan.js";
2
2
  //#region src/compile/aot.d.ts
3
- declare const AOT_MANIFEST_FORMAT = 5;
3
+ declare const AOT_MANIFEST_FORMAT = 6;
4
4
  interface AotFingerprint {
5
5
  abi: string;
6
6
  }
@@ -79,8 +79,9 @@ interface ValidatorManifest {
79
79
  };
80
80
  }
81
81
  interface FrozenHandler {
82
- a: string[];
83
- f: (...deps: unknown[]) => unknown;
82
+ a?: string[];
83
+ f?: (...deps: unknown[]) => unknown;
84
+ k?: number;
84
85
  }
85
86
  interface HandlerManifest {
86
87
  [method: string]: {
@@ -125,6 +126,8 @@ interface ReconstructImpl {
125
126
  reconstructInnerCodecs(ic: NonNullable<FrozenValidator['ic']>, schema: any): void;
126
127
  }
127
128
  declare function reconstruct(): ReconstructImpl;
129
+ declare const aotDrift: (method: string, path: string) => string;
130
+ declare function warnAotDrift(method: string, path: string): void;
128
131
  declare abstract class Compiled {
129
132
  static register(manifest: CompiledProgramRegistration): void;
130
133
  static claim(id: ProgramId, fingerprint: AotFingerprint): boolean;
@@ -135,10 +138,6 @@ declare abstract class Compiled {
135
138
  static getValidator(method: string, path: string, slot: ValidatorSlot, id?: ProgramId): FrozenValidator | undefined;
136
139
  static hasValidator(method: string, path: string, slot: ValidatorSlot, id?: ProgramId): boolean;
137
140
  static getPlanRebuilder(id?: ProgramId): ((original: unknown, plan: CoerceNode) => any) | undefined;
138
- /**
139
- * Drop a fully consumed program registration after an eager production
140
- * build publishes. Safe only when every route compiled before publish
141
- */
142
141
  static release(id: ProgramId): void;
143
142
  /** @internal test isolation */
144
143
  static clear(): void;
@@ -221,6 +220,7 @@ interface CapturedHandler {
221
220
  path: string;
222
221
  alias: string;
223
222
  code: string;
223
+ k: number | undefined;
224
224
  }
225
225
  declare function captureHandler(v: CapturedHandler): void;
226
226
  declare function captureSet(loc: {
@@ -282,4 +282,4 @@ interface CaptureImpl {
282
282
  declare let captureImpl: CaptureImpl | undefined;
283
283
  declare function setCaptureImpl(impl: CaptureImpl | undefined): void;
284
284
  //#endregion
285
- export { AOT_MANIFEST_FORMAT, AotFingerprint, Capture, CaptureImpl, CapturedHandler, CapturedMirror, CapturedValidator, CheckBuildResult, Compiled, CompiledProgramRegistration, CompiledSnapshot, CompilerSession, CompilerState, EMPTY_EXTERNALS, FrozenBothFactory, FrozenCheckFactory, FrozenHandler, FrozenMirror, FrozenMirrorFactory, FrozenValidator, HandlerManifest, ProgramId, ReconstructImpl, StringCodecNode, ValidatorManifest, ValidatorSlot, aotActivationError, beginCompilerSession, captureImpl, createAotFingerprint, endCompilerSession, getCompilerSession, reconstruct, setCaptureImpl };
285
+ export { AOT_MANIFEST_FORMAT, AotFingerprint, Capture, CaptureImpl, CapturedHandler, CapturedMirror, CapturedValidator, CheckBuildResult, Compiled, CompiledProgramRegistration, CompiledSnapshot, CompilerSession, CompilerState, EMPTY_EXTERNALS, FrozenBothFactory, FrozenCheckFactory, FrozenHandler, FrozenMirror, FrozenMirrorFactory, FrozenValidator, HandlerManifest, ProgramId, ReconstructImpl, StringCodecNode, ValidatorManifest, ValidatorSlot, aotActivationError, aotDrift, beginCompilerSession, captureImpl, createAotFingerprint, endCompilerSession, getCompilerSession, reconstruct, setCaptureImpl, warnAotDrift };
@@ -4,8 +4,8 @@ const require_universal_env = require('../universal/env.js');
4
4
  const require_package = require('../package.js');
5
5
 
6
6
  //#region src/compile/aot.ts
7
- const AOT_MANIFEST_FORMAT = 5;
8
- const AOT_ABI = `${require_package.version}:${5}`;
7
+ const AOT_MANIFEST_FORMAT = 6;
8
+ const AOT_ABI = `${require_package.version}:${6}`;
9
9
  const sharedAotFingerprint = Object.freeze({ abi: AOT_ABI });
10
10
  const createAotFingerprint = () => sharedAotFingerprint;
11
11
  let activeSession;
@@ -37,12 +37,16 @@ function reconstruct() {
37
37
  if (reconstructImpl === void 0) throw new Error("Elysia AOT reconstruct module is not activated");
38
38
  return reconstructImpl;
39
39
  }
40
+ let drifted;
41
+ const aotDrift = (method, path) => `[elysia-aot] ${method} ${path} differs from the AOT build`;
42
+ function warnAotDrift(method, path) {
43
+ const key = method + " " + path;
44
+ if (drifted?.has(key)) return;
45
+ drifted ??= /* @__PURE__ */ new Set();
46
+ drifted.add(key);
47
+ console.warn(aotDrift(method, path) + ", compiled at runtime");
48
+ }
40
49
  let registered;
41
- /**
42
- * App that consumed this process's manifest, held weakly: it only has to
43
- * recognise a re-claim by the *same* app, and `assertUncontested` always
44
- * compares against a live id, so a cleared ref answers as a strong one would
45
- */
46
50
  let claimed;
47
51
  let programs = /* @__PURE__ */ new WeakMap();
48
52
  const programFor = (id) => id ? programs.get(id) : void 0;
@@ -54,8 +58,7 @@ var Compiled = class {
54
58
  static claim(id, fingerprint) {
55
59
  if (!registered || claimed) return false;
56
60
  const manifest = registered;
57
- const expected = manifest.fingerprint;
58
- if (expected.abi !== fingerprint.abi) throw new Error(`[elysia-aot] Registered manifest fingerprint mismatch: abi (manifest ${expected.abi}, app ${fingerprint.abi}).`);
61
+ if (manifest.fingerprint.abi !== fingerprint.abi) throw new Error(`[elysia-aot] Mismatch fingerprint`);
59
62
  claimed = new WeakRef(id);
60
63
  registered = void 0;
61
64
  programs.set(id, {
@@ -105,10 +108,6 @@ var Compiled = class {
105
108
  static getPlanRebuilder(id) {
106
109
  return programFor(id)?.planRebuilder;
107
110
  }
108
- /**
109
- * Drop a fully consumed program registration after an eager production
110
- * build publishes. Safe only when every route compiled before publish
111
- */
112
111
  static release(id) {
113
112
  programs.delete(id);
114
113
  }
@@ -117,6 +116,7 @@ var Compiled = class {
117
116
  registered = void 0;
118
117
  claimed = void 0;
119
118
  programs = /* @__PURE__ */ new WeakMap();
119
+ drifted?.clear();
120
120
  }
121
121
  };
122
122
  /**
@@ -194,6 +194,7 @@ exports.Compiled = Compiled;
194
194
  exports.CompilerState = CompilerState;
195
195
  exports.EMPTY_EXTERNALS = EMPTY_EXTERNALS;
196
196
  exports.aotActivationError = aotActivationError;
197
+ exports.aotDrift = aotDrift;
197
198
  exports.beginCompilerSession = beginCompilerSession;
198
199
  Object.defineProperty(exports, 'captureImpl', {
199
200
  enumerable: true,
@@ -205,4 +206,5 @@ exports.createAotFingerprint = createAotFingerprint;
205
206
  exports.endCompilerSession = endCompilerSession;
206
207
  exports.getCompilerSession = getCompilerSession;
207
208
  exports.reconstruct = reconstruct;
208
- exports.setCaptureImpl = setCaptureImpl;
209
+ exports.setCaptureImpl = setCaptureImpl;
210
+ exports.warnAotDrift = warnAotDrift;
@@ -3,8 +3,8 @@ import { env } from "../universal/env.mjs";
3
3
  import { version } from "../package.mjs";
4
4
 
5
5
  //#region src/compile/aot.ts
6
- const AOT_MANIFEST_FORMAT = 5;
7
- const AOT_ABI = `${version}:${5}`;
6
+ const AOT_MANIFEST_FORMAT = 6;
7
+ const AOT_ABI = `${version}:${6}`;
8
8
  const sharedAotFingerprint = Object.freeze({ abi: AOT_ABI });
9
9
  const createAotFingerprint = () => sharedAotFingerprint;
10
10
  let activeSession;
@@ -36,12 +36,16 @@ function reconstruct() {
36
36
  if (reconstructImpl === void 0) throw new Error("Elysia AOT reconstruct module is not activated");
37
37
  return reconstructImpl;
38
38
  }
39
+ let drifted;
40
+ const aotDrift = (method, path) => `[elysia-aot] ${method} ${path} differs from the AOT build`;
41
+ function warnAotDrift(method, path) {
42
+ const key = method + " " + path;
43
+ if (drifted?.has(key)) return;
44
+ drifted ??= /* @__PURE__ */ new Set();
45
+ drifted.add(key);
46
+ console.warn(aotDrift(method, path) + ", compiled at runtime");
47
+ }
39
48
  let registered;
40
- /**
41
- * App that consumed this process's manifest, held weakly: it only has to
42
- * recognise a re-claim by the *same* app, and `assertUncontested` always
43
- * compares against a live id, so a cleared ref answers as a strong one would
44
- */
45
49
  let claimed;
46
50
  let programs = /* @__PURE__ */ new WeakMap();
47
51
  const programFor = (id) => id ? programs.get(id) : void 0;
@@ -53,8 +57,7 @@ var Compiled = class {
53
57
  static claim(id, fingerprint) {
54
58
  if (!registered || claimed) return false;
55
59
  const manifest = registered;
56
- const expected = manifest.fingerprint;
57
- if (expected.abi !== fingerprint.abi) throw new Error(`[elysia-aot] Registered manifest fingerprint mismatch: abi (manifest ${expected.abi}, app ${fingerprint.abi}).`);
60
+ if (manifest.fingerprint.abi !== fingerprint.abi) throw new Error(`[elysia-aot] Mismatch fingerprint`);
58
61
  claimed = new WeakRef(id);
59
62
  registered = void 0;
60
63
  programs.set(id, {
@@ -104,10 +107,6 @@ var Compiled = class {
104
107
  static getPlanRebuilder(id) {
105
108
  return programFor(id)?.planRebuilder;
106
109
  }
107
- /**
108
- * Drop a fully consumed program registration after an eager production
109
- * build publishes. Safe only when every route compiled before publish
110
- */
111
110
  static release(id) {
112
111
  programs.delete(id);
113
112
  }
@@ -116,6 +115,7 @@ var Compiled = class {
116
115
  registered = void 0;
117
116
  claimed = void 0;
118
117
  programs = /* @__PURE__ */ new WeakMap();
118
+ drifted?.clear();
119
119
  }
120
120
  };
121
121
  /**
@@ -187,4 +187,4 @@ function setCaptureImpl(impl) {
187
187
  }
188
188
 
189
189
  //#endregion
190
- export { AOT_MANIFEST_FORMAT, Capture, Compiled, CompilerState, EMPTY_EXTERNALS, aotActivationError, beginCompilerSession, captureImpl, createAotFingerprint, endCompilerSession, getCompilerSession, reconstruct, setCaptureImpl };
190
+ export { AOT_MANIFEST_FORMAT, Capture, Compiled, CompilerState, EMPTY_EXTERNALS, aotActivationError, aotDrift, beginCompilerSession, captureImpl, createAotFingerprint, endCompilerSession, getCompilerSession, reconstruct, setCaptureImpl, warnAotDrift };
@@ -3,10 +3,10 @@ const require_utils = require('../../utils.js');
3
3
  const require_cookie_crypto = require('../../cookie/crypto.js');
4
4
  const require_compile_aot = require('../aot.js');
5
5
  const require_generation = require('../../generation.js');
6
- const require_cookie_config = require('../../cookie/config.js');
7
6
  const require_compile_utils = require('../utils.js');
8
7
  const require_compile_jit_probe = require('../jit-probe.js');
9
8
  const require_sucrose = require('../../sucrose.js');
9
+ const require_compile_handler_reconstruct = require('./reconstruct.js');
10
10
 
11
11
  //#region src/compile/handler/descriptor.ts
12
12
  /**
@@ -82,9 +82,8 @@ function describeRoute(input) {
82
82
  const paramsValiIsAsync = vali?.params && isAsyncValidator(vali.params);
83
83
  const queryValiIsAsync = vali?.query && isAsyncValidator(vali.query);
84
84
  const cookieValidIsAsync = vali?.cookie && isAsyncValidator(vali.cookie);
85
- const appCookieConfig = require_generation.frozenRootOf(root)["~config"]?.cookie;
86
85
  const needsCookie = !!vali?.cookie || !!inference.cookie;
87
- const cookieConfig = needsCookie ? require_cookie_config.compileCookieConfig(hook?.cookie, appCookieConfig) : void 0;
86
+ const cookieConfig = needsCookie ? require_compile_handler_reconstruct.Reconstrct.cookie(hook, root) : void 0;
88
87
  const hasCookieSign = !!cookieConfig?.hasSign;
89
88
  const syncCookieSign = hasCookieSign && require_cookie_crypto.hasSyncHmac && !require_compile_aot.Capture.isCapturing();
90
89
  const asyncCookieSign = hasCookieSign && !syncCookieSign;
@@ -2,10 +2,10 @@ import { isNotEmpty } from "../../utils.mjs";
2
2
  import { hasSyncHmac } from "../../cookie/crypto.mjs";
3
3
  import { Capture } from "../aot.mjs";
4
4
  import { frozenRootOf, resolvedTraceOf, traceCapabilityRequired } from "../../generation.mjs";
5
- import { compileCookieConfig } from "../../cookie/config.mjs";
6
5
  import { isAsyncFunction, isAsyncLifecycle, mayReturnPromise } from "../utils.mjs";
7
6
  import { JITProbe } from "../jit-probe.mjs";
8
7
  import { mergeInference, sucrose } from "../../sucrose.mjs";
8
+ import { Reconstrct } from "./reconstruct.mjs";
9
9
 
10
10
  //#region src/compile/handler/descriptor.ts
11
11
  /**
@@ -81,9 +81,8 @@ function describeRoute(input) {
81
81
  const paramsValiIsAsync = vali?.params && isAsyncValidator(vali.params);
82
82
  const queryValiIsAsync = vali?.query && isAsyncValidator(vali.query);
83
83
  const cookieValidIsAsync = vali?.cookie && isAsyncValidator(vali.cookie);
84
- const appCookieConfig = frozenRootOf(root)["~config"]?.cookie;
85
84
  const needsCookie = !!vali?.cookie || !!inference.cookie;
86
- const cookieConfig = needsCookie ? compileCookieConfig(hook?.cookie, appCookieConfig) : void 0;
85
+ const cookieConfig = needsCookie ? Reconstrct.cookie(hook, root) : void 0;
87
86
  const hasCookieSign = !!cookieConfig?.hasSign;
88
87
  const syncCookieSign = hasCookieSign && hasSyncHmac && !Capture.isCapturing();
89
88
  const asyncCookieSign = hasCookieSign && !syncCookieSign;
@@ -15,6 +15,7 @@ declare function chainResolver(root: AnyElysia): ((node: ChainNode) => Partial<A
15
15
  declare const localMacroRoot: (instance: AnyElysia, root: AnyElysia) => AnyElysia;
16
16
  declare function buildNativeStaticResponse(route: InternalRoute, root: AnyElysia): Response | undefined;
17
17
  declare function composeRouteHook(instance: AnyElysia, localHook: Partial<AnyLocalHook> | undefined, appHook: ChainNode | undefined, inheritedChain: ChainNode | undefined, root: AnyElysia, macroScope?: AnyElysia, allowCompactPrefix?: boolean): AnyLocalHook | undefined;
18
+ declare function routeShape(hook: AnyLocalHook | undefined, handler: unknown, root: AnyElysia): number | undefined;
18
19
  declare function compileHandler(route: InternalRoute, root: AnyElysia, liveOnly?: boolean): CompiledHandler;
19
20
  //#endregion
20
- export { buildNativeStaticResponse, chainResolver, clearHandlerAnalysisCaches, compileHandler, composeRouteHook, localMacroRoot, resolveLocalHook, resolveWSLocalHook, setCaptureHeaderShorthand };
21
+ export { buildNativeStaticResponse, chainResolver, clearHandlerAnalysisCaches, compileHandler, composeRouteHook, localMacroRoot, resolveLocalHook, resolveWSLocalHook, routeShape, setCaptureHeaderShorthand };
@@ -6,11 +6,14 @@ const require_error = require('../../error.js');
6
6
  const require_adapter_web_standard_handler = require('../../adapter/web-standard/handler.js');
7
7
  const require_compile_aot = require('../aot.js');
8
8
  const require_generation = require('../../generation.js');
9
+ const require_compile_utils = require('../utils.js');
9
10
  const require_handler_utils = require('../../handler/utils.js');
11
+ const require_compile_handler_utils = require('./utils.js');
10
12
  const require_compile_handler_params = require('./params.js');
11
13
  const require_compile_handler_jit = require('./jit.js');
12
- const require_compile_handler_descriptor = require('./descriptor.js');
14
+ const require_compile_handler_frozen_validator = require('./frozen-validator.js');
13
15
  const require_compile_handler_reconstruct = require('./reconstruct.js');
16
+ const require_compile_handler_descriptor = require('./descriptor.js');
14
17
  const require_adapter_constants = require('../../adapter/constants.js');
15
18
 
16
19
  //#region src/compile/handler/index.ts
@@ -274,18 +277,129 @@ function composeRouteHook(instance, localHook, appHook, inheritedChain, root, ma
274
277
  }
275
278
  return hook;
276
279
  }
277
- const hookStateAliases = [
278
- "ho",
279
- "tf",
280
- "bf",
281
- "af",
282
- "mr",
283
- "er",
284
- "ar",
285
- "va",
286
- "cc",
287
- "tr"
280
+ const shapeEvents = [
281
+ "parse",
282
+ "transform",
283
+ "beforeHandle",
284
+ "afterHandle",
285
+ "mapResponse",
286
+ "afterResponse",
287
+ "error",
288
+ "trace"
289
+ ];
290
+ const shapeSlots = [
291
+ "body",
292
+ "headers",
293
+ "params",
294
+ "query",
295
+ "cookie",
296
+ "response"
288
297
  ];
298
+ const isCookieAt = (at) => at === "cookie" || at === "field";
299
+ function childAt(at, k, value, deferred) {
300
+ if (at.endsWith("*")) return at.slice(0, -1);
301
+ if (at.endsWith("^")) return k === "0" ? at.slice(0, -1) + (Array.isArray(value) ? "*" : "") : "";
302
+ if (!isCookieAt(at)) return "";
303
+ switch (k) {
304
+ case "$ref": return at;
305
+ case "properties": return at === "cookie" ? "field*" : "";
306
+ case "parameters": return deferred ? at + "^" : "";
307
+ }
308
+ return k === "$defs" || require_utils.compositionKeys.includes(k) ? at + "*" : "";
309
+ }
310
+ function routeShape(hook, handler, root) {
311
+ const frozenRoot = require_generation.frozenRootOf(root);
312
+ const config = frozenRoot["~config"];
313
+ const models = frozenRoot["~ext"]?.models;
314
+ const refs = /* @__PURE__ */ new Map();
315
+ const addRef = (name, at = "") => {
316
+ if (!isCookieAt(at)) at = "";
317
+ if (at === "cookie" || !refs.get(name)) refs.set(name, at);
318
+ };
319
+ const ids = /* @__PURE__ */ new Map();
320
+ const visiting = /* @__PURE__ */ new Set();
321
+ let unsupported = false;
322
+ for (const _ in []) return;
323
+ const shape = (v, at = "") => {
324
+ switch (typeof v) {
325
+ case "string": return JSON.stringify(v);
326
+ case "number": return "n" + (Object.is(v, -0) ? "-0" : v);
327
+ case "bigint": return "b" + v;
328
+ case "boolean": return v ? "T" : "F";
329
+ case "undefined": return "U";
330
+ case "function":
331
+ if (ids.has(v)) return "#" + ids.get(v);
332
+ ids.set(v, ids.size);
333
+ return require_compile_utils.isAsyncFunction(v) ? "fa" : "fs";
334
+ case "symbol":
335
+ unsupported = true;
336
+ return "";
337
+ }
338
+ if (v === null) return "N";
339
+ if ("~standard" in v) return "S";
340
+ if (visiting.has(v)) {
341
+ unsupported = true;
342
+ return "";
343
+ }
344
+ let tag = "";
345
+ const list = Array.isArray(v);
346
+ const proto = Object.getPrototypeOf(v);
347
+ if (list ? proto !== Array.prototype : proto !== null && proto !== Object.prototype) {
348
+ const kind = proto && Object.getOwnPropertyDescriptor(proto, "~kind");
349
+ if (!kind || !("value" in kind) || Reflect.ownKeys(proto).length !== 1 || Object.getPrototypeOf(proto) !== Object.prototype) {
350
+ unsupported = true;
351
+ return "";
352
+ }
353
+ tag = shape(kind.value);
354
+ }
355
+ visiting.add(v);
356
+ const map = at === "response" && require_compile_handler_frozen_validator.isResponseMap(v);
357
+ const deferred = v["~kind"] === "Deferred";
358
+ let s = (list ? "[" : "{") + tag;
359
+ for (const k of Reflect.ownKeys(v)) {
360
+ const d = Object.getOwnPropertyDescriptor(v, k);
361
+ if (typeof k === "symbol" || !("value" in d)) {
362
+ unsupported = true;
363
+ break;
364
+ }
365
+ const value = d.value;
366
+ if (k === "$ref" && typeof value === "string") addRef(value, at);
367
+ s += "," + (d.enumerable ? "" : "!") + JSON.stringify(k) + ":";
368
+ if (map) s += named(value);
369
+ else if (k === "config" && isCookieAt(at)) s += shape([value?.sign, !!value?.secrets]);
370
+ else if (k === "secrets" && (typeof value === "string" || Array.isArray(value))) s += shape(!!value);
371
+ else s += shape(value, childAt(at, k, value, deferred));
372
+ }
373
+ visiting.delete(v);
374
+ return s + (list ? "]" : "}");
375
+ };
376
+ const named = (v, at) => {
377
+ if (typeof v === "string") addRef(v, at);
378
+ return shape(v, at);
379
+ };
380
+ let s = typeof handler === "function" || handler == null ? shape(handler) : handler instanceof Response ? "R" : handler instanceof Promise ? "P" : typeof handler === "object" ? "O" : "V";
381
+ for (const event of shapeEvents) {
382
+ s += "|";
383
+ const fns = hook?.[event];
384
+ if (fns) for (const fn of Array.isArray(fns) ? fns : [fns]) s += shape(fn);
385
+ }
386
+ const bf = hook?.beforeHandle;
387
+ s += "|" + JSON.stringify(bf && require_compile_handler_utils.deriveModes(Array.isArray(bf) ? bf : [bf], hook["~deriveEntries"]));
388
+ for (const from of [hook, ...hook?.schemas || []]) for (const slot of shapeSlots) s += "|" + named(from?.[slot], slot);
389
+ let targets;
390
+ for (const [ref, at] of refs) for (const target of at ? (targets ??= require_utils.refTargets([], models))(ref) : [models?.[ref]]) s += "|" + JSON.stringify(ref) + shape(target, at);
391
+ s += "|" + JSON.stringify([
392
+ config?.cookie?.sign,
393
+ config?.cookie?.verify,
394
+ config?.normalize,
395
+ !!config?.allowUnsafeValidationDetails,
396
+ config?.abortSignal !== false,
397
+ require_utils.isNotEmpty(frozenRoot["~ext"]?.headers),
398
+ !!(config?.adapter ?? require_adapter_constants.defaultAdapter).response.supportsDefaultHeaderSink,
399
+ !!require_handler_utils.returnedErrorClasses(hook, root)
400
+ ]) + shape(config?.sanitize);
401
+ return unsupported ? void 0 : require_utils.fnv1a(s);
402
+ }
289
403
  const isBareArrow = /^(?:async\s*)?\(\s*\)\s*=>/;
290
404
  const isSucroseOpaque = /arguments|eval|\[native code\]/;
291
405
  function compileHandler(route, root, liveOnly = false) {
@@ -303,17 +417,7 @@ function compileHandler(route, root, liveOnly = false) {
303
417
  handler = (c) => handle(new Request(require_utils.replaceUrlPath(c.request.url, c.path.slice(c.path.startsWith(encRoot) ? encLen : rawLen) || "/"), c.request));
304
418
  }
305
419
  const reconstructed = liveOnly ? void 0 : require_compile_aot.Compiled.getHandler(frozenRoot["~programId"], method, path);
306
- if (reconstructed && typeof handler === "function" && !frozenRoot["~ext"]?.macro && !require_generation.frozenRootOf(localMacroRoot(macroScope ?? instance, root))["~ext"]?.macro) {
307
- if (!reconstructed.a.some((name) => hookStateAliases.includes(name))) return reconstructed.f(handler, ...require_compile_handler_params.resolveHandlerParams(reconstructed.a, {
308
- root,
309
- parse: adapter.parse,
310
- res: adapter.response,
311
- hook: require_utils.nullObject(),
312
- vali: void 0,
313
- cookieConfig: void 0,
314
- tracers: void 0
315
- }));
316
- }
420
+ if (!reconstructed) liveOnly ||= require_compile_aot.Compiled.hasProgram(frozenRoot["~programId"]);
317
421
  const hook = composeRouteHook(instance, localHook, appHook, inheritedChain, root, macroScope, !reconstructed);
318
422
  if (hook) {
319
423
  promoteDerive(hook);
@@ -351,6 +455,20 @@ function compileHandler(route, root, liveOnly = false) {
351
455
  const resolve = (p) => typeof p === "string" && p in namedParsers ? namedParsers[p] : p;
352
456
  hook.parse = Array.isArray(hook.parse) ? hook.parse.map(resolve) : resolve(hook.parse);
353
457
  }
458
+ let shape;
459
+ if (reconstructed || require_compile_aot.Capture.isCapturing()) {
460
+ shape = routeShape(hook, handler, root);
461
+ if (reconstructed && (!shape || reconstructed.k !== shape)) {
462
+ let live;
463
+ try {
464
+ live = compileHandler(route, root, true);
465
+ } catch (cause) {
466
+ throw new Error(require_compile_aot.aotDrift(method, path), { cause });
467
+ }
468
+ require_compile_aot.warnAotDrift(method, path);
469
+ return live;
470
+ }
471
+ }
354
472
  if (reconstructed) return reconstructed.f(handler, ...require_compile_handler_params.resolveHandlerParams(reconstructed.a, {
355
473
  root,
356
474
  parse: adapter.parse,
@@ -402,7 +520,8 @@ function compileHandler(route, root, liveOnly = false) {
402
520
  isStaticResponse,
403
521
  isPromiseHandler,
404
522
  errorClasses,
405
- state
523
+ state,
524
+ shape
406
525
  });
407
526
  }
408
527
 
@@ -415,4 +534,5 @@ exports.composeRouteHook = composeRouteHook;
415
534
  exports.localMacroRoot = localMacroRoot;
416
535
  exports.resolveLocalHook = resolveLocalHook;
417
536
  exports.resolveWSLocalHook = resolveWSLocalHook;
537
+ exports.routeShape = routeShape;
418
538
  exports.setCaptureHeaderShorthand = require_compile_handler_jit.setCaptureHeaderShorthand;