elysia 2.0.0-exp.2 → 2.0.0-exp.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 (135) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +2 -0
  2. package/dist/adapter/bun/index.d.ts +2 -25
  3. package/dist/adapter/bun/index.js +18 -12
  4. package/dist/adapter/bun/index.mjs +19 -13
  5. package/dist/adapter/bun/router.js +1 -1
  6. package/dist/adapter/bun/router.mjs +1 -1
  7. package/dist/adapter/constants.d.ts +3 -26
  8. package/dist/adapter/index.d.ts +1 -26
  9. package/dist/adapter/index.js +1 -17
  10. package/dist/adapter/index.mjs +1 -17
  11. package/dist/adapter/types.d.ts +1 -0
  12. package/dist/adapter/utils.d.ts +3 -4
  13. package/dist/adapter/utils.js +83 -81
  14. package/dist/adapter/utils.mjs +82 -80
  15. package/dist/adapter/web-standard/handler.js +6 -3
  16. package/dist/adapter/web-standard/handler.mjs +6 -3
  17. package/dist/adapter/web-standard/index.d.ts +2 -26
  18. package/dist/adapter/web-standard/index.js +12 -1
  19. package/dist/adapter/web-standard/index.mjs +12 -1
  20. package/dist/base.d.ts +38 -68
  21. package/dist/base.js +133 -97
  22. package/dist/base.mjs +133 -97
  23. package/dist/compile/aot.d.ts +22 -1
  24. package/dist/compile/aot.js +22 -0
  25. package/dist/compile/aot.mjs +22 -0
  26. package/dist/compile/handler/index.d.ts +2 -2
  27. package/dist/compile/handler/index.js +85 -456
  28. package/dist/compile/handler/index.mjs +86 -457
  29. package/dist/compile/handler/jit.d.ts +35 -0
  30. package/dist/compile/handler/jit.js +445 -0
  31. package/dist/compile/handler/jit.mjs +443 -0
  32. package/dist/compile/handler/params.js +3 -2
  33. package/dist/compile/handler/params.mjs +4 -3
  34. package/dist/compile/handler/reconstruct.d.ts +13 -0
  35. package/dist/compile/handler/reconstruct.js +29 -0
  36. package/dist/compile/handler/reconstruct.mjs +28 -0
  37. package/dist/compile/handler/utils.d.ts +2 -1
  38. package/dist/compile/handler/utils.js +9 -3
  39. package/dist/compile/handler/utils.mjs +9 -4
  40. package/dist/compile/jit-probe.d.ts +19 -0
  41. package/dist/compile/jit-probe.js +38 -0
  42. package/dist/compile/jit-probe.mjs +36 -0
  43. package/dist/cookie/index.d.ts +4 -3
  44. package/dist/cookie/index.js +2 -1
  45. package/dist/cookie/index.mjs +2 -1
  46. package/dist/cookie/serialize.d.ts +6 -0
  47. package/dist/cookie/serialize.js +28 -0
  48. package/dist/cookie/serialize.mjs +27 -0
  49. package/dist/cookie/utils.d.ts +1 -2
  50. package/dist/cookie/utils.js +2 -23
  51. package/dist/cookie/utils.mjs +5 -25
  52. package/dist/handler/error.js +2 -2
  53. package/dist/handler/error.mjs +3 -3
  54. package/dist/handler/fetch.js +49 -42
  55. package/dist/handler/fetch.mjs +50 -43
  56. package/dist/index.d.ts +13 -8
  57. package/dist/index.js +11 -4
  58. package/dist/index.mjs +7 -6
  59. package/dist/parse-query.js +1 -1
  60. package/dist/parse-query.mjs +1 -1
  61. package/dist/plugin/bun.d.ts +10 -0
  62. package/dist/plugin/bun.js +18 -1
  63. package/dist/plugin/bun.mjs +19 -2
  64. package/dist/plugin/core.d.ts +61 -1
  65. package/dist/plugin/core.js +90 -10
  66. package/dist/plugin/core.mjs +90 -12
  67. package/dist/plugin/esbuild.d.ts +10 -0
  68. package/dist/plugin/esbuild.js +18 -1
  69. package/dist/plugin/esbuild.mjs +19 -2
  70. package/dist/plugin/source.d.ts +38 -1
  71. package/dist/plugin/source.js +104 -13
  72. package/dist/plugin/source.mjs +102 -14
  73. package/dist/plugin/vite.d.ts +7 -0
  74. package/dist/plugin/vite.js +22 -1
  75. package/dist/plugin/vite.mjs +23 -2
  76. package/dist/sucrose.js +23 -10
  77. package/dist/sucrose.mjs +23 -10
  78. package/dist/trace.d.ts +1 -1
  79. package/dist/trace.js +4 -6
  80. package/dist/trace.mjs +4 -6
  81. package/dist/type/bridge.d.ts +9 -8
  82. package/dist/type/coerce.d.ts +20 -2
  83. package/dist/type/coerce.js +110 -0
  84. package/dist/type/coerce.mjs +109 -2
  85. package/dist/type/compat.js +4 -3
  86. package/dist/type/compat.mjs +2 -1
  87. package/dist/type/constants.d.ts +1 -1
  88. package/dist/type/elysia/boolean-string.js +1 -1
  89. package/dist/type/elysia/boolean-string.mjs +1 -1
  90. package/dist/type/elysia/file-type.js +1 -1
  91. package/dist/type/elysia/file-type.mjs +1 -1
  92. package/dist/type/elysia/integer-string.js +1 -1
  93. package/dist/type/elysia/integer-string.mjs +1 -1
  94. package/dist/type/exports.js +29 -2059
  95. package/dist/type/exports.mjs +7 -295
  96. package/dist/type/index.d.ts +6 -2
  97. package/dist/type/index.js +4 -0
  98. package/dist/type/index.mjs +3 -1
  99. package/dist/type/types.d.ts +1 -1
  100. package/dist/type/utils.js +4 -4
  101. package/dist/type/utils.mjs +4 -4
  102. package/dist/type/validator/custom-error.d.ts +10 -0
  103. package/dist/type/validator/custom-error.js +113 -0
  104. package/dist/type/validator/custom-error.mjs +110 -0
  105. package/dist/type/validator/default-precompute.d.ts +22 -0
  106. package/dist/type/validator/default-precompute.js +476 -0
  107. package/dist/type/validator/default-precompute.mjs +465 -0
  108. package/dist/type/validator/frozen-check.d.ts +11 -0
  109. package/dist/type/validator/frozen-check.js +19 -0
  110. package/dist/type/validator/frozen-check.mjs +18 -0
  111. package/dist/type/{validator.d.ts → validator/index.d.ts} +7 -20
  112. package/dist/type/validator/index.js +572 -0
  113. package/dist/type/validator/index.mjs +567 -0
  114. package/dist/type/validator/string-codec-aot.d.ts +9 -0
  115. package/dist/type/validator/string-codec-aot.js +106 -0
  116. package/dist/type/validator/string-codec-aot.mjs +102 -0
  117. package/dist/type/validator/validator-cache.d.ts +21 -0
  118. package/dist/type/validator/validator-cache.js +163 -0
  119. package/dist/type/validator/validator-cache.mjs +161 -0
  120. package/dist/types.d.ts +22 -14
  121. package/dist/universal/file.d.ts +1 -1
  122. package/dist/universal/file.js +35 -29
  123. package/dist/universal/file.mjs +35 -29
  124. package/dist/utils.d.ts +12 -1
  125. package/dist/utils.js +89 -45
  126. package/dist/utils.mjs +88 -46
  127. package/dist/validator/index.d.ts +1 -1
  128. package/dist/validator/index.js +15 -2
  129. package/dist/validator/index.mjs +15 -2
  130. package/dist/validator/route.d.ts +0 -1
  131. package/dist/ws/route.js +47 -24
  132. package/dist/ws/route.mjs +48 -25
  133. package/package.json +10 -4
  134. package/dist/type/validator.js +0 -1033
  135. package/dist/type/validator.mjs +0 -1029
