elysia 2.0.0-beta.21 → 2.0.0-beta.22

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 (215) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +1 -0
  2. package/dist/adapter/bun/index.d.ts +6 -8
  3. package/dist/adapter/bun/index.js +6 -8
  4. package/dist/adapter/bun/index.mjs +7 -8
  5. package/dist/adapter/constants.mjs +1 -0
  6. package/dist/adapter/default-headers.mjs +1 -0
  7. package/dist/adapter/index.mjs +1 -0
  8. package/dist/adapter/origin.mjs +1 -0
  9. package/dist/adapter/response-ownership.mjs +1 -0
  10. package/dist/adapter/skip-clone.mjs +1 -0
  11. package/dist/adapter/types.mjs +1 -0
  12. package/dist/adapter/utils.d.ts +5 -8
  13. package/dist/adapter/utils.js +24 -18
  14. package/dist/adapter/utils.mjs +25 -18
  15. package/dist/adapter/web-standard/handler.mjs +2 -1
  16. package/dist/adapter/web-standard/index.mjs +1 -0
  17. package/dist/adapter/web-standard/utils.mjs +1 -0
  18. package/dist/base.d.ts +118 -69
  19. package/dist/base.js +213 -193
  20. package/dist/base.mjs +220 -199
  21. package/dist/compile/aot-capture.js +2 -2
  22. package/dist/compile/aot-capture.mjs +4 -3
  23. package/dist/compile/aot-emit.js +7 -8
  24. package/dist/compile/aot-emit.mjs +8 -8
  25. package/dist/compile/aot-reconstruct.mjs +3 -2
  26. package/dist/compile/aot.d.ts +3 -3
  27. package/dist/compile/aot.js +5 -5
  28. package/dist/compile/aot.mjs +6 -5
  29. package/dist/compile/handler/descriptor.d.ts +2 -5
  30. package/dist/compile/handler/descriptor.js +12 -17
  31. package/dist/compile/handler/descriptor.mjs +16 -21
  32. package/dist/compile/handler/frozen-validator.d.ts +2 -2
  33. package/dist/compile/handler/frozen-validator.js +3 -3
  34. package/dist/compile/handler/frozen-validator.mjs +4 -3
  35. package/dist/compile/handler/index.d.ts +3 -1
  36. package/dist/compile/handler/index.js +77 -118
  37. package/dist/compile/handler/index.mjs +83 -125
  38. package/dist/compile/handler/jit.d.ts +12 -12
  39. package/dist/compile/handler/jit.js +60 -43
  40. package/dist/compile/handler/jit.mjs +63 -47
  41. package/dist/compile/handler/params.d.ts +5 -1
  42. package/dist/compile/handler/params.js +14 -5
  43. package/dist/compile/handler/params.mjs +16 -7
  44. package/dist/compile/handler/reconstruct.d.ts +2 -2
  45. package/dist/compile/handler/reconstruct.js +2 -2
  46. package/dist/compile/handler/reconstruct.mjs +3 -2
  47. package/dist/compile/handler/static-clone-resolver.mjs +1 -0
  48. package/dist/compile/handler/utils.d.ts +13 -7
  49. package/dist/compile/handler/utils.js +75 -52
  50. package/dist/compile/handler/utils.mjs +77 -54
  51. package/dist/compile/jit-probe.mjs +1 -0
  52. package/dist/compile/lexer.js +4 -4
  53. package/dist/compile/lexer.mjs +5 -4
  54. package/dist/compile/utils.d.ts +2 -1
  55. package/dist/compile/utils.js +8 -3
  56. package/dist/compile/utils.mjs +8 -3
  57. package/dist/compiled.mjs +1 -0
  58. package/dist/constants.mjs +1 -0
  59. package/dist/context.d.ts +1 -1
  60. package/dist/context.js +1 -0
  61. package/dist/context.mjs +3 -1
  62. package/dist/cookie/config.d.ts +2 -2
  63. package/dist/cookie/config.js +21 -26
  64. package/dist/cookie/config.mjs +22 -26
  65. package/dist/cookie/cookie.mjs +1 -0
  66. package/dist/cookie/crypto.mjs +1 -0
  67. package/dist/cookie/error.mjs +1 -0
  68. package/dist/cookie/lib.mjs +1 -0
  69. package/dist/cookie/serialize.mjs +1 -0
  70. package/dist/cookie/types.mjs +1 -0
  71. package/dist/cookie/utils.d.ts +1 -1
  72. package/dist/cookie/utils.js +64 -45
  73. package/dist/cookie/utils.mjs +66 -46
  74. package/dist/error.d.ts +10 -6
  75. package/dist/error.js +22 -6
  76. package/dist/error.mjs +25 -9
  77. package/dist/generation.mjs +1 -0
  78. package/dist/handler/error.d.ts +12 -15
  79. package/dist/handler/error.js +43 -40
  80. package/dist/handler/error.mjs +45 -41
  81. package/dist/handler/fetch.js +59 -21
  82. package/dist/handler/fetch.mjs +61 -22
  83. package/dist/handler/utils.d.ts +16 -3
  84. package/dist/handler/utils.js +14 -13
  85. package/dist/handler/utils.mjs +16 -15
  86. package/dist/index.d.ts +9 -9
  87. package/dist/index.js +1 -0
  88. package/dist/index.mjs +3 -2
  89. package/dist/memory.mjs +1 -0
  90. package/dist/package.js +1 -1
  91. package/dist/package.mjs +2 -1
  92. package/dist/parse-query.js +76 -76
  93. package/dist/parse-query.mjs +77 -76
  94. package/dist/plugin/aot/bun.mjs +1 -0
  95. package/dist/plugin/aot/core.js +7 -4
  96. package/dist/plugin/aot/core.mjs +8 -5
  97. package/dist/plugin/aot/esbuild.mjs +1 -0
  98. package/dist/plugin/aot/rspack-loader.mjs +1 -0
  99. package/dist/plugin/aot/rspack.mjs +1 -0
  100. package/dist/plugin/aot/treeshake.mjs +1 -0
  101. package/dist/plugin/aot/unplugin.mjs +4 -3
  102. package/dist/plugin/aot/vite.mjs +1 -0
  103. package/dist/plugin/aot/worker.mjs +1 -0
  104. package/dist/plugin/auto-head.mjs +1 -0
  105. package/dist/plugin/trace.mjs +1 -0
  106. package/dist/plugin/websocket.mjs +1 -0
  107. package/dist/route-table.mjs +1 -0
  108. package/dist/schema-snapshot.mjs +1 -0
  109. package/dist/sucrose.d.ts +2 -2
  110. package/dist/sucrose.js +11 -11
  111. package/dist/sucrose.mjs +12 -11
  112. package/dist/trace.js +8 -10
  113. package/dist/trace.mjs +10 -11
  114. package/dist/type/bridge-live.d.ts +1 -1
  115. package/dist/type/bridge-live.mjs +1 -0
  116. package/dist/type/bridge.d.ts +1 -1
  117. package/dist/type/bridge.mjs +1 -0
  118. package/dist/type/coerce-plan.mjs +1 -0
  119. package/dist/type/coerce.d.ts +1 -1
  120. package/dist/type/coerce.mjs +1 -0
  121. package/dist/type/compat.mjs +1 -0
  122. package/dist/type/constants.d.ts +1 -1
  123. package/dist/type/constants.mjs +1 -0
  124. package/dist/type/elysia/accelerate.mjs +1 -0
  125. package/dist/type/elysia/array-buffer.d.ts +3 -2
  126. package/dist/type/elysia/array-buffer.js +5 -5
  127. package/dist/type/elysia/array-buffer.mjs +6 -5
  128. package/dist/type/elysia/array-string.mjs +1 -0
  129. package/dist/type/elysia/array.mjs +1 -0
  130. package/dist/type/elysia/boolean-string.mjs +1 -0
  131. package/dist/type/elysia/boolean.mjs +1 -0
  132. package/dist/type/elysia/cookie.mjs +1 -0
  133. package/dist/type/elysia/date.mjs +1 -0
  134. package/dist/type/elysia/file-type.mjs +1 -0
  135. package/dist/type/elysia/file.mjs +1 -0
  136. package/dist/type/elysia/files.mjs +1 -0
  137. package/dist/type/elysia/form.mjs +1 -0
  138. package/dist/type/elysia/integer-string.mjs +1 -0
  139. package/dist/type/elysia/integer.mjs +1 -0
  140. package/dist/type/elysia/intersect.mjs +1 -0
  141. package/dist/type/elysia/json-string.mjs +1 -0
  142. package/dist/type/elysia/keep-config.js +8 -8
  143. package/dist/type/elysia/keep-config.mjs +9 -8
  144. package/dist/type/elysia/maybe-empty.mjs +1 -0
  145. package/dist/type/elysia/no-validate.mjs +1 -0
  146. package/dist/type/elysia/nullable.mjs +1 -0
  147. package/dist/type/elysia/number.mjs +1 -0
  148. package/dist/type/elysia/numeric-enum.d.ts +4 -2
  149. package/dist/type/elysia/numeric-enum.mjs +1 -0
  150. package/dist/type/elysia/numeric.mjs +1 -0
  151. package/dist/type/elysia/object-string.mjs +1 -0
  152. package/dist/type/elysia/object.mjs +1 -0
  153. package/dist/type/elysia/optional.mjs +1 -0
  154. package/dist/type/elysia/problem.mjs +1 -0
  155. package/dist/type/elysia/string.mjs +1 -0
  156. package/dist/type/elysia/uint8-array.d.ts +2 -1
  157. package/dist/type/elysia/uint8-array.js +2 -2
  158. package/dist/type/elysia/uint8-array.mjs +3 -2
  159. package/dist/type/elysia/union-enum.mjs +1 -0
  160. package/dist/type/elysia/union.mjs +1 -0
  161. package/dist/type/elysia/utils.js +3 -3
  162. package/dist/type/elysia/utils.mjs +4 -3
  163. package/dist/type/exports.mjs +1 -0
  164. package/dist/type/index.mjs +2 -1
  165. package/dist/type/shared.mjs +1 -0
  166. package/dist/type/sync-require.mjs +1 -0
  167. package/dist/type/typebox-system-lite.mjs +1 -0
  168. package/dist/type/typebox-system-require.mjs +1 -0
  169. package/dist/type/typebox-type-live.mjs +1 -0
  170. package/dist/type/typebox-value-live.mjs +1 -0
  171. package/dist/type/typebox-value-ops.mjs +1 -0
  172. package/dist/type/typebox-value.mjs +1 -0
  173. package/dist/type/types.d.ts +1 -1
  174. package/dist/type/types.mjs +1 -0
  175. package/dist/type/utils.mjs +1 -0
  176. package/dist/type/validator/clean-safe.mjs +1 -0
  177. package/dist/type/validator/custom-error.js +41 -33
  178. package/dist/type/validator/custom-error.mjs +42 -33
  179. package/dist/type/validator/default-precompute.d.ts +2 -2
  180. package/dist/type/validator/default-precompute.js +10 -11
  181. package/dist/type/validator/default-precompute.mjs +13 -13
  182. package/dist/type/validator/exact-mirror.mjs +1 -0
  183. package/dist/type/validator/frozen-check.js +7 -7
  184. package/dist/type/validator/frozen-check.mjs +8 -7
  185. package/dist/type/validator/index.d.ts +2 -2
  186. package/dist/type/validator/index.js +4 -8
  187. package/dist/type/validator/index.mjs +5 -8
  188. package/dist/type/validator/string-codec-aot.d.ts +1 -1
  189. package/dist/type/validator/string-codec-aot.mjs +1 -0
  190. package/dist/type/validator/validator-cache.js +18 -18
  191. package/dist/type/validator/validator-cache.mjs +19 -18
  192. package/dist/types.d.ts +105 -69
  193. package/dist/types.mjs +1 -0
  194. package/dist/universal/constants.mjs +1 -0
  195. package/dist/universal/file.mjs +1 -0
  196. package/dist/universal/index.mjs +1 -0
  197. package/dist/universal/is-production.mjs +1 -0
  198. package/dist/universal/server.mjs +1 -0
  199. package/dist/utils.d.ts +49 -31
  200. package/dist/utils.js +221 -109
  201. package/dist/utils.mjs +215 -106
  202. package/dist/validator/index.d.ts +3 -3
  203. package/dist/validator/index.js +4 -4
  204. package/dist/validator/index.mjs +5 -4
  205. package/dist/validator/route.d.ts +2 -2
  206. package/dist/validator/route.mjs +1 -0
  207. package/dist/ws/context.js +1 -1
  208. package/dist/ws/context.mjs +2 -1
  209. package/dist/ws/index.mjs +1 -0
  210. package/dist/ws/parser.mjs +1 -0
  211. package/dist/ws/route.js +34 -25
  212. package/dist/ws/route.mjs +40 -30
  213. package/dist/ws/types.d.ts +2 -3
  214. package/dist/ws/types.mjs +1 -0
  215. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
+ // @bun
1
2
  import { nullObject } from "../../utils.mjs";
2
- import { subValueAt } from "../../error.mjs";
3
3
  import { EMPTY_EXTERNALS, reconstruct } from "../../compile/aot.mjs";
4
4
  import { Build, SchemaCompile } from "../typebox-value.mjs";
5
5
  import { buildFrozenCheck } from "./frozen-check.mjs";
@@ -7,10 +7,10 @@ import { buildFrozenCheck } from "./frozen-check.mjs";
7
7
  //#region src/type/validator/custom-error.ts
8
8
  function encodePointer(segments) {
9
9
  let out = "";
10
- for (const s of segments) out += "/" + s.replace(/~/g, "~0").replace(/\//g, "~1");
10
+ for (const s of segments) out += "/" + (typeof s === "object" ? "[]" : String(s).replace(/~/g, "~0").replace(/\//g, "~1"));
11
11
  return out;
12
12
  }
13
- function collectCustomErrorNodes(schema, segments, out, seen, union) {
13
+ function collectCustomErrorNodes(schema, segments, out, seen, union, required) {
14
14
  if (!schema || typeof schema !== "object") return out;
15
15
  if (seen.has(schema)) return out;
16
16
  seen.add(schema);
@@ -18,22 +18,16 @@ function collectCustomErrorNodes(schema, segments, out, seen, union) {
18
18
  path: encodePointer(segments),
19
19
  node: schema,
20
20
  segments,
21
+ required,
21
22
  union
22
23
  });
23
- if (schema.properties) for (const k in schema.properties) collectCustomErrorNodes(schema.properties[k], [...segments, k], out, seen, union);
24
- const items = schema.items;
25
- if (Array.isArray(items)) for (let i = 0; i < items.length; i++) collectCustomErrorNodes(items[i], [...segments, String(i)], out, seen, union);
26
- else if (items && typeof items === "object") {
27
- const inner = [];
28
- collectCustomErrorNodes(items, [], inner, seen, union);
29
- for (const child of inner) out.push({
30
- path: encodePointer(segments) + "/[]" + child.path,
31
- node: child.node,
32
- segments,
33
- each: { itemSegments: child.segments },
34
- union: child.union
35
- });
24
+ if (schema.properties) {
25
+ const keys = union?.segments !== segments && Array.isArray(schema.required) ? schema.required : void 0;
26
+ for (const k in schema.properties) collectCustomErrorNodes(schema.properties[k], [...segments, k], out, seen, union, keys?.includes(k));
36
27
  }
28
+ const items = schema.items;
29
+ if (Array.isArray(items)) for (let i = 0; i < items.length; i++) collectCustomErrorNodes(items[i], [...segments, i], out, seen, union);
30
+ else if (items && typeof items === "object") collectCustomErrorNodes(items, [...segments, { items }], out, seen, union);
37
31
  const branches = schema.anyOf ?? schema.oneOf;
38
32
  if (Array.isArray(branches)) for (let i = 0; i < branches.length; i++) collectCustomErrorNodes(branches[i], segments, out, seen, {
39
33
  node: schema,
@@ -76,26 +70,43 @@ function buildFindCustomError(schema, frozen) {
76
70
  const nodes = collectCustomErrorNodes(schema, [], [], /* @__PURE__ */ new WeakSet());
77
71
  if (!nodes.length) return;
78
72
  const frozenByPath = frozen?.ce ? new Map(frozen.ce.map((e) => [e.p, e])) : void 0;
79
- const unionCheckCache = /* @__PURE__ */ new WeakMap();
73
+ const checkCache = /* @__PURE__ */ new WeakMap();
80
74
  const discriminatorCache = /* @__PURE__ */ new WeakMap();
81
- const compileUnion = (node) => {
82
- const cached = unionCheckCache.get(node);
75
+ const compileOnce = (node) => {
76
+ const cached = checkCache.get(node);
83
77
  if (cached) return cached;
84
78
  try {
85
79
  const uc = SchemaCompile(node);
86
80
  const fn = (v) => uc.Check(v);
87
- unionCheckCache.set(node, fn);
81
+ checkCache.set(node, fn);
88
82
  return fn;
89
83
  } catch {
90
84
  return;
91
85
  }
92
86
  };
87
+ let found;
88
+ const reach = (value, segments) => {
89
+ let current = value;
90
+ for (let i = 0; i < segments.length; i++) {
91
+ const s = segments[i];
92
+ if (current === null || typeof current !== "object" || Array.isArray(current) === (typeof s === "string")) return -1;
93
+ if (typeof s === "object") {
94
+ const check = compileOnce(s.items);
95
+ const at = check ? current.findIndex((x) => !check(x)) : -1;
96
+ if (at < 0) return -1;
97
+ current = current[at];
98
+ } else if (s in current) current = current[s];
99
+ else return i === segments.length - 1 ? 0 : -1;
100
+ }
101
+ found = current;
102
+ return 1;
103
+ };
93
104
  const discriminatorsOf = (node, branches) => {
94
105
  if (!discriminatorCache.has(node)) discriminatorCache.set(node, findDiscriminators(branches));
95
106
  return discriminatorCache.get(node) ?? void 0;
96
107
  };
97
108
  const checks = [];
98
- for (const { path, node, each, segments, union } of nodes) {
109
+ for (const { path, node, segments, required, union } of nodes) {
99
110
  let check;
100
111
  const fe = union ? void 0 : frozenByPath?.get(path);
101
112
  if (fe) try {
@@ -106,23 +117,19 @@ function buildFindCustomError(schema, frozen) {
106
117
  check = (v) => c.Check(v);
107
118
  } catch {}
108
119
  if (!check) continue;
109
- if (each) {
110
- const leafCheck = check;
111
- const itemSegments = each.itemSegments;
112
- check = (v) => !Array.isArray(v) || v.every((x) => leafCheck(subValueAt(x, itemSegments)));
113
- }
114
120
  let gate;
115
121
  if (union) {
116
122
  const branches = union.node.anyOf ?? union.node.oneOf ?? [];
117
123
  const discriminators = discriminatorsOf(union.node, branches);
118
124
  if (!discriminators) gate = () => true;
119
125
  else {
120
- const unionCheck = compileUnion(union.node);
126
+ const unionCheck = compileOnce(union.node);
121
127
  if (!unionCheck) continue;
122
128
  const unionSegments = union.segments;
123
129
  const branchIndex = union.branchIndex;
124
130
  gate = (root) => {
125
- const unionValue = subValueAt(root, unionSegments);
131
+ if (reach(root, unionSegments) < 1) return true;
132
+ const unionValue = found;
126
133
  if (unionCheck(unionValue)) return true;
127
134
  if (unionValue === null || typeof unionValue !== "object") return true;
128
135
  let matches = 0;
@@ -145,7 +152,7 @@ function buildFindCustomError(schema, frozen) {
145
152
  }
146
153
  checks.push({
147
154
  segments,
148
- each,
155
+ required,
149
156
  check,
150
157
  gate,
151
158
  path,
@@ -153,11 +160,13 @@ function buildFindCustomError(schema, frozen) {
153
160
  });
154
161
  }
155
162
  if (!checks.length) return;
156
- checks.sort((a, b) => b.segments.length - a.segments.length || b.path.length - a.path.length);
163
+ checks.sort((a, b) => b.segments.length - a.segments.length);
157
164
  return (value) => {
158
165
  for (const c of checks) {
159
166
  if (c.gate && c.gate(value)) continue;
160
- if (!c.check(subValueAt(value, c.segments))) return {
167
+ const at = reach(value, c.segments);
168
+ if (at < 0 || !at && !c.required) continue;
169
+ if (!at || !c.check(found)) return {
161
170
  instancePath: c.path,
162
171
  error: c.error
163
172
  };
@@ -168,8 +177,8 @@ function captureCustomErrors(schema) {
168
177
  const ceNodes = collectCustomErrorNodes(schema, [], [], /* @__PURE__ */ new WeakSet());
169
178
  if (!ceNodes.length) return;
170
179
  const entries = [];
171
- for (const { path, node, union, each } of ceNodes) {
172
- if (union || each) continue;
180
+ for (const { path, node, union, segments } of ceNodes) {
181
+ if (union || segments.some((s) => typeof s === "object")) continue;
173
182
  try {
174
183
  const cf = buildFrozenCheck(Build(node), node);
175
184
  if (cf) entries.push({
@@ -23,7 +23,7 @@ interface DefaultProbeImpl {
23
23
  validateObjectDefault(schema: TSchema, pod: Record<string, unknown>): boolean;
24
24
  }
25
25
  declare function setDefaultProbeImpl(impl: DefaultProbeImpl): void;
26
- declare function canonical(v: unknown): string;
26
+ declare function stableStringify(v: unknown): string;
27
27
  declare function verifyPreallocatableDefault(schema: TSchema, validate?: boolean): {
28
28
  pd: unknown;
29
29
  pn: boolean;
@@ -31,4 +31,4 @@ declare function verifyPreallocatableDefault(schema: TSchema, validate?: boolean
31
31
  ms: string | undefined;
32
32
  } | undefined;
33
33
  //#endregion
34
- export { DefaultProbeImpl, applyPrecomputed, buildDefaultClonerSource, buildObjectDefaultMergeSource, canonical, createDefaultCloner, createMergerFromSource, createObjectDefaultMerger, isEmittable, precomputeCompileFailures, setDefaultProbeImpl, verifyPreallocatableDefault };
34
+ export { DefaultProbeImpl, applyPrecomputed, buildDefaultClonerSource, buildObjectDefaultMergeSource, createDefaultCloner, createMergerFromSource, createObjectDefaultMerger, isEmittable, precomputeCompileFailures, setDefaultProbeImpl, stableStringify, verifyPreallocatableDefault };
@@ -37,7 +37,7 @@ function nestedOwnDefaultDiverges(objectSchema) {
37
37
  const child = props[key];
38
38
  if (!child || typeof child !== "object") continue;
39
39
  if ("default" in child) {
40
- if (!(key in own) || canonical(own[key]) !== canonical(child.default)) return true;
40
+ if (!(key in own) || stableStringify(own[key]) !== stableStringify(child.default)) return true;
41
41
  } else if (child["~kind"] === "Object" || child.type === "object") {
42
42
  if (key in own) {
43
43
  if (nestedOwnDefaultDiverges({
@@ -74,8 +74,8 @@ const containsRefLike = (node) => require_type_validator_clean_safe.schemaSome(n
74
74
  function structuralPreallocatable(schema, depth = 0) {
75
75
  if (!schema || typeof schema !== "object") return true;
76
76
  if (!((schema["~kind"] === "Object" || schema.type === "object") && !schema["~codec"] && !schema["~refine"] && !Array.isArray(schema.anyOf) && !Array.isArray(schema.allOf) && !Array.isArray(schema.oneOf) && schema.$ref === void 0 && schema.if === void 0 && schema.not === void 0)) {
77
- const ownKey = "default" in schema ? canonical(schema.default) : void 0;
78
- return !require_type_validator_clean_safe.schemaSome(schema, (n) => n !== schema && "default" in n && (ownKey === void 0 || canonical(n.default) !== ownKey), void 0, void 0, true);
77
+ const ownKey = "default" in schema ? stableStringify(schema.default) : void 0;
78
+ return !require_type_validator_clean_safe.schemaSome(schema, (n) => n !== schema && "default" in n && (ownKey === void 0 || stableStringify(n.default) !== ownKey), void 0, void 0, true);
79
79
  }
80
80
  if (depth > 0 && schema.default === void 0 && hasDefaultBelow(schema)) return false;
81
81
  if (typeof schema.additionalProperties === "object" && subtreeHasDefault(schema.additionalProperties)) return false;
@@ -336,12 +336,12 @@ function probe() {
336
336
  if (!probeImpl) throw new Error("[Elysia] validating a preallocatable default requires the build-only AOT capture module (src/compile/aot-capture)");
337
337
  return probeImpl;
338
338
  }
339
- function canonical(v) {
339
+ function stableStringify(v) {
340
340
  if (v === void 0) return "\0u";
341
341
  if (Object.is(v, -0)) return "-0";
342
342
  if (v === null || typeof v !== "object") return JSON.stringify(v) ?? "\0u";
343
- if (Array.isArray(v)) return "[" + v.map(canonical).join(",") + "]";
344
- return "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + canonical(v[k])).join(",") + "}";
343
+ if (Array.isArray(v)) return "[" + v.map(stableStringify).join(",") + "]";
344
+ return "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + stableStringify(v[k])).join(",") + "}";
345
345
  }
346
346
  function verifyPreallocatableDefault(schema, validate = true) {
347
347
  if (hasUnemittableDefaultValue(schema)) return;
@@ -361,11 +361,10 @@ function verifyPreallocatableDefault(schema, validate = true) {
361
361
  const nullDefault = isPrecomputeSafe(schema);
362
362
  let ms;
363
363
  const category = mergeCategory(schema);
364
- if (category !== "object" && category !== "array") ms = void 0;
365
- else {
364
+ if (category === "object" || category === "array") {
366
365
  const helpers = [];
367
- const root = emitMerger(schema, helpers, /* @__PURE__ */ new WeakMap());
368
- ms = root ? `(function(){${helpers.join(";")};return ${root}})()` : void 0;
366
+ const root = emitMerger(schema, helpers);
367
+ if (root) ms = `(function(){${helpers.join(";")};return ${root}})()`;
369
368
  }
370
369
  if (ms !== void 0 && validate && !probe().validateMergeSource(schema, ms)) ms = void 0;
371
370
  if (!nullDefault && ms === void 0) {
@@ -385,11 +384,11 @@ function verifyPreallocatableDefault(schema, validate = true) {
385
384
  exports.applyPrecomputed = applyPrecomputed;
386
385
  exports.buildDefaultClonerSource = buildDefaultClonerSource;
387
386
  exports.buildObjectDefaultMergeSource = buildObjectDefaultMergeSource;
388
- exports.canonical = canonical;
389
387
  exports.createDefaultCloner = createDefaultCloner;
390
388
  exports.createMergerFromSource = createMergerFromSource;
391
389
  exports.createObjectDefaultMerger = createObjectDefaultMerger;
392
390
  exports.isEmittable = isEmittable;
393
391
  exports.precomputeCompileFailures = precomputeCompileFailures;
394
392
  exports.setDefaultProbeImpl = setDefaultProbeImpl;
393
+ exports.stableStringify = stableStringify;
395
394
  exports.verifyPreallocatableDefault = verifyPreallocatableDefault;
@@ -1,3 +1,4 @@
1
+ // @bun
1
2
  import { dangerousKeys } from "../../constants.mjs";
2
3
  import { nullObject } from "../../utils.mjs";
3
4
  import { isProduction } from "../../universal/is-production.mjs";
@@ -36,7 +37,7 @@ function nestedOwnDefaultDiverges(objectSchema) {
36
37
  const child = props[key];
37
38
  if (!child || typeof child !== "object") continue;
38
39
  if ("default" in child) {
39
- if (!(key in own) || canonical(own[key]) !== canonical(child.default)) return true;
40
+ if (!(key in own) || stableStringify(own[key]) !== stableStringify(child.default)) return true;
40
41
  } else if (child["~kind"] === "Object" || child.type === "object") {
41
42
  if (key in own) {
42
43
  if (nestedOwnDefaultDiverges({
@@ -73,8 +74,8 @@ const containsRefLike = (node) => schemaSome(node, (n) => n.$ref !== void 0 || n
73
74
  function structuralPreallocatable(schema, depth = 0) {
74
75
  if (!schema || typeof schema !== "object") return true;
75
76
  if (!((schema["~kind"] === "Object" || schema.type === "object") && !schema["~codec"] && !schema["~refine"] && !Array.isArray(schema.anyOf) && !Array.isArray(schema.allOf) && !Array.isArray(schema.oneOf) && schema.$ref === void 0 && schema.if === void 0 && schema.not === void 0)) {
76
- const ownKey = "default" in schema ? canonical(schema.default) : void 0;
77
- return !schemaSome(schema, (n) => n !== schema && "default" in n && (ownKey === void 0 || canonical(n.default) !== ownKey), void 0, void 0, true);
77
+ const ownKey = "default" in schema ? stableStringify(schema.default) : void 0;
78
+ return !schemaSome(schema, (n) => n !== schema && "default" in n && (ownKey === void 0 || stableStringify(n.default) !== ownKey), void 0, void 0, true);
78
79
  }
79
80
  if (depth > 0 && schema.default === void 0 && hasDefaultBelow(schema)) return false;
80
81
  if (typeof schema.additionalProperties === "object" && subtreeHasDefault(schema.additionalProperties)) return false;
@@ -216,7 +217,7 @@ let compileFailures = 0;
216
217
  *
217
218
  * Build-time only. A non-zero count means codegen emitted source that
218
219
  * `Function()` rejected, so those routes silently fell back to the interpreted
219
- * default path — always a bug in this module, never a user error.
220
+ * default path \u2014 always a bug in this module, never a user error.
220
221
  */
221
222
  const precomputeCompileFailures = () => compileFailures;
222
223
  function fromSource(source) {
@@ -224,7 +225,7 @@ function fromSource(source) {
224
225
  return Function(`return ${source}`)();
225
226
  } catch (error) {
226
227
  compileFailures++;
227
- console.warn("[Elysia] default precompute emitted source that does not compile; falling back to the interpreted default path. This is a bug, please report it:", error, ...isProduction() ? [] : ["\nsource: " + (source.length > 512 ? source.slice(0, 512) + "…" : source)]);
228
+ console.warn("[Elysia] default precompute emitted source that does not compile; falling back to the interpreted default path. This is a bug, please report it:", error, ...isProduction() ? [] : ["\nsource: " + (source.length > 512 ? source.slice(0, 512) + "\u2026" : source)]);
228
229
  }
229
230
  }
230
231
  function createDefaultCloner(value) {
@@ -335,12 +336,12 @@ function probe() {
335
336
  if (!probeImpl) throw new Error("[Elysia] validating a preallocatable default requires the build-only AOT capture module (src/compile/aot-capture)");
336
337
  return probeImpl;
337
338
  }
338
- function canonical(v) {
339
+ function stableStringify(v) {
339
340
  if (v === void 0) return "\0u";
340
341
  if (Object.is(v, -0)) return "-0";
341
342
  if (v === null || typeof v !== "object") return JSON.stringify(v) ?? "\0u";
342
- if (Array.isArray(v)) return "[" + v.map(canonical).join(",") + "]";
343
- return "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + canonical(v[k])).join(",") + "}";
343
+ if (Array.isArray(v)) return "[" + v.map(stableStringify).join(",") + "]";
344
+ return "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + stableStringify(v[k])).join(",") + "}";
344
345
  }
345
346
  function verifyPreallocatableDefault(schema, validate = true) {
346
347
  if (hasUnemittableDefaultValue(schema)) return;
@@ -360,11 +361,10 @@ function verifyPreallocatableDefault(schema, validate = true) {
360
361
  const nullDefault = isPrecomputeSafe(schema);
361
362
  let ms;
362
363
  const category = mergeCategory(schema);
363
- if (category !== "object" && category !== "array") ms = void 0;
364
- else {
364
+ if (category === "object" || category === "array") {
365
365
  const helpers = [];
366
- const root = emitMerger(schema, helpers, /* @__PURE__ */ new WeakMap());
367
- ms = root ? `(function(){${helpers.join(";")};return ${root}})()` : void 0;
366
+ const root = emitMerger(schema, helpers);
367
+ if (root) ms = `(function(){${helpers.join(";")};return ${root}})()`;
368
368
  }
369
369
  if (ms !== void 0 && validate && !probe().validateMergeSource(schema, ms)) ms = void 0;
370
370
  if (!nullDefault && ms === void 0) {
@@ -381,4 +381,4 @@ function verifyPreallocatableDefault(schema, validate = true) {
381
381
  }
382
382
 
383
383
  //#endregion
384
- export { applyPrecomputed, buildDefaultClonerSource, buildObjectDefaultMergeSource, canonical, createDefaultCloner, createMergerFromSource, createObjectDefaultMerger, isEmittable, precomputeCompileFailures, setDefaultProbeImpl, verifyPreallocatableDefault };
384
+ export { applyPrecomputed, buildDefaultClonerSource, buildObjectDefaultMergeSource, createDefaultCloner, createMergerFromSource, createObjectDefaultMerger, isEmittable, precomputeCompileFailures, setDefaultProbeImpl, stableStringify, verifyPreallocatableDefault };
@@ -1,3 +1,4 @@
1
+ // @bun
1
2
  import { syncRequire } from "../sync-require.mjs";
2
3
  import { requireExactMirror } from "./exact-mirror-require.mjs";
3
4
 
@@ -4,14 +4,14 @@ const require_compile_aot_emit = require('../../compile/aot-emit.js');
4
4
  //#region src/type/validator/frozen-check.ts
5
5
  function buildFrozenCheck(build, node) {
6
6
  if (!build?.functions?.length || !build.entry) return;
7
- const b = require_compile_aot_emit.alignBuildExternals(build, node);
8
- if (!b) return;
9
- const cr = require_compile_aot_emit.reconstructCheck(b);
7
+ const aligned = require_compile_aot_emit.alignBuildExternals(build, node);
8
+ if (!aligned) return;
9
+ const check = require_compile_aot_emit.reconstructCheck(aligned);
10
10
  return {
11
- identifier: b.external.identifier,
12
- checkDefs: cr.defs,
13
- checkValue: cr.value,
14
- external: b.external.variables.length > 0
11
+ identifier: aligned.external.identifier,
12
+ checkDefs: check.defs,
13
+ checkValue: check.value,
14
+ external: aligned.external.variables.length > 0
15
15
  };
16
16
  }
17
17
 
@@ -1,16 +1,17 @@
1
+ // @bun
1
2
  import { alignBuildExternals, reconstructCheck } from "../../compile/aot-emit.mjs";
2
3
 
3
4
  //#region src/type/validator/frozen-check.ts
4
5
  function buildFrozenCheck(build, node) {
5
6
  if (!build?.functions?.length || !build.entry) return;
6
- const b = alignBuildExternals(build, node);
7
- if (!b) return;
8
- const cr = reconstructCheck(b);
7
+ const aligned = alignBuildExternals(build, node);
8
+ if (!aligned) return;
9
+ const check = reconstructCheck(aligned);
9
10
  return {
10
- identifier: b.external.identifier,
11
- checkDefs: cr.defs,
12
- checkValue: cr.value,
13
- external: b.external.variables.length > 0
11
+ identifier: aligned.external.identifier,
12
+ checkDefs: check.defs,
13
+ checkValue: check.value,
14
+ external: aligned.external.variables.length > 0
14
15
  };
15
16
  }
16
17
 
@@ -1,6 +1,6 @@
1
- import { MaybePromise } from "../../types.js";
2
1
  import { Validator as Validator$1, ValidatorOptions } from "../../validator/index.js";
3
2
  import { TypeBoxValidatorCache, mayHaveFileType } from "./validator-cache.js";
3
+ import { MaybePromise } from "../../types.js";
4
4
  import { Static, StaticDecode, StaticEncode, TAny, TSchema } from "typebox/type";
5
5
  import { Validator } from "typebox/schema";
6
6
  import { TLocalizedValidationError } from "typebox/error";
@@ -10,7 +10,7 @@ declare function shallowMergeObjects(members: any[]): TSchema | null;
10
10
  declare function schemaMayHaveAsyncRefine(node: any, seen?: WeakSet<object>): boolean;
11
11
  declare class TypeBoxValidator<const in out T extends TSchema = TAny> extends Validator$1 {
12
12
  #private;
13
- static member(schema: TSchema, compiled: any): boolean;
13
+ static isAsyncMember(schema: TSchema, compiled: any): boolean;
14
14
  tb?: Validator;
15
15
  reconstructedCheck?: (value: unknown) => boolean;
16
16
  schema: T;
@@ -217,7 +217,7 @@ function warnMirrorFailure(schema, error) {
217
217
  }
218
218
  let warnedMissingMirror = false;
219
219
  var TypeBoxValidator = class extends require_validator_index.Validator {
220
- static member(schema, compiled) {
220
+ static isAsyncMember(schema, compiled) {
221
221
  const isAsync = (compiled.buildResult ?? require_type_typebox_value.Build(schema)).external.variables.some(require_type_elysia_file_type.isAsyncPredicate);
222
222
  collectRefinements(schema);
223
223
  return isAsync;
@@ -282,14 +282,11 @@ var TypeBoxValidator = class extends require_validator_index.Validator {
282
282
  })[id];
283
283
  }
284
284
  }
285
- let isFrozen;
286
- if (!options?.aot || !options.slot || options.normalize === "typebox") isFrozen = false;
287
- else if (!frozen?.c && !frozen?.cm) isFrozen = false;
288
- else {
285
+ const isFrozen = !!(options?.aot && options.slot && options.normalize !== "typebox" && (frozen?.c || frozen?.cm));
286
+ if (isFrozen) {
289
287
  this.isAsync = frozen.a === 1;
290
288
  this.hasDefault = frozen.d === 1;
291
289
  this.hasCodec = frozen.k === 1;
292
- isFrozen = true;
293
290
  }
294
291
  this.schema = isFrozen && frozen.cp ? require_type_coerce.buildCoercedFromPlan(schema, frozen.cp) : isFrozen && !this.hasCodec ? schema : require_type_coerce.applyCoercions(schema, options?.coerces);
295
292
  if (options?.normalize === false && options.slot !== "headers" && options.slot !== "cookie") this.schema = require_type_shared.nonAdditionalProperties(this.schema);
@@ -370,8 +367,7 @@ var TypeBoxValidator = class extends require_validator_index.Validator {
370
367
  }
371
368
  try {
372
369
  if (options?.normalize === false) this.Clean = void 0;
373
- else if (options?.normalize === "typebox") this.Clean = (value) => require_type_typebox_value.Clean(this.schema, value);
374
- else if (require_type_validator_clean_safe.schemaHasDangerousProperties(this.schema)) this.Clean = (value) => require_type_typebox_value.Clean(this.schema, value);
370
+ else if (options?.normalize === "typebox" || require_type_validator_clean_safe.schemaHasDangerousProperties(this.schema)) this.Clean = (value) => require_type_typebox_value.Clean(this.schema, value);
375
371
  else {
376
372
  const aot = options?.aot;
377
373
  const slot = options?.slot;
@@ -1,3 +1,4 @@
1
+ // @bun
1
2
  import { ELYSIA_FORM_PROTOTYPE, nullObject } from "../../utils.mjs";
2
3
  import { ELYSIA_TYPES } from "../constants.mjs";
3
4
  import { ValidationError } from "../../error.mjs";
@@ -216,7 +217,7 @@ function warnMirrorFailure(schema, error) {
216
217
  }
217
218
  let warnedMissingMirror = false;
218
219
  var TypeBoxValidator = class extends Validator {
219
- static member(schema, compiled) {
220
+ static isAsyncMember(schema, compiled) {
220
221
  const isAsync = (compiled.buildResult ?? Build(schema)).external.variables.some(isAsyncPredicate);
221
222
  collectRefinements(schema);
222
223
  return isAsync;
@@ -281,14 +282,11 @@ var TypeBoxValidator = class extends Validator {
281
282
  })[id];
282
283
  }
283
284
  }
284
- let isFrozen;
285
- if (!options?.aot || !options.slot || options.normalize === "typebox") isFrozen = false;
286
- else if (!frozen?.c && !frozen?.cm) isFrozen = false;
287
- else {
285
+ const isFrozen = !!(options?.aot && options.slot && options.normalize !== "typebox" && (frozen?.c || frozen?.cm));
286
+ if (isFrozen) {
288
287
  this.isAsync = frozen.a === 1;
289
288
  this.hasDefault = frozen.d === 1;
290
289
  this.hasCodec = frozen.k === 1;
291
- isFrozen = true;
292
290
  }
293
291
  this.schema = isFrozen && frozen.cp ? buildCoercedFromPlan(schema, frozen.cp) : isFrozen && !this.hasCodec ? schema : applyCoercions(schema, options?.coerces);
294
292
  if (options?.normalize === false && options.slot !== "headers" && options.slot !== "cookie") this.schema = nonAdditionalProperties(this.schema);
@@ -369,8 +367,7 @@ var TypeBoxValidator = class extends Validator {
369
367
  }
370
368
  try {
371
369
  if (options?.normalize === false) this.Clean = void 0;
372
- else if (options?.normalize === "typebox") this.Clean = (value) => Clean(this.schema, value);
373
- else if (schemaHasDangerousProperties(this.schema)) this.Clean = (value) => Clean(this.schema, value);
370
+ else if (options?.normalize === "typebox" || schemaHasDangerousProperties(this.schema)) this.Clean = (value) => Clean(this.schema, value);
374
371
  else {
375
372
  const aot = options?.aot;
376
373
  const slot = options?.slot;
@@ -1,5 +1,5 @@
1
- import { ValidatorOptions } from "../../validator/index.js";
2
1
  import { CapturedValidator } from "../../compile/aot.js";
2
+ import { ValidatorOptions } from "../../validator/index.js";
3
3
  import { TSchema } from "typebox/type";
4
4
 
5
5
  //#region src/type/validator/string-codec-aot.d.ts
@@ -1,3 +1,4 @@
1
+ // @bun
1
2
  import { schemaHasDangerousProperties } from "./clean-safe.mjs";
2
3
  import { hasProperty } from "../utils.mjs";
3
4
  import { collectStringCodecNodes } from "../../compile/aot-reconstruct.mjs";
@@ -75,24 +75,22 @@ function walk(value, key, mode, state) {
75
75
  }
76
76
  function walkObject(value, mode, state) {
77
77
  const keys = Object.keys(value);
78
- let serialized = "{";
79
- let first = true;
78
+ const parts = ["{"];
80
79
  for (let i = 0; i < keys.length; i++) {
81
80
  const key = keys[i];
82
81
  const child = value[key];
83
82
  const piece = walk(child, key, mode === CONTAINER ? NODE : mode === NODE ? childMode(key, child) : OFF, state);
84
83
  if (piece === void 0) continue;
85
84
  if (state.buildKey) {
86
- if (first) first = false;
87
- else serialized += ",";
88
- serialized += quote(key) + ":" + piece;
85
+ if (parts.length > 1) parts.push(",");
86
+ parts.push(quote(key), ":", piece);
89
87
  }
90
88
  }
91
- return serialized + "}";
89
+ parts.push("}");
90
+ return parts.join("");
92
91
  }
93
92
  function walkOptional(value, mode, state) {
94
- let serialized = "{";
95
- let first = true;
93
+ const parts = ["{"];
96
94
  let emittedOptional = false;
97
95
  for (const key in value) {
98
96
  const child = value[key];
@@ -100,28 +98,29 @@ function walkOptional(value, mode, state) {
100
98
  if (key === "~optional") emittedOptional = true;
101
99
  if (piece === void 0) continue;
102
100
  if (state.buildKey) {
103
- if (first) first = false;
104
- else serialized += ",";
105
- serialized += quote(key) + ":" + piece;
101
+ if (parts.length > 1) parts.push(",");
102
+ parts.push(quote(key), ":", piece);
106
103
  }
107
104
  }
108
105
  if (!emittedOptional && state.buildKey) {
109
- if (!first) serialized += ",";
110
- serialized += "\"~optional\":true";
106
+ if (parts.length > 1) parts.push(",");
107
+ parts.push("\"~optional\":true");
111
108
  }
112
- return serialized + "}";
109
+ parts.push("}");
110
+ return parts.join("");
113
111
  }
114
112
  function walkArray(value, mode, state) {
115
113
  const elementMode = mode === CONTAINER ? NODE : OFF;
116
- let serialized = "[";
114
+ const parts = ["["];
117
115
  for (let i = 0; i < value.length; i++) {
118
116
  const piece = walk(value[i], i, elementMode, state);
119
117
  if (state.buildKey) {
120
- if (i) serialized += ",";
121
- serialized += piece === void 0 ? "null" : piece;
118
+ if (i) parts.push(",");
119
+ parts.push(piece === void 0 ? "null" : piece);
122
120
  }
123
121
  }
124
- return serialized + "]";
122
+ parts.push("]");
123
+ return parts.join("");
125
124
  }
126
125
  function computeSchemaMeta(schema, forceKey) {
127
126
  const state = {
@@ -253,6 +252,7 @@ var TypeBoxValidatorCache = class TypeBoxValidatorCache {
253
252
  this.#referenceCache = /* @__PURE__ */ new WeakMap();
254
253
  TypeBoxValidatorCache.#lastSchema = void 0;
255
254
  TypeBoxValidatorCache.#lastMeta = void 0;
255
+ TypeBoxValidatorCache.#metaCache = /* @__PURE__ */ new WeakMap();
256
256
  require_type_coerce.deferCoercions();
257
257
  }
258
258
  };
@@ -1,3 +1,4 @@
1
+ // @bun
1
2
  import { isCloudflareWorker } from "../../universal/constants.mjs";
2
3
  import { evictOldestHalf, nullObject } from "../../utils.mjs";
3
4
  import { ELYSIA_TYPES } from "../constants.mjs";
@@ -74,24 +75,22 @@ function walk(value, key, mode, state) {
74
75
  }
75
76
  function walkObject(value, mode, state) {
76
77
  const keys = Object.keys(value);
77
- let serialized = "{";
78
- let first = true;
78
+ const parts = ["{"];
79
79
  for (let i = 0; i < keys.length; i++) {
80
80
  const key = keys[i];
81
81
  const child = value[key];
82
82
  const piece = walk(child, key, mode === CONTAINER ? NODE : mode === NODE ? childMode(key, child) : OFF, state);
83
83
  if (piece === void 0) continue;
84
84
  if (state.buildKey) {
85
- if (first) first = false;
86
- else serialized += ",";
87
- serialized += quote(key) + ":" + piece;
85
+ if (parts.length > 1) parts.push(",");
86
+ parts.push(quote(key), ":", piece);
88
87
  }
89
88
  }
90
- return serialized + "}";
89
+ parts.push("}");
90
+ return parts.join("");
91
91
  }
92
92
  function walkOptional(value, mode, state) {
93
- let serialized = "{";
94
- let first = true;
93
+ const parts = ["{"];
95
94
  let emittedOptional = false;
96
95
  for (const key in value) {
97
96
  const child = value[key];
@@ -99,28 +98,29 @@ function walkOptional(value, mode, state) {
99
98
  if (key === "~optional") emittedOptional = true;
100
99
  if (piece === void 0) continue;
101
100
  if (state.buildKey) {
102
- if (first) first = false;
103
- else serialized += ",";
104
- serialized += quote(key) + ":" + piece;
101
+ if (parts.length > 1) parts.push(",");
102
+ parts.push(quote(key), ":", piece);
105
103
  }
106
104
  }
107
105
  if (!emittedOptional && state.buildKey) {
108
- if (!first) serialized += ",";
109
- serialized += "\"~optional\":true";
106
+ if (parts.length > 1) parts.push(",");
107
+ parts.push("\"~optional\":true");
110
108
  }
111
- return serialized + "}";
109
+ parts.push("}");
110
+ return parts.join("");
112
111
  }
113
112
  function walkArray(value, mode, state) {
114
113
  const elementMode = mode === CONTAINER ? NODE : OFF;
115
- let serialized = "[";
114
+ const parts = ["["];
116
115
  for (let i = 0; i < value.length; i++) {
117
116
  const piece = walk(value[i], i, elementMode, state);
118
117
  if (state.buildKey) {
119
- if (i) serialized += ",";
120
- serialized += piece === void 0 ? "null" : piece;
118
+ if (i) parts.push(",");
119
+ parts.push(piece === void 0 ? "null" : piece);
121
120
  }
122
121
  }
123
- return serialized + "]";
122
+ parts.push("]");
123
+ return parts.join("");
124
124
  }
125
125
  function computeSchemaMeta(schema, forceKey) {
126
126
  const state = {
@@ -252,6 +252,7 @@ var TypeBoxValidatorCache = class TypeBoxValidatorCache {
252
252
  this.#referenceCache = /* @__PURE__ */ new WeakMap();
253
253
  TypeBoxValidatorCache.#lastSchema = void 0;
254
254
  TypeBoxValidatorCache.#lastMeta = void 0;
255
+ TypeBoxValidatorCache.#metaCache = /* @__PURE__ */ new WeakMap();
255
256
  deferCoercions();
256
257
  }
257
258
  };