@@ -0,0 +1,102 @@
1
+ import { Capture, collectExternals, instantiateFrozenDecodeMirror } from "../../compile/aot.mjs";
2
+ import { ELYSIA_TYPES } from "../constants.mjs";
3
+ import { hasProperty } from "../utils.mjs";
4
+ import { buildFrozenCheck } from "./frozen-check.mjs";
5
+ import { Build, Compile } from "typebox/schema";
6
+ import createMirror from "exact-mirror";
7
+
8
+ //#region src/type/validator/string-codec-aot.ts
9
+ function collectStringCodecNodes(schema, out = []) {
10
+ if (!schema || typeof schema !== "object") return out;
11
+ const ely = schema["~elyTyp"];
12
+ if (ely === ELYSIA_TYPES.ObjectString || ely === ELYSIA_TYPES.ArrayString) {
13
+ const inner = schema.anyOf?.[0];
14
+ const codec = schema.anyOf?.[1];
15
+ if (inner && codec?.["~codec"] && codec["~refine"]) out.push({
16
+ inner,
17
+ codec,
18
+ open: ely === ELYSIA_TYPES.ObjectString ? 123 : 91
19
+ });
20
+ }
21
+ if (schema.properties) for (const k in schema.properties) collectStringCodecNodes(schema.properties[k], out);
22
+ const items = schema.items;
23
+ if (Array.isArray(items)) for (const it of items) collectStringCodecNodes(it, out);
24
+ else if (items) collectStringCodecNodes(items, out);
25
+ if (Array.isArray(schema.anyOf)) for (const b of schema.anyOf) collectStringCodecNodes(b, out);
26
+ return out;
27
+ }
28
+ function reconstructInnerCodecs(ic, schema) {
29
+ const nodes = collectStringCodecNodes(schema);
30
+ for (let i = nodes.length - 1; i >= 0; i--) {
31
+ const entry = ic[i];
32
+ const node = nodes[i];
33
+ if (!entry || !node) continue;
34
+ const innerSchema = node.inner;
35
+ const innerCheck = entry.c(entry.e ? collectExternals(innerSchema) : []);
36
+ const innerMirror = entry.d.x ? instantiateFrozenDecodeMirror(entry.d, innerSchema) : entry.d.s;
37
+ const open = entry.o;
38
+ node.codec["~refine"][0].check = (v) => {
39
+ if (v.charCodeAt(0) !== open) return false;
40
+ try {
41
+ return innerCheck(JSON.parse(v));
42
+ } catch {
43
+ return false;
44
+ }
45
+ };
46
+ node.codec["~codec"].decode = (v) => innerMirror(JSON.parse(v));
47
+ }
48
+ }
49
+ function captureInnerCodec(inner, open, sanitize) {
50
+ let cf;
51
+ try {
52
+ cf = buildFrozenCheck(Build(inner), inner);
53
+ if (!cf) return;
54
+ } catch {
55
+ return;
56
+ }
57
+ let decode;
58
+ try {
59
+ const emitted = createMirror(inner, {
60
+ Compile,
61
+ sanitize,
62
+ decode: true,
63
+ emit: true
64
+ });
65
+ if (typeof emitted?.source !== "string") return;
66
+ const ext = emitted.externals;
67
+ if (ext?.hof) return;
68
+ if (ext?.codecs && !Capture.mirrorCodecs(inner, ext.codecs)) return;
69
+ let u;
70
+ if (ext?.unions && ext.unions.length) {
71
+ u = Capture.mirrorUnions(inner, ext.unions);
72
+ if (!u) return;
73
+ }
74
+ decode = {
75
+ source: emitted.source,
76
+ hasExternals: !!(ext?.codecs || u),
77
+ u
78
+ };
79
+ } catch {
80
+ return;
81
+ }
82
+ if (hasProperty("default", inner)) return;
83
+ return {
84
+ open,
85
+ ...cf,
86
+ decode
87
+ };
88
+ }
89
+ function captureStringCodecEntries(schema, sanitize) {
90
+ const stringCodecs = collectStringCodecNodes(schema);
91
+ if (!stringCodecs.length) return;
92
+ const entries = [];
93
+ for (const { inner, open } of stringCodecs) {
94
+ const entry = captureInnerCodec(inner, open, sanitize);
95
+ if (!entry) break;
96
+ entries.push(entry);
97
+ }
98
+ return entries.length === stringCodecs.length ? entries : void 0;
99
+ }
100
+
101
+ //#endregion
102
+ export { captureStringCodecEntries, reconstructInnerCodecs };
@@ -0,0 +1,21 @@
1
+ import { CoerceOption } from "../coerce.js";
2
+ import { TSchema } from "typebox/type";
3
+ import * as _$typebox_schema0 from "typebox/schema";
4
+ import { Validator } from "typebox/schema";
5
+
6
+ //#region src/type/validator/validator-cache.d.ts
7
+ declare class TypeBoxValidatorCache {
8
+ #private;
9
+ private static EMPTY;
10
+ private static ignoreKeys;
11
+ private static fnIds;
12
+ private static nextFnId;
13
+ private static fnKey;
14
+ static ignoreMeta(k: string, v: unknown): any;
15
+ constructor(gcTime: number);
16
+ get(schema: TSchema, coercions?: CoerceOption[] | typeof TypeBoxValidatorCache.EMPTY, normalize?: string): Validator<_$typebox_schema0.XSchema, unknown> | undefined;
17
+ set(schema: TSchema, coercions?: CoerceOption[] | typeof TypeBoxValidatorCache.EMPTY, validator?: Validator, normalize?: string): void;
18
+ clear(): void;
19
+ }
20
+ //#endregion
21
+ export { TypeBoxValidatorCache };
@@ -0,0 +1,163 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_runtime = require('../../_virtual/_rolldown/runtime.js');
3
+ const require_universal_constants = require('../../universal/constants.js');
4
+ const require_utils = require('../../utils.js');
5
+ const require_type_constants = require('../constants.js');
6
+ const require_type_coerce = require('../coerce.js');
7
+ let typebox_value = require("typebox/value");
8
+
9
+ //#region src/type/validator/validator-cache.ts
10
+ const DEFAULT_CACHE_LIMIT = 1024;
11
+ const DEFAULT_GC_TIME = 60 * 1e3;
12
+ var TypeBoxValidatorCache = class TypeBoxValidatorCache {
13
+ static {
14
+ this.EMPTY = require_utils.nullObject();
15
+ }
16
+ static {
17
+ this.ignoreKeys = new Set([
18
+ "title",
19
+ "description",
20
+ "tags",
21
+ "examples",
22
+ "defaultValue"
23
+ ]);
24
+ }
25
+ static {
26
+ this.fnIds = /* @__PURE__ */ new WeakMap();
27
+ }
28
+ static {
29
+ this.nextFnId = 0;
30
+ }
31
+ static fnKey(fn) {
32
+ let id = TypeBoxValidatorCache.fnIds.get(fn);
33
+ if (id === void 0) {
34
+ id = ++TypeBoxValidatorCache.nextFnId;
35
+ TypeBoxValidatorCache.fnIds.set(fn, id);
36
+ }
37
+ return `<fn:${id}>`;
38
+ }
39
+ static ignoreMeta(k, v) {
40
+ if (TypeBoxValidatorCache.ignoreKeys.has(k)) return;
41
+ if (typeof v === "function") return TypeBoxValidatorCache.fnKey(v);
42
+ if (v && typeof v === "object" && v["~optional"] === true) {
43
+ const out = require_utils.nullObject();
44
+ for (const key in v) out[key] = v[key];
45
+ out["~optional"] = true;
46
+ return out;
47
+ }
48
+ return v;
49
+ }
50
+ static #isOpaqueType(schema, seen = /* @__PURE__ */ new WeakSet()) {
51
+ if (!schema || typeof schema !== "object" || seen.has(schema)) return false;
52
+ seen.add(schema);
53
+ if (schema["~refine"] || schema["~elyTyp"] === require_type_constants.ELYSIA_TYPES.NoValidate) return true;
54
+ const props = schema.properties;
55
+ if (props) {
56
+ for (const k in props) if (TypeBoxValidatorCache.#isOpaqueType(props[k], seen)) return true;
57
+ }
58
+ const items = schema.items;
59
+ if (Array.isArray(items)) {
60
+ for (const it of items) if (TypeBoxValidatorCache.#isOpaqueType(it, seen)) return true;
61
+ } else if (items && TypeBoxValidatorCache.#isOpaqueType(items, seen)) return true;
62
+ for (const k of [
63
+ "anyOf",
64
+ "allOf",
65
+ "oneOf"
66
+ ]) {
67
+ const arr = schema[k];
68
+ if (Array.isArray(arr)) {
69
+ for (const x of arr) if (TypeBoxValidatorCache.#isOpaqueType(x, seen)) return true;
70
+ }
71
+ }
72
+ if (schema.additionalProperties && typeof schema.additionalProperties === "object" && TypeBoxValidatorCache.#isOpaqueType(schema.additionalProperties, seen)) return true;
73
+ if (schema.not && TypeBoxValidatorCache.#isOpaqueType(schema.not, seen)) return true;
74
+ const pp = schema.patternProperties;
75
+ if (pp) {
76
+ for (const k in pp) if (TypeBoxValidatorCache.#isOpaqueType(pp[k], seen)) return true;
77
+ }
78
+ return false;
79
+ }
80
+ #cache = /* @__PURE__ */ new Map();
81
+ #referenceCache = /* @__PURE__ */ new WeakMap();
82
+ #gc;
83
+ #gcTime;
84
+ #lastSchema;
85
+ #lastMeta;
86
+ #meta(schema) {
87
+ if (this.#lastSchema === schema && this.#lastMeta) return this.#lastMeta;
88
+ const special = (0, typebox_value.HasCodec)(schema) || TypeBoxValidatorCache.#isOpaqueType(schema);
89
+ const meta = {
90
+ special,
91
+ key: special ? "" : JSON.stringify(schema, TypeBoxValidatorCache.ignoreMeta)
92
+ };
93
+ this.#lastSchema = schema;
94
+ this.#lastMeta = meta;
95
+ return meta;
96
+ }
97
+ constructor(gcTime) {
98
+ this.#gcTime = gcTime;
99
+ }
100
+ #scheduleClear() {
101
+ if (require_universal_constants.isCloudflareWorker) return;
102
+ if (this.#gc) clearTimeout(this.#gc);
103
+ this.#gc = setTimeout(() => this.clear(), this.#gcTime ?? DEFAULT_GC_TIME);
104
+ this.#gc.unref?.();
105
+ }
106
+ get(schema, coercions = TypeBoxValidatorCache.EMPTY, normalize = "") {
107
+ const refBucket = this.#referenceCache.get(schema)?.get(normalize);
108
+ if (refBucket?.has(coercions)) return refBucket.get(coercions);
109
+ const meta = this.#meta(schema);
110
+ if (meta.special) return;
111
+ const key = meta.key + "\0" + normalize;
112
+ if (this.#cache.has(key)) {
113
+ const coercionsCache = this.#cache.get(key);
114
+ this.#cache.delete(key);
115
+ this.#cache.set(key, coercionsCache);
116
+ if (coercionsCache.has(coercions)) return coercionsCache.get(coercions);
117
+ }
118
+ }
119
+ #refBucket(schema) {
120
+ let byNormalize = this.#referenceCache.get(schema);
121
+ if (!byNormalize) {
122
+ byNormalize = /* @__PURE__ */ new Map();
123
+ this.#referenceCache.set(schema, byNormalize);
124
+ }
125
+ return byNormalize;
126
+ }
127
+ set(schema, coercions = TypeBoxValidatorCache.EMPTY, validator, normalize = "") {
128
+ this.#scheduleClear();
129
+ const meta = this.#meta(schema);
130
+ if (meta.special) {
131
+ const cache = (/* @__PURE__ */ new WeakMap()).set(coercions, validator);
132
+ this.#refBucket(schema).set(normalize, cache);
133
+ return;
134
+ }
135
+ const key = meta.key + "\0" + normalize;
136
+ if (this.#cache.has(key)) {
137
+ const cache = this.#cache.get(key).set(coercions, validator);
138
+ const byNormalize = this.#refBucket(schema);
139
+ if (byNormalize.has(normalize)) byNormalize.get(normalize).set(coercions, validator);
140
+ else byNormalize.set(normalize, cache);
141
+ return;
142
+ }
143
+ if (this.#cache.size >= DEFAULT_CACHE_LIMIT) {
144
+ const oldest = this.#cache.keys().next().value;
145
+ if (oldest !== void 0) this.#cache.delete(oldest);
146
+ }
147
+ const cache = (/* @__PURE__ */ new WeakMap()).set(coercions, validator);
148
+ this.#cache.set(key, cache);
149
+ this.#refBucket(schema).set(normalize, cache);
150
+ }
151
+ clear() {
152
+ if (this.#gc) {
153
+ clearTimeout(this.#gc);
154
+ this.#gc = void 0;
155
+ }
156
+ this.#cache.clear();
157
+ this.#referenceCache = /* @__PURE__ */ new WeakMap();
158
+ require_type_coerce.deferCoercions();
159
+ }
160
+ };
161
+
162
+ //#endregion
163
+ exports.TypeBoxValidatorCache = TypeBoxValidatorCache;
@@ -0,0 +1,161 @@
1
+ import { isCloudflareWorker } from "../../universal/constants.mjs";
2
+ import { nullObject } from "../../utils.mjs";
3
+ import { ELYSIA_TYPES } from "../constants.mjs";
4
+ import { deferCoercions } from "../coerce.mjs";
5
+ import { HasCodec } from "typebox/value";
6
+
7
+ //#region src/type/validator/validator-cache.ts
8
+ const DEFAULT_CACHE_LIMIT = 1024;
9
+ const DEFAULT_GC_TIME = 60 * 1e3;
10
+ var TypeBoxValidatorCache = class TypeBoxValidatorCache {
11
+ static {
12
+ this.EMPTY = nullObject();
13
+ }
14
+ static {
15
+ this.ignoreKeys = new Set([
16
+ "title",
17
+ "description",
18
+ "tags",
19
+ "examples",
20
+ "defaultValue"
21
+ ]);
22
+ }
23
+ static {
24
+ this.fnIds = /* @__PURE__ */ new WeakMap();
25
+ }
26
+ static {
27
+ this.nextFnId = 0;
28
+ }
29
+ static fnKey(fn) {
30
+ let id = TypeBoxValidatorCache.fnIds.get(fn);
31
+ if (id === void 0) {
32
+ id = ++TypeBoxValidatorCache.nextFnId;
33
+ TypeBoxValidatorCache.fnIds.set(fn, id);
34
+ }
35
+ return `<fn:${id}>`;
36
+ }
37
+ static ignoreMeta(k, v) {
38
+ if (TypeBoxValidatorCache.ignoreKeys.has(k)) return;
39
+ if (typeof v === "function") return TypeBoxValidatorCache.fnKey(v);
40
+ if (v && typeof v === "object" && v["~optional"] === true) {
41
+ const out = nullObject();
42
+ for (const key in v) out[key] = v[key];
43
+ out["~optional"] = true;
44
+ return out;
45
+ }
46
+ return v;
47
+ }
48
+ static #isOpaqueType(schema, seen = /* @__PURE__ */ new WeakSet()) {
49
+ if (!schema || typeof schema !== "object" || seen.has(schema)) return false;
50
+ seen.add(schema);
51
+ if (schema["~refine"] || schema["~elyTyp"] === ELYSIA_TYPES.NoValidate) return true;
52
+ const props = schema.properties;
53
+ if (props) {
54
+ for (const k in props) if (TypeBoxValidatorCache.#isOpaqueType(props[k], seen)) return true;
55
+ }
56
+ const items = schema.items;
57
+ if (Array.isArray(items)) {
58
+ for (const it of items) if (TypeBoxValidatorCache.#isOpaqueType(it, seen)) return true;
59
+ } else if (items && TypeBoxValidatorCache.#isOpaqueType(items, seen)) return true;
60
+ for (const k of [
61
+ "anyOf",
62
+ "allOf",
63
+ "oneOf"
64
+ ]) {
65
+ const arr = schema[k];
66
+ if (Array.isArray(arr)) {
67
+ for (const x of arr) if (TypeBoxValidatorCache.#isOpaqueType(x, seen)) return true;
68
+ }
69
+ }
70
+ if (schema.additionalProperties && typeof schema.additionalProperties === "object" && TypeBoxValidatorCache.#isOpaqueType(schema.additionalProperties, seen)) return true;
71
+ if (schema.not && TypeBoxValidatorCache.#isOpaqueType(schema.not, seen)) return true;
72
+ const pp = schema.patternProperties;
73
+ if (pp) {
74
+ for (const k in pp) if (TypeBoxValidatorCache.#isOpaqueType(pp[k], seen)) return true;
75
+ }
76
+ return false;
77
+ }
78
+ #cache = /* @__PURE__ */ new Map();
79
+ #referenceCache = /* @__PURE__ */ new WeakMap();
80
+ #gc;
81
+ #gcTime;
82
+ #lastSchema;
83
+ #lastMeta;
84
+ #meta(schema) {
85
+ if (this.#lastSchema === schema && this.#lastMeta) return this.#lastMeta;
86
+ const special = HasCodec(schema) || TypeBoxValidatorCache.#isOpaqueType(schema);
87
+ const meta = {
88
+ special,
89
+ key: special ? "" : JSON.stringify(schema, TypeBoxValidatorCache.ignoreMeta)
90
+ };
91
+ this.#lastSchema = schema;
92
+ this.#lastMeta = meta;
93
+ return meta;
94
+ }
95
+ constructor(gcTime) {
96
+ this.#gcTime = gcTime;
97
+ }
98
+ #scheduleClear() {
99
+ if (isCloudflareWorker) return;
100
+ if (this.#gc) clearTimeout(this.#gc);
101
+ this.#gc = setTimeout(() => this.clear(), this.#gcTime ?? DEFAULT_GC_TIME);
102
+ this.#gc.unref?.();
103
+ }
104
+ get(schema, coercions = TypeBoxValidatorCache.EMPTY, normalize = "") {
105
+ const refBucket = this.#referenceCache.get(schema)?.get(normalize);
106
+ if (refBucket?.has(coercions)) return refBucket.get(coercions);
107
+ const meta = this.#meta(schema);
108
+ if (meta.special) return;
109
+ const key = meta.key + "\0" + normalize;
110
+ if (this.#cache.has(key)) {
111
+ const coercionsCache = this.#cache.get(key);
112
+ this.#cache.delete(key);
113
+ this.#cache.set(key, coercionsCache);
114
+ if (coercionsCache.has(coercions)) return coercionsCache.get(coercions);
115
+ }
116
+ }
117
+ #refBucket(schema) {
118
+ let byNormalize = this.#referenceCache.get(schema);
119
+ if (!byNormalize) {
120
+ byNormalize = /* @__PURE__ */ new Map();
121
+ this.#referenceCache.set(schema, byNormalize);
122
+ }
123
+ return byNormalize;
124
+ }
125
+ set(schema, coercions = TypeBoxValidatorCache.EMPTY, validator, normalize = "") {
126
+ this.#scheduleClear();
127
+ const meta = this.#meta(schema);
128
+ if (meta.special) {
129
+ const cache = (/* @__PURE__ */ new WeakMap()).set(coercions, validator);
130
+ this.#refBucket(schema).set(normalize, cache);
131
+ return;
132
+ }
133
+ const key = meta.key + "\0" + normalize;
134
+ if (this.#cache.has(key)) {
135
+ const cache = this.#cache.get(key).set(coercions, validator);
136
+ const byNormalize = this.#refBucket(schema);
137
+ if (byNormalize.has(normalize)) byNormalize.get(normalize).set(coercions, validator);
138
+ else byNormalize.set(normalize, cache);
139
+ return;
140
+ }
141
+ if (this.#cache.size >= DEFAULT_CACHE_LIMIT) {
142
+ const oldest = this.#cache.keys().next().value;
143
+ if (oldest !== void 0) this.#cache.delete(oldest);
144
+ }
145
+ const cache = (/* @__PURE__ */ new WeakMap()).set(coercions, validator);
146
+ this.#cache.set(key, cache);
147
+ this.#refBucket(schema).set(normalize, cache);
148
+ }
149
+ clear() {
150
+ if (this.#gc) {
151
+ clearTimeout(this.#gc);
152
+ this.#gc = void 0;
153
+ }
154
+ this.#cache.clear();
155
+ this.#referenceCache = /* @__PURE__ */ new WeakMap();
156
+ deferCoercions();
157
+ }
158
+ };
159
+
160
+ //#endregion
161
+ export { TypeBoxValidatorCache };
package/dist/types.d.ts CHANGED
@@ -4,14 +4,14 @@ import { CookieOptions } from "./cookie/types.js";
4
4
  import { ElysiaFile } from "./universal/file.js";
5
5
  import { TraceEvent, TraceListener } from "./trace.js";
6
6
  import { Serve } from "./universal/server.js";
7
- import { ElysiaAdapter } from "./adapter/index.js";
8
7
  import { AnySchema, StandardSchemaV1Like, TypeBoxSchema } from "./type/types.js";
9
8
  import { ChainNode } from "./utils.js";
10
9
  import { Context, ErrorContext, LifecycleContext, PreContext } from "./context.js";
11
10
  import { WebSocketHandler } from "./ws/types.js";
12
11
  import { AnyElysia, Elysia } from "./base.js";
13
- import { Instruction } from "exact-mirror";
12
+ import { ElysiaAdapter } from "./adapter/index.js";
14
13
  import { Static, StaticDecode, StaticEncode, TIntersect, TObject, TSchema } from "typebox";
14
+ import { Instruction } from "exact-mirror";
15
15
  import { OpenAPIV3 } from "openapi-types";
16
16
 
17
17
  //#region src/types.d.ts
@@ -83,6 +83,12 @@ interface ElysiaConfig<in out Prefix extends string | undefined, in out Scope ex
83
83
  * @default false
84
84
  */
85
85
  strictPath?: boolean;
86
+ /**
87
+ * Whether should Elysia handle distinction between overlapping path
88
+ *
89
+ * @default false
90
+ */
91
+ distinctPath?: boolean;
86
92
  /**
87
93
  * Automatically register a HEAD handler for every GET route, deriving the
88
94
  * response headers (e.g. `content-length`) from the GET handler while
@@ -736,6 +742,18 @@ type MacroDefSchema<K, MBody, MHeaders, MQuery, MParams, MCookie> = {
736
742
  cookie: AsMacroSchemaField<K extends keyof MCookie ? MCookie[K] : undefined>;
737
743
  response: undefined;
738
744
  };
745
+ /**
746
+ * Upper bound for a macro definition's schema channel (`body`/`headers`/…):
747
+ * a registered model name or an inline schema.
748
+ *
749
+ * Used as the `const Body extends …` constraint on `.macro()`. It does not
750
+ * restrict (valid inputs already satisfy it) — it stops `Body[K]` from being a
751
+ * bare `unknown`, which is what lets the `| Name` in the field surface model
752
+ * names to autocomplete (a `unknown | Name` union collapses to `unknown`).
753
+ * `const` still narrows `Body[K]` to the typed literal for `UnwrapRoute`.
754
+ */
755
+ type MacroSchemaChannel<Definitions extends DefinitionBase> = Record<keyof any, AnySchema | (keyof Definitions['typebox'] & string)>;
756
+ type MacroChannel<Channel, Key extends keyof InputSchema, Definitions extends DefinitionBase> = { [K in keyof Channel]: MaybeValueOrVoidFunction<{ [F in Key]?: Channel[K] | (keyof Definitions['typebox'] & string) } & Record<string, unknown>> };
739
757
  /**
740
758
  * Parameter type of the object-form `.macro({ name: definition })`
741
759
  *
@@ -748,17 +766,7 @@ type MacroDefSchema<K, MBody, MHeaders, MQuery, MParams, MCookie> = {
748
766
  * still flow into `N` (the verbatim definitions, stored in
749
767
  * `Metadata['macroFn']` for the consuming route)
750
768
  */
751
- type ObjectMacroDefs<Body, Headers, Query, Params, Cookie, N, AmbientSchema extends RouteSchema, ScopedSchemas extends RouteSchema, Singleton extends SingletonBase, Definitions extends DefinitionBase, MacroNames extends BaseMacro> = { [K in keyof Body]: MaybeValueOrVoidFunction<{
752
- body?: Body[K];
753
- }> } & { [K in keyof Headers]: MaybeValueOrVoidFunction<{
754
- headers?: Headers[K];
755
- }> } & { [K in keyof Query]: MaybeValueOrVoidFunction<{
756
- query?: Query[K];
757
- }> } & { [K in keyof Params]: MaybeValueOrVoidFunction<{
758
- params?: Params[K];
759
- }> } & { [K in keyof Cookie]: MaybeValueOrVoidFunction<{
760
- cookie?: Cookie[K];
761
- }> } & { [K in keyof N]: MaybeValueOrVoidFunction<MacroProperty<MacroNames & InputSchema<keyof Definitions['typebox'] & string>, IntersectIfObjectSchema<MergeSchema<UnwrapMacroSchema<MacroDefSchema<K, Body, Headers, Query, Params, Cookie>, Definitions['typebox']>, AmbientSchema>, ScopedSchemas>, Singleton, Definitions['error']>> } & { [K in keyof N]: N[K] extends ((...a: any[]) => any) ? unknown : string extends keyof N[K] ? unknown : { [P in Exclude<keyof N[K], MacroPropertyKey | InputSchemaKey | keyof MacroNames | keyof N>]: `Unknown macro property '${P & string}'` } } & N;
769
+ type ObjectMacroDefs<Body, Headers, Query, Params, Cookie, N, AmbientSchema extends RouteSchema, ScopedSchemas extends RouteSchema, Singleton extends SingletonBase, Definitions extends DefinitionBase, MacroNames extends BaseMacro> = MacroChannel<Body, 'body', Definitions> & MacroChannel<Headers, 'headers', Definitions> & MacroChannel<Query, 'query', Definitions> & MacroChannel<Params, 'params', Definitions> & MacroChannel<Cookie, 'cookie', Definitions> & { [K in keyof N]: MaybeValueOrVoidFunction<MacroProperty<MacroNames & InputSchema<keyof Definitions['typebox'] & string>, IntersectIfObjectSchema<MergeSchema<UnwrapMacroSchema<MacroDefSchema<K, Body, Headers, Query, Params, Cookie>, Definitions['typebox']>, AmbientSchema>, ScopedSchemas>, Singleton, Definitions['error']>> } & { [K in keyof N]: N[K] extends ((...a: any[]) => any) ? unknown : string extends keyof N[K] ? unknown : { [P in Exclude<keyof N[K], MacroPropertyKey | InputSchemaKey | keyof MacroNames | keyof N>]: `Unknown macro property '${P & string}'` } } & N;
762
770
  type CreateEden<Path extends string, Property extends Record<string, unknown> = {}> = Path extends `/${infer Rest}` ? _CreateEden<Rest, Property> : Path extends '' | '/' ? Property : _CreateEden<Path, Property>;
763
771
  type _CreateEden<Path extends string, Property extends Record<string, unknown> = {}> = Path extends `${infer Start}/${infer Rest}` ? { [x in Start]: _CreateEden<Rest, Property> } : Path extends '' ? Property : { [x in Path]: Property };
764
772
  type CreateEdenResponse<Path extends string, Schema extends RouteSchema, MacroContext extends RouteSchema, Res extends PossibleResponse, Err extends Error = never> = RouteSchema extends MacroContext ? {
@@ -877,4 +885,4 @@ type AddWSRoute<BasePath extends string, Scope extends EventScope, Singleton ext
877
885
  subscribe: CreateWSEdenResponse<Path, Schema, MacroContext, ComposeElysiaResponse<Schema & MacroContext & Metadata['schemas'] & Ephemeral['schemas'] & Volatile['schemas'], Response, UnionResponseStatus<Metadata['response'], UnionResponseStatus<Ephemeral['response'], UnionResponseStatus<Volatile['response'], MacroContext['return'] & {}>>>, [...Definitions['error'], ...Ephemeral['error'], ...Volatile['error']]>>;
878
886
  }>, Ephemeral, Volatile>;
879
887
  //#endregion
880
- export { AddRoute, AddWSRoute, AfterHandler, AfterResponseHandler, AnyErrorConstructor, AnyLocalHook, AnyWSLocalHook, AppEvent, AppHook, BaseMacro, BodyHandler, BunHTMLBundlelike, CompiledHandler, ComposeElysiaResponse, ContentType, ContextAppendType, CreateEden, CreateEdenResponse, CreateWSEdenResponse, DefaultEphemeral, DefaultMetadata, DefaultSingleton, DefinitionBase, DocumentDecoration, ElysiaConfig, ElysiaFormData, ElysiaHandlerToResponseSchema, ElysiaHandlerToResponseSchemaAmbiguous, ElysiaHandlerToResponseSchemas, EmptyInputSchema, EphemeralType, Equal, ErrorDefinition, ErrorDefinitionEntry, ErrorHandler, ErrorHandlerResponseSchema, EventFn, EventScope, ExcludeElysiaResponse, ExtractErrorFromHandle, ExtractReturnedError, GetPathParameter, GracefulHandler, GuardLocalHook, GuardSchemaType, HTTPHeaders, HTTPMethod, Handler, InlineHandler, InlineHandlerNonMacro, InlineHandlerResponse, InlineResponse, InlineSchemaResponse, InputSchema, InputSchemaKey, InternalRoute, IntersectIfObject, IntersectIfObjectSchema, IsAny, IsNever, IsTuple, IsUnknown, JoinPath, LocalHook, Macro, MacroProperty, MacroPropertyKey, MacroToContext, MacroToProperty, MapResponse, MaybeArray, MaybePromise, MaybeValueOrVoidFunction, MergeElysiaInstances, MergeSchema, MergeScopedSchemas, MetadataBase, NonResolvableMacroKey, ObjectMacroDefs, OptionalHandler, PossibleResponse, PreHandler, Prettify, PublicRoute, Replace, ResolveHandler, ResolvePath, ResolveRouteErrors, RouteBase, RouteSchema, SSEPayload, SingletonBase, TraceHandler, TransformHandler, UnhandledReturnedError, UnhandledReturnedErrorOf, UnionResponseStatus, UnionToIntersect, UnwrapArray, UnwrapBodySchema, UnwrapMacroSchema, UnwrapRoute, UnwrapSchema, ValueOrFunctionToResponseSchema, ValueToResponseSchema, VoidHandler, WrapFn };
888
+ export { AddRoute, AddWSRoute, AfterHandler, AfterResponseHandler, AnyErrorConstructor, AnyLocalHook, type AnySchema, AnyWSLocalHook, AppEvent, AppHook, BaseMacro, BodyHandler, BunHTMLBundlelike, CompiledHandler, ComposeElysiaResponse, ContentType, ContextAppendType, CreateEden, CreateEdenResponse, CreateWSEdenResponse, DefaultEphemeral, DefaultMetadata, DefaultSingleton, DefinitionBase, DocumentDecoration, ElysiaConfig, ElysiaFormData, ElysiaHandlerToResponseSchema, ElysiaHandlerToResponseSchemaAmbiguous, ElysiaHandlerToResponseSchemas, EmptyInputSchema, EphemeralType, Equal, ErrorDefinition, ErrorDefinitionEntry, ErrorHandler, ErrorHandlerResponseSchema, EventFn, EventScope, ExcludeElysiaResponse, ExtractErrorFromHandle, ExtractReturnedError, GetPathParameter, GracefulHandler, GuardLocalHook, GuardSchemaType, HTTPHeaders, HTTPMethod, Handler, InlineHandler, InlineHandlerNonMacro, InlineHandlerResponse, InlineResponse, InlineSchemaResponse, InputSchema, InputSchemaKey, InternalRoute, IntersectIfObject, IntersectIfObjectSchema, IsAny, IsNever, IsTuple, IsUnknown, JoinPath, LocalHook, Macro, MacroProperty, MacroPropertyKey, MacroSchemaChannel, MacroToContext, MacroToProperty, MapResponse, MaybeArray, MaybePromise, MaybeValueOrVoidFunction, MergeElysiaInstances, MergeSchema, MergeScopedSchemas, MetadataBase, NonResolvableMacroKey, ObjectMacroDefs, OptionalHandler, PossibleResponse, PreHandler, Prettify, PublicRoute, Replace, ResolveHandler, ResolvePath, ResolveRouteErrors, RouteBase, RouteSchema, SSEPayload, SingletonBase, type StandardSchemaV1Like, TraceHandler, TransformHandler, type TypeBoxSchema, UnhandledReturnedError, UnhandledReturnedErrorOf, UnionResponseStatus, UnionToIntersect, UnwrapArray, UnwrapBodySchema, UnwrapMacroSchema, UnwrapRoute, UnwrapSchema, ValueOrFunctionToResponseSchema, ValueToResponseSchema, VoidHandler, WrapFn };
@@ -36,7 +36,7 @@ declare const mime: {
36
36
  readonly ppt: "application/vnd.ms-powerpoint";
37
37
  readonly pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation";
38
38
  };
39
- declare const getFileExtension: (path: string) => string;
39
+ declare function getFileExtension(path: string): string;
40
40
  declare const file: (path: string) => ElysiaFile;
41
41
  declare class ElysiaFile {
42
42
  path: string;
@@ -2,22 +2,26 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_universal_constants = require('./constants.js');
3
3
 
4
4
  //#region src/universal/file.ts
5
+ const text = "text/";
6
+ const application = "application/";
7
+ const image = "image/";
8
+ const msft365 = "application/vnd.openxmlformats-officedocument.";
5
9
  const mime = {
6
- html: "text/html",
7
- htm: "text/html",
8
- css: "text/css",
9
- js: "application/javascript",
10
- ts: "application/typescript",
11
- json: "application/json",
12
- xml: "application/xml",
13
- jpg: "image/jpeg",
14
- jpeg: "image/jpeg",
15
- png: "image/png",
16
- gif: "image/gif",
17
- webp: "image/webp",
18
- avif: "image/avif",
19
- svg: "image/svg+xml",
20
- ico: "image/x-icon",
10
+ html: `${text}html`,
11
+ htm: `${text}html`,
12
+ css: `${text}css`,
13
+ js: `${application}javascript`,
14
+ ts: `${application}typescript`,
15
+ json: `${application}json`,
16
+ xml: `${application}xml`,
17
+ jpg: `${image}jpeg`,
18
+ jpeg: `${image}jpeg`,
19
+ png: `${image}png`,
20
+ gif: `${image}gif`,
21
+ webp: `${image}webp`,
22
+ avif: `${image}avif`,
23
+ svg: `${image}svg+xml`,
24
+ ico: `${image}x-icon`,
21
25
  mp4: "video/mp4",
22
26
  webm: "video/webm",
23
27
  mp3: "audio/mpeg",
@@ -26,26 +30,28 @@ const mime = {
26
30
  woff2: "font/woff2",
27
31
  ttf: "font/ttf",
28
32
  otf: "font/otf",
29
- pdf: "application/pdf",
30
- txt: "text/plain",
31
- csv: "text/csv",
32
- zip: "application/zip",
33
- doc: "application/msword",
34
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
35
- xls: "application/vnd.ms-excel",
36
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
37
- ppt: "application/vnd.ms-powerpoint",
38
- pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
33
+ pdf: `${application}pdf`,
34
+ txt: `${text}plain`,
35
+ csv: `${text}csv`,
36
+ zip: `${application}zip`,
37
+ doc: `${application}msword`,
38
+ docx: `${msft365}wordprocessingml.document`,
39
+ xls: `${application}vnd.ms-excel`,
40
+ xlsx: `${msft365}spreadsheetml.sheet`,
41
+ ppt: `${application}vnd.ms-powerpoint`,
42
+ pptx: `${msft365}presentationml.presentation`
39
43
  };
40
- const getFileExtension = (path) => {
44
+ function getFileExtension(path) {
41
45
  const index = path.lastIndexOf(".");
42
46
  if (index === -1) return "";
43
- return path.slice(index + 1);
44
- };
47
+ return path.slice(index + 1).toLowerCase();
48
+ }
45
49
  const file = (path) => new ElysiaFile(path);
46
50
  let createReadStream;
47
51
  let stat;
48
- const warnMissing = (name) => console.warn(/* @__PURE__ */ new Error(`[elysia] \`file\` require \`fs${name ? "." + name : ""}\` ${name?.includes(".") ? "module " : ""}which is not available in this environment`));
52
+ function warnMissing(name) {
53
+ console.warn(/* @__PURE__ */ new Error(`[Elysia] \`file\` require \`fs${name ? "." + name : ""}\` ${name?.includes(".") ? "module " : ""}which is not available in this environment`));
54
+ }
49
55
  var ElysiaFile = class {
50
56
  constructor(path) {
51
57
  this.path = path;