elysia 2.0.0-beta.2 → 2.0.0-beta.3

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 (145) hide show
  1. package/dist/adapter/utils.js +3 -3
  2. package/dist/adapter/utils.mjs +4 -4
  3. package/dist/adapter/web-standard/handler.js +5 -2
  4. package/dist/adapter/web-standard/handler.mjs +5 -2
  5. package/dist/base.d.ts +2 -2
  6. package/dist/base.js +42 -27
  7. package/dist/base.mjs +43 -28
  8. package/dist/compile/aot.d.ts +4 -4
  9. package/dist/compile/aot.js +14 -9
  10. package/dist/compile/aot.mjs +15 -9
  11. package/dist/compile/handler/descriptor.js +1 -1
  12. package/dist/compile/handler/descriptor.mjs +1 -1
  13. package/dist/compile/handler/index.d.ts +2 -2
  14. package/dist/compile/handler/index.js +6 -4
  15. package/dist/compile/handler/index.mjs +6 -4
  16. package/dist/compile/handler/utils.js +2 -2
  17. package/dist/compile/handler/utils.mjs +3 -3
  18. package/dist/context.js +3 -4
  19. package/dist/context.mjs +3 -4
  20. package/dist/cookie/config.d.ts +1 -0
  21. package/dist/cookie/config.js +3 -2
  22. package/dist/cookie/config.mjs +3 -2
  23. package/dist/cookie/cookie.d.ts +1 -0
  24. package/dist/cookie/cookie.js +6 -5
  25. package/dist/cookie/cookie.mjs +6 -5
  26. package/dist/cookie/crypto.d.ts +8 -7
  27. package/dist/cookie/crypto.js +38 -31
  28. package/dist/cookie/crypto.mjs +38 -32
  29. package/dist/cookie/error.js +1 -2
  30. package/dist/cookie/error.mjs +1 -2
  31. package/dist/cookie/lib.js +5 -1
  32. package/dist/cookie/lib.mjs +5 -1
  33. package/dist/cookie/serialize.js +1 -1
  34. package/dist/cookie/serialize.mjs +1 -1
  35. package/dist/cookie/types.d.ts +10 -0
  36. package/dist/cookie/utils.js +28 -14
  37. package/dist/cookie/utils.mjs +29 -15
  38. package/dist/handler/error.d.ts +23 -12
  39. package/dist/handler/error.js +24 -21
  40. package/dist/handler/error.mjs +20 -21
  41. package/dist/handler/fetch.js +6 -7
  42. package/dist/handler/fetch.mjs +7 -8
  43. package/dist/handler/utils.js +4 -2
  44. package/dist/handler/utils.mjs +5 -3
  45. package/dist/index.js +1 -8
  46. package/dist/package.js +1 -1
  47. package/dist/package.mjs +1 -1
  48. package/dist/plugin/aot/core.d.ts +22 -1
  49. package/dist/plugin/aot/core.js +35 -3
  50. package/dist/plugin/aot/core.mjs +35 -3
  51. package/dist/route-table.js +12 -10
  52. package/dist/route-table.mjs +12 -10
  53. package/dist/type/bridge-live.d.ts +1 -1
  54. package/dist/type/bridge-live.js +1 -1
  55. package/dist/type/bridge-live.mjs +1 -1
  56. package/dist/type/bridge.d.ts +1 -1
  57. package/dist/type/coerce-plan.js +3 -4
  58. package/dist/type/coerce-plan.mjs +1 -1
  59. package/dist/type/compat.d.ts +3 -0
  60. package/dist/type/compat.js +32 -14
  61. package/dist/type/compat.mjs +27 -8
  62. package/dist/type/elysia/array-buffer.js +2 -3
  63. package/dist/type/elysia/array-buffer.mjs +1 -1
  64. package/dist/type/elysia/array-string.js +7 -4
  65. package/dist/type/elysia/array-string.mjs +9 -5
  66. package/dist/type/elysia/boolean-string.js +2 -3
  67. package/dist/type/elysia/boolean-string.mjs +1 -1
  68. package/dist/type/elysia/boolean.js +4 -3
  69. package/dist/type/elysia/boolean.mjs +4 -2
  70. package/dist/type/elysia/cookie.js +2 -1
  71. package/dist/type/elysia/cookie.mjs +2 -1
  72. package/dist/type/elysia/date.js +7 -7
  73. package/dist/type/elysia/date.mjs +3 -2
  74. package/dist/type/elysia/file-type.d.ts +9 -2
  75. package/dist/type/elysia/file-type.js +16 -1
  76. package/dist/type/elysia/file-type.mjs +16 -2
  77. package/dist/type/elysia/file.js +8 -4
  78. package/dist/type/elysia/file.mjs +8 -3
  79. package/dist/type/elysia/files.js +6 -4
  80. package/dist/type/elysia/files.mjs +5 -2
  81. package/dist/type/elysia/form.js +2 -3
  82. package/dist/type/elysia/form.mjs +3 -3
  83. package/dist/type/elysia/integer-string.js +4 -5
  84. package/dist/type/elysia/integer-string.mjs +3 -3
  85. package/dist/type/elysia/integer.js +4 -3
  86. package/dist/type/elysia/integer.mjs +4 -2
  87. package/dist/type/elysia/maybe-empty.js +3 -4
  88. package/dist/type/elysia/maybe-empty.mjs +1 -1
  89. package/dist/type/elysia/nullable.js +2 -3
  90. package/dist/type/elysia/nullable.mjs +1 -1
  91. package/dist/type/elysia/number.js +4 -3
  92. package/dist/type/elysia/number.mjs +4 -2
  93. package/dist/type/elysia/numeric-enum.js +2 -3
  94. package/dist/type/elysia/numeric-enum.mjs +1 -1
  95. package/dist/type/elysia/numeric.js +5 -5
  96. package/dist/type/elysia/numeric.mjs +3 -2
  97. package/dist/type/elysia/object-string.js +7 -4
  98. package/dist/type/elysia/object-string.mjs +9 -5
  99. package/dist/type/elysia/string.js +4 -3
  100. package/dist/type/elysia/string.mjs +4 -2
  101. package/dist/type/elysia/uint8-array.js +2 -3
  102. package/dist/type/elysia/uint8-array.mjs +1 -1
  103. package/dist/type/elysia/union-enum.js +2 -3
  104. package/dist/type/elysia/union-enum.mjs +1 -1
  105. package/dist/type/elysia/utils.js +2 -3
  106. package/dist/type/elysia/utils.mjs +1 -1
  107. package/dist/type/exports.js +10 -1
  108. package/dist/type/exports.mjs +7 -0
  109. package/dist/type/index.d.ts +9 -1
  110. package/dist/type/index.js +41 -13
  111. package/dist/type/index.mjs +44 -9
  112. package/dist/type/typebox-type-live.d.ts +9 -0
  113. package/dist/type/typebox-type-live.js +31 -0
  114. package/dist/type/typebox-type-live.mjs +16 -0
  115. package/dist/type/typebox-type.d.ts +24 -0
  116. package/dist/type/typebox-type.js +130 -0
  117. package/dist/type/typebox-type.mjs +66 -0
  118. package/dist/type/typebox-value-live.d.ts +9 -0
  119. package/dist/type/typebox-value-live.js +27 -0
  120. package/dist/type/typebox-value-live.mjs +11 -0
  121. package/dist/type/typebox-value.d.ts +30 -0
  122. package/dist/type/typebox-value.js +147 -0
  123. package/dist/type/typebox-value.mjs +62 -0
  124. package/dist/type/validator/custom-error.js +4 -5
  125. package/dist/type/validator/custom-error.mjs +3 -3
  126. package/dist/type/validator/default-precompute.js +4 -5
  127. package/dist/type/validator/default-precompute.mjs +1 -1
  128. package/dist/type/validator/index.js +41 -35
  129. package/dist/type/validator/index.mjs +23 -16
  130. package/dist/type/validator/validator-cache.js +10 -5
  131. package/dist/type/validator/validator-cache.mjs +10 -4
  132. package/dist/universal/constants.d.ts +2 -1
  133. package/dist/universal/constants.js +3 -1
  134. package/dist/universal/constants.mjs +2 -1
  135. package/dist/utils.d.ts +10 -1
  136. package/dist/utils.js +18 -3
  137. package/dist/utils.mjs +14 -3
  138. package/dist/validator/index.js +2 -1
  139. package/dist/validator/index.mjs +2 -1
  140. package/dist/ws/context.d.ts +4 -0
  141. package/dist/ws/context.js +44 -26
  142. package/dist/ws/context.mjs +44 -26
  143. package/dist/ws/route.js +126 -23
  144. package/dist/ws/route.mjs +128 -25
  145. package/package.json +4 -2
@@ -198,10 +198,10 @@ function resolveChainNode(root, node) {
198
198
  }
199
199
  return resolved;
200
200
  }
201
- const chainResolver = (root) => {
201
+ function chainResolver(root) {
202
202
  const frozenRoot = require_generation.frozenRootOf(root);
203
203
  return frozenRoot["~ext"]?.macro || frozenRoot["~scopeChildren"] ? (node) => resolveChainNode(root, node) : void 0;
204
- };
204
+ }
205
205
  const localMacroRoot = (instance, root) => instance !== root && instance["~scopeChild"] === true && require_generation.frozenRootOf(instance)["~ext"]?.macro ? instance : root;
206
206
  function composeRootHook(root, inheritedChain) {
207
207
  const resolve = chainResolver(root);
@@ -211,7 +211,8 @@ function composeRootHook(root, inheritedChain) {
211
211
  if (!locals) return inherited;
212
212
  return require_utils.mergeHook(inherited, locals);
213
213
  }
214
- function buildNativeStaticResponse([, , handler, instance, localHook, appHook, inheritedChain, macroScope], root) {
214
+ function buildNativeStaticResponse(route, root) {
215
+ const [, , handler, instance, localHook, appHook, inheritedChain, macroScope] = route;
215
216
  if (typeof handler === "function" || handler instanceof Error || handler instanceof Promise) return;
216
217
  const frozenRoot = require_generation.frozenRootOf(root);
217
218
  const adapter = frozenRoot["~config"]?.adapter ?? require_adapter_constants.defaultAdapter;
@@ -273,7 +274,8 @@ function isContextFreeHandler(handler) {
273
274
  const source = Function.prototype.toString.call(handler);
274
275
  return isBareArrow.test(source) && !isSucroseOpaque.test(source);
275
276
  }
276
- function compileHandler([_method, path, handler, instance, localHook, appHook, inheritedChain, macroScope], root, precomputedStatic) {
277
+ function compileHandler(route, root, precomputedStatic) {
278
+ let [_method, path, handler, instance, localHook, appHook, inheritedChain, macroScope] = route;
277
279
  const frozenRoot = require_generation.frozenRootOf(root);
278
280
  const adapter = frozenRoot["~config"]?.adapter ?? require_adapter_constants.defaultAdapter;
279
281
  const method = _method;
@@ -197,10 +197,10 @@ function resolveChainNode(root, node) {
197
197
  }
198
198
  return resolved;
199
199
  }
200
- const chainResolver = (root) => {
200
+ function chainResolver(root) {
201
201
  const frozenRoot = frozenRootOf(root);
202
202
  return frozenRoot["~ext"]?.macro || frozenRoot["~scopeChildren"] ? (node) => resolveChainNode(root, node) : void 0;
203
- };
203
+ }
204
204
  const localMacroRoot = (instance, root) => instance !== root && instance["~scopeChild"] === true && frozenRootOf(instance)["~ext"]?.macro ? instance : root;
205
205
  function composeRootHook(root, inheritedChain) {
206
206
  const resolve = chainResolver(root);
@@ -210,7 +210,8 @@ function composeRootHook(root, inheritedChain) {
210
210
  if (!locals) return inherited;
211
211
  return mergeHook(inherited, locals);
212
212
  }
213
- function buildNativeStaticResponse([, , handler, instance, localHook, appHook, inheritedChain, macroScope], root) {
213
+ function buildNativeStaticResponse(route, root) {
214
+ const [, , handler, instance, localHook, appHook, inheritedChain, macroScope] = route;
214
215
  if (typeof handler === "function" || handler instanceof Error || handler instanceof Promise) return;
215
216
  const frozenRoot = frozenRootOf(root);
216
217
  const adapter = frozenRoot["~config"]?.adapter ?? defaultAdapter;
@@ -272,7 +273,8 @@ function isContextFreeHandler(handler) {
272
273
  const source = Function.prototype.toString.call(handler);
273
274
  return isBareArrow.test(source) && !isSucroseOpaque.test(source);
274
275
  }
275
- function compileHandler([_method, path, handler, instance, localHook, appHook, inheritedChain, macroScope], root, precomputedStatic) {
276
+ function compileHandler(route, root, precomputedStatic) {
277
+ let [_method, path, handler, instance, localHook, appHook, inheritedChain, macroScope] = route;
276
278
  const frozenRoot = frozenRootOf(root);
277
279
  const adapter = frozenRoot["~config"]?.adapter ?? defaultAdapter;
278
280
  const method = _method;
@@ -60,7 +60,7 @@ function extractDeriveKeys(fn) {
60
60
  }
61
61
  function replaceDeriveContext(context, derivative) {
62
62
  const next = Object.create(Object.getPrototypeOf(context));
63
- Object.assign(next, derivative);
63
+ require_utils.assignOwn(next, derivative);
64
64
  next.request = context.request;
65
65
  next["~sig"] = context["~sig"];
66
66
  next["~afterResponse"] = context["~afterResponse"];
@@ -334,7 +334,7 @@ function mapBeforeHandle(_hooks, derive, link, isAsync, report, abortGuard) {
334
334
  code += "if(tmp instanceof es)_r=tmp\nelse if(tmp){if(typeof tmp==='object'||typeof tmp==='function')c=rdc(c,tmp);tmp=undefined}\n";
335
335
  } else {
336
336
  const keys = extractDeriveKeys(fn);
337
- const merge = keys && keys.length ? keys.map((k) => `c[${JSON.stringify(k)}]=tmp[${JSON.stringify(k)}]`).join(";") : "Object.assign(c,tmp)";
337
+ const merge = keys && keys.length && !keys.includes("__proto__") ? keys.map((k) => `c[${JSON.stringify(k)}]=tmp[${JSON.stringify(k)}]`).join(";") : "Object.hasOwn(tmp,'__proto__')?Object.defineProperties(c,Object.getOwnPropertyDescriptors(tmp)):Object.assign(c,tmp)";
338
338
  code += `if(tmp instanceof es)_r=tmp
339
339
  else if(tmp){${merge};tmp=undefined}\n`;
340
340
  }
@@ -1,4 +1,4 @@
1
- import { deriveEntryFn, isMapDeriveEntry } from "../../utils.mjs";
1
+ import { assignOwn, deriveEntryFn, isMapDeriveEntry } from "../../utils.mjs";
2
2
  import { ELYSIA_TYPES } from "../../type/constants.mjs";
3
3
  import { skipClone } from "../../adapter/skip-clone.mjs";
4
4
  import { ElysiaStatus } from "../../error.mjs";
@@ -59,7 +59,7 @@ function extractDeriveKeys(fn) {
59
59
  }
60
60
  function replaceDeriveContext(context, derivative) {
61
61
  const next = Object.create(Object.getPrototypeOf(context));
62
- Object.assign(next, derivative);
62
+ assignOwn(next, derivative);
63
63
  next.request = context.request;
64
64
  next["~sig"] = context["~sig"];
65
65
  next["~afterResponse"] = context["~afterResponse"];
@@ -333,7 +333,7 @@ function mapBeforeHandle(_hooks, derive, link, isAsync, report, abortGuard) {
333
333
  code += "if(tmp instanceof es)_r=tmp\nelse if(tmp){if(typeof tmp==='object'||typeof tmp==='function')c=rdc(c,tmp);tmp=undefined}\n";
334
334
  } else {
335
335
  const keys = extractDeriveKeys(fn);
336
- const merge = keys && keys.length ? keys.map((k) => `c[${JSON.stringify(k)}]=tmp[${JSON.stringify(k)}]`).join(";") : "Object.assign(c,tmp)";
336
+ const merge = keys && keys.length && !keys.includes("__proto__") ? keys.map((k) => `c[${JSON.stringify(k)}]=tmp[${JSON.stringify(k)}]`).join(";") : "Object.hasOwn(tmp,'__proto__')?Object.defineProperties(c,Object.getOwnPropertyDescriptors(tmp)):Object.assign(c,tmp)";
337
337
  code += `if(tmp instanceof es)_r=tmp
338
338
  else if(tmp){${merge};tmp=undefined}\n`;
339
339
  }
package/dist/context.js CHANGED
@@ -46,7 +46,6 @@ function clearContextCache() {
46
46
  sharedEmptyDecorator = null;
47
47
  sharedEmptyContext = null;
48
48
  }
49
- const pathValue = Symbol("path");
50
49
  function buildEmptyContext(Base, headers = null, warnPathMutation = false) {
51
50
  const immutableHeaders = headers !== null && Object.isFrozen(headers);
52
51
  let warnedPathMutation = false;
@@ -54,14 +53,14 @@ function buildEmptyContext(Base, headers = null, warnPathMutation = false) {
54
53
  enumerable: true,
55
54
  configurable: true,
56
55
  get() {
57
- return this[pathValue];
56
+ return this["~path"];
58
57
  },
59
58
  set(value) {
60
- if (pathValue in this && !warnedPathMutation) {
59
+ if ("~path" in this && !warnedPathMutation) {
61
60
  warnedPathMutation = true;
62
61
  console.warn("[elysia] context.path is readonly; request-hook rerouting will stop working in a future release.");
63
62
  }
64
- this[pathValue] = value;
63
+ this["~path"] = value;
65
64
  }
66
65
  } : void 0;
67
66
  class Context extends Base {
package/dist/context.mjs CHANGED
@@ -45,7 +45,6 @@ function clearContextCache() {
45
45
  sharedEmptyDecorator = null;
46
46
  sharedEmptyContext = null;
47
47
  }
48
- const pathValue = Symbol("path");
49
48
  function buildEmptyContext(Base, headers = null, warnPathMutation = false) {
50
49
  const immutableHeaders = headers !== null && Object.isFrozen(headers);
51
50
  let warnedPathMutation = false;
@@ -53,14 +52,14 @@ function buildEmptyContext(Base, headers = null, warnPathMutation = false) {
53
52
  enumerable: true,
54
53
  configurable: true,
55
54
  get() {
56
- return this[pathValue];
55
+ return this["~path"];
57
56
  },
58
57
  set(value) {
59
- if (pathValue in this && !warnedPathMutation) {
58
+ if ("~path" in this && !warnedPathMutation) {
60
59
  warnedPathMutation = true;
61
60
  console.warn("[elysia] context.path is readonly; request-hook rerouting will stop working in a future release.");
62
61
  }
63
- this[pathValue] = value;
62
+ this["~path"] = value;
64
63
  }
65
64
  } : void 0;
66
65
  class Context extends Base {
@@ -18,6 +18,7 @@ interface CompiledCookieConfig {
18
18
  globalSecrets: string | null | (string | null)[] | undefined;
19
19
  hasSign: boolean;
20
20
  verify: 'lazy' | 'eager';
21
+ legacySignature: boolean;
21
22
  }
22
23
  declare function compileCookieConfig(routeSchema: AnySchema | undefined, appConfig: AppCookieConfig | undefined): CompiledCookieConfig;
23
24
  declare function resolveSignSecrets(name: string, config: CompiledCookieConfig): CompiledCookieConfig['globalSecrets'] | undefined;
@@ -31,7 +31,7 @@ function normalizeSign(sign) {
31
31
  if (Array.isArray(sign)) return sign.length ? sign : void 0;
32
32
  return [sign];
33
33
  }
34
- const hasUsableSecret = (secrets) => secrets == null ? false : Array.isArray(secrets) ? secrets.some((s) => s != null) : true;
34
+ const hasUsableSecret = (secrets) => Array.isArray(secrets) ? secrets.some((s) => !!s?.trim()) : !!secrets?.trim();
35
35
  function compileCookieConfig(routeSchema, appConfig) {
36
36
  const routeConfig = routeSchema?.config ?? void 0;
37
37
  const appAttributes = getAttributes(appConfig);
@@ -74,7 +74,8 @@ function compileCookieConfig(routeSchema, appConfig) {
74
74
  globalSignSet: Array.isArray(globalSign) ? new Set(globalSign) : void 0,
75
75
  globalSecrets,
76
76
  hasSign,
77
- verify: appConfig?.verify ?? "lazy"
77
+ verify: appConfig?.verify ?? "lazy",
78
+ legacySignature: (routeConfig?.legacySignature ?? appConfig?.legacySignature) !== false
78
79
  };
79
80
  }
80
81
  function resolveSignSecrets(name, config) {
@@ -30,7 +30,7 @@ function normalizeSign(sign) {
30
30
  if (Array.isArray(sign)) return sign.length ? sign : void 0;
31
31
  return [sign];
32
32
  }
33
- const hasUsableSecret = (secrets) => secrets == null ? false : Array.isArray(secrets) ? secrets.some((s) => s != null) : true;
33
+ const hasUsableSecret = (secrets) => Array.isArray(secrets) ? secrets.some((s) => !!s?.trim()) : !!secrets?.trim();
34
34
  function compileCookieConfig(routeSchema, appConfig) {
35
35
  const routeConfig = routeSchema?.config ?? void 0;
36
36
  const appAttributes = getAttributes(appConfig);
@@ -73,7 +73,8 @@ function compileCookieConfig(routeSchema, appConfig) {
73
73
  globalSignSet: Array.isArray(globalSign) ? new Set(globalSign) : void 0,
74
74
  globalSecrets,
75
75
  hasSign,
76
- verify: appConfig?.verify ?? "lazy"
76
+ verify: appConfig?.verify ?? "lazy",
77
+ legacySignature: (routeConfig?.legacySignature ?? appConfig?.legacySignature) !== false
77
78
  };
78
79
  }
79
80
  function resolveSignSecrets(name, config) {
@@ -10,6 +10,7 @@ declare class Cookie<T = any> implements BaseCookie {
10
10
  constructor(name: string, setRef: {
11
11
  cookie?: Record<string, BaseCookie>;
12
12
  }, initial?: Partial<BaseCookie>);
13
+ static isCookie(v: unknown): v is Cookie;
13
14
  get cookie(): BaseCookie;
14
15
  set cookie(jar: BaseCookie);
15
16
  protected get setCookie(): BaseCookie;
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_utils = require('../utils.js');
2
3
  const require_cookie_crypto = require('./crypto.js');
3
4
 
4
5
  //#region src/cookie/cookie.ts
@@ -23,6 +24,9 @@ var Cookie = class {
23
24
  this.#setRef = setRef;
24
25
  this.#initial = initial;
25
26
  }
27
+ static isCookie(v) {
28
+ return typeof v === "object" && v !== null && #name in v;
29
+ }
26
30
  get #jar() {
27
31
  return this.#setRef.cookie ??= Object.create(null);
28
32
  }
@@ -56,7 +60,7 @@ var Cookie = class {
56
60
  set value(value) {
57
61
  if (this.cookie.value === value && (!value || typeof value !== "object")) return;
58
62
  const j = this.#jar;
59
- if (!(this.#name in j)) j[this.#name] = { ...this.#initial };
63
+ if (!(this.#name in j)) j[this.#name] = Object.assign(require_utils.nullObject(), this.#initial);
60
64
  j[this.#name].value = value;
61
65
  }
62
66
  update(config) {
@@ -66,10 +70,7 @@ var Cookie = class {
66
70
  return this;
67
71
  }
68
72
  set(config) {
69
- const cookie = Object.assign({
70
- ...this.#initial,
71
- value: this.value
72
- }, typeof config === "function" ? config(this.cookie) : config);
73
+ const cookie = Object.assign(require_utils.nullObject(), this.#initial, { value: this.value }, typeof config === "function" ? config(this.cookie) : config);
73
74
  delete cookie["~raw"];
74
75
  this.setCookie = cookie;
75
76
  return this;
@@ -1,3 +1,4 @@
1
+ import { nullObject } from "../utils.mjs";
1
2
  import { resolvePendingCookie } from "./crypto.mjs";
2
3
 
3
4
  //#region src/cookie/cookie.ts
@@ -22,6 +23,9 @@ var Cookie = class {
22
23
  this.#setRef = setRef;
23
24
  this.#initial = initial;
24
25
  }
26
+ static isCookie(v) {
27
+ return typeof v === "object" && v !== null && #name in v;
28
+ }
25
29
  get #jar() {
26
30
  return this.#setRef.cookie ??= Object.create(null);
27
31
  }
@@ -55,7 +59,7 @@ var Cookie = class {
55
59
  set value(value) {
56
60
  if (this.cookie.value === value && (!value || typeof value !== "object")) return;
57
61
  const j = this.#jar;
58
- if (!(this.#name in j)) j[this.#name] = { ...this.#initial };
62
+ if (!(this.#name in j)) j[this.#name] = Object.assign(nullObject(), this.#initial);
59
63
  j[this.#name].value = value;
60
64
  }
61
65
  update(config) {
@@ -65,10 +69,7 @@ var Cookie = class {
65
69
  return this;
66
70
  }
67
71
  set(config) {
68
- const cookie = Object.assign({
69
- ...this.#initial,
70
- value: this.value
71
- }, typeof config === "function" ? config(this.cookie) : config);
72
+ const cookie = Object.assign(nullObject(), this.#initial, { value: this.value }, typeof config === "function" ? config(this.cookie) : config);
72
73
  delete cookie["~raw"];
73
74
  this.setCookie = cookie;
74
75
  return this;
@@ -7,14 +7,15 @@ declare const signCookieSyncImpl: (val: string, secret: string) => string;
7
7
  declare const keyCache: Map<string, Promise<CryptoKey>>;
8
8
  declare function importSecretKey(secret: string): Promise<CryptoKey>;
9
9
  declare function signCookieSubtle(val: string, secret: string): Promise<string>;
10
- declare function signCookie(val: string, secret: string | null): Promise<string>;
11
- declare function signCookieSync(val: string, secret: string | null): string;
12
- declare function unsignCookie(input: string, secret: string | null): Promise<string | false>;
13
- declare function unsignCookieSync(input: string, secret: string | null): string | false;
14
- declare function unsignWithSecretsSync(name: string, value: unknown, secrets: string | null | (string | null)[] | undefined): string;
15
- declare function unsignWithSecrets(name: string, value: unknown, secrets: string | null | (string | null)[] | undefined): Promise<string>;
10
+ declare const deriveSignKey: (secret: string, name: string) => string;
11
+ declare function signCookie(val: string, secret: string | null, name?: string): Promise<string>;
12
+ declare function signCookieSync(val: string, secret: string | null, name?: string): string;
13
+ declare function unsignCookie(input: string, secret: string | null, name?: string): Promise<string | false>;
14
+ declare function unsignCookieSync(input: string, secret: string | null, name?: string): string | false;
15
+ declare function unsignWithSecretsSync(name: string, value: unknown, secrets: string | null | (string | null)[] | undefined, legacy?: boolean): string;
16
+ declare function unsignWithSecrets(name: string, value: unknown, secrets: string | null | (string | null)[] | undefined, legacy?: boolean): Promise<string>;
16
17
  declare const rawJsonValue: WeakMap<object, string>;
17
18
  declare function maybeJsonDecode(value: unknown): any;
18
19
  declare function resolvePendingCookie(entry: Record<string, any>, name: string): void;
19
20
  //#endregion
20
- export { hasSyncHmac, hmacProvider, importSecretKey, keyCache, maybeJsonDecode, rawJsonValue, resolvePendingCookie, signCookie, signCookieBun, signCookieNode, signCookieSubtle, signCookieSync, signCookieSyncImpl, unsignCookie, unsignCookieSync, unsignWithSecrets, unsignWithSecretsSync };
21
+ export { deriveSignKey, hasSyncHmac, hmacProvider, importSecretKey, keyCache, maybeJsonDecode, rawJsonValue, resolvePendingCookie, signCookie, signCookieBun, signCookieNode, signCookieSubtle, signCookieSync, signCookieSyncImpl, unsignCookie, unsignCookieSync, unsignWithSecrets, unsignWithSecretsSync };
@@ -20,12 +20,11 @@ function nodeCrypto() {
20
20
  }
21
21
  return _nodeCrypto;
22
22
  }
23
- const HMAC_PROBE_DIGEST = "bzs6y9cVmkYub8fplSKaOuuqMqJlDwhMypFT/jSdCEk=";
24
23
  const bunCryptoHasher = (() => {
25
24
  const hasher = globalThis.Bun?.CryptoHasher;
26
25
  if (typeof hasher !== "function") return void 0;
27
26
  try {
28
- return new hasher("sha256", "elysia").update("probe").digest("base64") === HMAC_PROBE_DIGEST ? hasher : void 0;
27
+ return new hasher("sha256", "elysia").update("probe").digest("base64") === "bzs6y9cVmkYub8fplSKaOuuqMqJlDwhMypFT/jSdCEk=" ? hasher : void 0;
29
28
  } catch {
30
29
  return;
31
30
  }
@@ -62,19 +61,22 @@ async function signCookieSubtle(val, secret) {
62
61
  const hmacBuffer = await crypto.subtle.sign("HMAC", await importSecretKey(secret), encoder.encode(val));
63
62
  return `${val}.${btoa(String.fromCharCode(...new Uint8Array(hmacBuffer))).replace(removeTrailingEquals, "")}`;
64
63
  }
65
- async function signCookie(val, secret) {
64
+ const deriveSignKey = (secret, name) => `${name.length}\0${name}${secret}`;
65
+ async function signCookie(val, secret, name) {
66
66
  val = coerceValue(val);
67
- if (secret === null || secret === void 0) throw new TypeError("Secret key must be provided");
67
+ if (!secret?.trim()) throw new TypeError("Secret key must be provided");
68
+ if (name !== void 0) secret = deriveSignKey(secret, name);
68
69
  if (hasSyncHmac) return signCookieSyncImpl(val, secret);
69
70
  return signCookieSubtle(val, secret);
70
71
  }
71
- function signCookieSync(val, secret) {
72
+ function signCookieSync(val, secret, name) {
72
73
  val = coerceValue(val);
73
- if (secret === null || secret === void 0) throw new TypeError("Secret key must be provided");
74
+ if (!secret?.trim()) throw new TypeError("Secret key must be provided");
74
75
  if (!hasSyncHmac) throw new Error("signCookieSync called without a sync HMAC available");
76
+ if (name !== void 0) secret = deriveSignKey(secret, name);
75
77
  return signCookieSyncImpl(val, secret);
76
78
  }
77
- async function unsignCookie(input, secret) {
79
+ async function unsignCookie(input, secret, name) {
78
80
  if (typeof input !== "string") throw new TypeError("Signed cookie string must be provided.");
79
81
  const dot = input.lastIndexOf(".");
80
82
  if (dot === -1) {
@@ -82,10 +84,10 @@ async function unsignCookie(input, secret) {
82
84
  return false;
83
85
  }
84
86
  const tentativeValue = input.slice(0, dot);
85
- if (secret === null) return false;
86
- return require_utils.constantTimeEqual(await signCookie(tentativeValue, secret), input) ? tentativeValue : false;
87
+ if (!secret?.trim()) return false;
88
+ return require_utils.constantTimeEqual(await signCookie(tentativeValue, secret, name), input) ? tentativeValue : false;
87
89
  }
88
- function unsignCookieSync(input, secret) {
90
+ function unsignCookieSync(input, secret, name) {
89
91
  if (typeof input !== "string") throw new TypeError("Signed cookie string must be provided.");
90
92
  const dot = input.lastIndexOf(".");
91
93
  if (dot === -1) {
@@ -93,32 +95,36 @@ function unsignCookieSync(input, secret) {
93
95
  return false;
94
96
  }
95
97
  const tentativeValue = input.slice(0, dot);
96
- if (secret === null) return false;
97
- return require_utils.constantTimeEqual(signCookieSync(tentativeValue, secret), input) ? tentativeValue : false;
98
+ if (!secret?.trim()) return false;
99
+ return require_utils.constantTimeEqual(signCookieSync(tentativeValue, secret, name), input) ? tentativeValue : false;
98
100
  }
99
- function unsignWithSecretsSync(name, value, secrets) {
101
+ function unsignWithSecretsSync(name, value, secrets, legacy) {
100
102
  if (typeof value !== "string") throw require_cookie_error.InvalidCookie.signature(name);
101
- if (typeof secrets === "string") {
102
- const temp = unsignCookieSync(value, secrets);
103
- if (temp === false) throw require_cookie_error.InvalidCookie.signature(name);
104
- return temp;
105
- }
106
- if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
107
- const temp = unsignCookieSync(value, secrets[i]);
108
- if (temp !== false) return temp;
103
+ for (let pass = 0; pass < 2; pass++) {
104
+ const bound = pass === 0 ? name : void 0;
105
+ if (typeof secrets === "string") {
106
+ const temp = unsignCookieSync(value, secrets, bound);
107
+ if (temp !== false) return temp;
108
+ } else if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
109
+ const temp = unsignCookieSync(value, secrets[i], bound);
110
+ if (temp !== false) return temp;
111
+ }
112
+ if (!legacy) break;
109
113
  }
110
114
  throw require_cookie_error.InvalidCookie.signature(name);
111
115
  }
112
- async function unsignWithSecrets(name, value, secrets) {
116
+ async function unsignWithSecrets(name, value, secrets, legacy) {
113
117
  if (typeof value !== "string") throw require_cookie_error.InvalidCookie.signature(name);
114
- if (typeof secrets === "string") {
115
- const temp = await unsignCookie(value, secrets);
116
- if (temp === false) throw require_cookie_error.InvalidCookie.signature(name);
117
- return temp;
118
- }
119
- if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
120
- const temp = await unsignCookie(value, secrets[i]);
121
- if (temp !== false) return temp;
118
+ for (let pass = 0; pass < 2; pass++) {
119
+ const bound = pass === 0 ? name : void 0;
120
+ if (typeof secrets === "string") {
121
+ const temp = await unsignCookie(value, secrets, bound);
122
+ if (temp !== false) return temp;
123
+ } else if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
124
+ const temp = await unsignCookie(value, secrets[i], bound);
125
+ if (temp !== false) return temp;
126
+ }
127
+ if (!legacy) break;
122
128
  }
123
129
  throw require_cookie_error.InvalidCookie.signature(name);
124
130
  }
@@ -139,7 +145,7 @@ function resolvePendingCookie(entry, name) {
139
145
  const value = entry.value;
140
146
  if (typeof value !== "string") throw require_cookie_error.InvalidCookie.signature(name);
141
147
  if (!hasSyncHmac) throw new Error(`resolvePendingCookie called without sync HMAC. Unreachable under correct lane gating (cookie: "${name}")`);
142
- const resolvedValue = maybeJsonDecode(unsignWithSecretsSync(name, value, entry["~unsign"]));
148
+ const resolvedValue = maybeJsonDecode(unsignWithSecretsSync(name, value, entry["~unsign"], !entry["~strict"]));
143
149
  entry.value = resolvedValue;
144
150
  if (resolvedValue !== null && typeof resolvedValue === "object") {
145
151
  const raw = rawJsonValue.get(resolvedValue);
@@ -149,6 +155,7 @@ function resolvePendingCookie(entry, name) {
149
155
  }
150
156
 
151
157
  //#endregion
158
+ exports.deriveSignKey = deriveSignKey;
152
159
  exports.hasSyncHmac = hasSyncHmac;
153
160
  exports.hmacProvider = hmacProvider;
154
161
  exports.importSecretKey = importSecretKey;
@@ -19,12 +19,11 @@ function nodeCrypto() {
19
19
  }
20
20
  return _nodeCrypto;
21
21
  }
22
- const HMAC_PROBE_DIGEST = "bzs6y9cVmkYub8fplSKaOuuqMqJlDwhMypFT/jSdCEk=";
23
22
  const bunCryptoHasher = (() => {
24
23
  const hasher = globalThis.Bun?.CryptoHasher;
25
24
  if (typeof hasher !== "function") return void 0;
26
25
  try {
27
- return new hasher("sha256", "elysia").update("probe").digest("base64") === HMAC_PROBE_DIGEST ? hasher : void 0;
26
+ return new hasher("sha256", "elysia").update("probe").digest("base64") === "bzs6y9cVmkYub8fplSKaOuuqMqJlDwhMypFT/jSdCEk=" ? hasher : void 0;
28
27
  } catch {
29
28
  return;
30
29
  }
@@ -61,19 +60,22 @@ async function signCookieSubtle(val, secret) {
61
60
  const hmacBuffer = await crypto.subtle.sign("HMAC", await importSecretKey(secret), encoder.encode(val));
62
61
  return `${val}.${btoa(String.fromCharCode(...new Uint8Array(hmacBuffer))).replace(removeTrailingEquals, "")}`;
63
62
  }
64
- async function signCookie(val, secret) {
63
+ const deriveSignKey = (secret, name) => `${name.length}\0${name}${secret}`;
64
+ async function signCookie(val, secret, name) {
65
65
  val = coerceValue(val);
66
- if (secret === null || secret === void 0) throw new TypeError("Secret key must be provided");
66
+ if (!secret?.trim()) throw new TypeError("Secret key must be provided");
67
+ if (name !== void 0) secret = deriveSignKey(secret, name);
67
68
  if (hasSyncHmac) return signCookieSyncImpl(val, secret);
68
69
  return signCookieSubtle(val, secret);
69
70
  }
70
- function signCookieSync(val, secret) {
71
+ function signCookieSync(val, secret, name) {
71
72
  val = coerceValue(val);
72
- if (secret === null || secret === void 0) throw new TypeError("Secret key must be provided");
73
+ if (!secret?.trim()) throw new TypeError("Secret key must be provided");
73
74
  if (!hasSyncHmac) throw new Error("signCookieSync called without a sync HMAC available");
75
+ if (name !== void 0) secret = deriveSignKey(secret, name);
74
76
  return signCookieSyncImpl(val, secret);
75
77
  }
76
- async function unsignCookie(input, secret) {
78
+ async function unsignCookie(input, secret, name) {
77
79
  if (typeof input !== "string") throw new TypeError("Signed cookie string must be provided.");
78
80
  const dot = input.lastIndexOf(".");
79
81
  if (dot === -1) {
@@ -81,10 +83,10 @@ async function unsignCookie(input, secret) {
81
83
  return false;
82
84
  }
83
85
  const tentativeValue = input.slice(0, dot);
84
- if (secret === null) return false;
85
- return constantTimeEqual(await signCookie(tentativeValue, secret), input) ? tentativeValue : false;
86
+ if (!secret?.trim()) return false;
87
+ return constantTimeEqual(await signCookie(tentativeValue, secret, name), input) ? tentativeValue : false;
86
88
  }
87
- function unsignCookieSync(input, secret) {
89
+ function unsignCookieSync(input, secret, name) {
88
90
  if (typeof input !== "string") throw new TypeError("Signed cookie string must be provided.");
89
91
  const dot = input.lastIndexOf(".");
90
92
  if (dot === -1) {
@@ -92,32 +94,36 @@ function unsignCookieSync(input, secret) {
92
94
  return false;
93
95
  }
94
96
  const tentativeValue = input.slice(0, dot);
95
- if (secret === null) return false;
96
- return constantTimeEqual(signCookieSync(tentativeValue, secret), input) ? tentativeValue : false;
97
+ if (!secret?.trim()) return false;
98
+ return constantTimeEqual(signCookieSync(tentativeValue, secret, name), input) ? tentativeValue : false;
97
99
  }
98
- function unsignWithSecretsSync(name, value, secrets) {
100
+ function unsignWithSecretsSync(name, value, secrets, legacy) {
99
101
  if (typeof value !== "string") throw InvalidCookie.signature(name);
100
- if (typeof secrets === "string") {
101
- const temp = unsignCookieSync(value, secrets);
102
- if (temp === false) throw InvalidCookie.signature(name);
103
- return temp;
104
- }
105
- if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
106
- const temp = unsignCookieSync(value, secrets[i]);
107
- if (temp !== false) return temp;
102
+ for (let pass = 0; pass < 2; pass++) {
103
+ const bound = pass === 0 ? name : void 0;
104
+ if (typeof secrets === "string") {
105
+ const temp = unsignCookieSync(value, secrets, bound);
106
+ if (temp !== false) return temp;
107
+ } else if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
108
+ const temp = unsignCookieSync(value, secrets[i], bound);
109
+ if (temp !== false) return temp;
110
+ }
111
+ if (!legacy) break;
108
112
  }
109
113
  throw InvalidCookie.signature(name);
110
114
  }
111
- async function unsignWithSecrets(name, value, secrets) {
115
+ async function unsignWithSecrets(name, value, secrets, legacy) {
112
116
  if (typeof value !== "string") throw InvalidCookie.signature(name);
113
- if (typeof secrets === "string") {
114
- const temp = await unsignCookie(value, secrets);
115
- if (temp === false) throw InvalidCookie.signature(name);
116
- return temp;
117
- }
118
- if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
119
- const temp = await unsignCookie(value, secrets[i]);
120
- if (temp !== false) return temp;
117
+ for (let pass = 0; pass < 2; pass++) {
118
+ const bound = pass === 0 ? name : void 0;
119
+ if (typeof secrets === "string") {
120
+ const temp = await unsignCookie(value, secrets, bound);
121
+ if (temp !== false) return temp;
122
+ } else if (Array.isArray(secrets)) for (let i = 0; i < secrets.length; i++) {
123
+ const temp = await unsignCookie(value, secrets[i], bound);
124
+ if (temp !== false) return temp;
125
+ }
126
+ if (!legacy) break;
121
127
  }
122
128
  throw InvalidCookie.signature(name);
123
129
  }
@@ -138,7 +144,7 @@ function resolvePendingCookie(entry, name) {
138
144
  const value = entry.value;
139
145
  if (typeof value !== "string") throw InvalidCookie.signature(name);
140
146
  if (!hasSyncHmac) throw new Error(`resolvePendingCookie called without sync HMAC. Unreachable under correct lane gating (cookie: "${name}")`);
141
- const resolvedValue = maybeJsonDecode(unsignWithSecretsSync(name, value, entry["~unsign"]));
147
+ const resolvedValue = maybeJsonDecode(unsignWithSecretsSync(name, value, entry["~unsign"], !entry["~strict"]));
142
148
  entry.value = resolvedValue;
143
149
  if (resolvedValue !== null && typeof resolvedValue === "object") {
144
150
  const raw = rawJsonValue.get(resolvedValue);
@@ -148,4 +154,4 @@ function resolvePendingCookie(entry, name) {
148
154
  }
149
155
 
150
156
  //#endregion
151
- export { hasSyncHmac, hmacProvider, importSecretKey, keyCache, maybeJsonDecode, rawJsonValue, resolvePendingCookie, signCookie, signCookieBun, signCookieNode, signCookieSubtle, signCookieSync, signCookieSyncImpl, unsignCookie, unsignCookieSync, unsignWithSecrets, unsignWithSecretsSync };
157
+ export { deriveSignKey, hasSyncHmac, hmacProvider, importSecretKey, keyCache, maybeJsonDecode, rawJsonValue, resolvePendingCookie, signCookie, signCookieBun, signCookieNode, signCookieSubtle, signCookieSync, signCookieSyncImpl, unsignCookie, unsignCookieSync, unsignWithSecrets, unsignWithSecretsSync };
@@ -16,8 +16,7 @@ var InvalidCookie = class InvalidCookie extends require_error.ElysiaError {
16
16
  return new InvalidCookie(key, `"${key}" has invalid cookie signature`);
17
17
  }
18
18
  static secret(key) {
19
- if (key) return new InvalidCookie(key, `"${key}" is signed but no secret is provided`, 500);
20
- return new InvalidCookie(void 0, `Cookie is signed but no secret is provided`, 500);
19
+ return new InvalidCookie(key, `${key ? `Cookie "${key}"` : "A cookie"} is signed but \`cookie.secrets\` is missing or empty. Set it to a non-empty string: an empty secret signs with a zero-length key, which anyone can forge.`, 500);
21
20
  }
22
21
  };
23
22
 
@@ -15,8 +15,7 @@ var InvalidCookie = class InvalidCookie extends ElysiaError {
15
15
  return new InvalidCookie(key, `"${key}" has invalid cookie signature`);
16
16
  }
17
17
  static secret(key) {
18
- if (key) return new InvalidCookie(key, `"${key}" is signed but no secret is provided`, 500);
19
- return new InvalidCookie(void 0, `Cookie is signed but no secret is provided`, 500);
18
+ return new InvalidCookie(key, `${key ? `Cookie "${key}"` : "A cookie"} is signed but \`cookie.secrets\` is missing or empty. Set it to a non-empty string: an empty secret signs with a zero-length key, which anyone can forge.`, 500);
20
19
  }
21
20
  };
22
21
 
@@ -40,7 +40,11 @@ function serialize(name, value = "", options) {
40
40
  if (value) value = encodeURIComponent(value);
41
41
  let str = `${name}=${value}`;
42
42
  const maxAge = options.maxAge;
43
- if (maxAge !== void 0) str += "; Max-Age=" + maxAge;
43
+ if (maxAge !== void 0) {
44
+ const age = Math.floor(maxAge);
45
+ if (!Number.isFinite(age)) throw new require_cookie_error.InvalidCookie(`Invalid cookie Max-Age ${JSON.stringify(maxAge)}.`);
46
+ str += "; Max-Age=" + age;
47
+ }
44
48
  const domain = options.domain;
45
49
  if (domain) {
46
50
  if (COOKIE_ATTR_INVALID.test(domain)) throw new require_cookie_error.InvalidCookie(`Invalid cookie Domain ${JSON.stringify(domain)}.`);
@@ -39,7 +39,11 @@ function serialize(name, value = "", options) {
39
39
  if (value) value = encodeURIComponent(value);
40
40
  let str = `${name}=${value}`;
41
41
  const maxAge = options.maxAge;
42
- if (maxAge !== void 0) str += "; Max-Age=" + maxAge;
42
+ if (maxAge !== void 0) {
43
+ const age = Math.floor(maxAge);
44
+ if (!Number.isFinite(age)) throw new InvalidCookie(`Invalid cookie Max-Age ${JSON.stringify(maxAge)}.`);
45
+ str += "; Max-Age=" + age;
46
+ }
43
47
  const domain = options.domain;
44
48
  if (domain) {
45
49
  if (COOKIE_ATTR_INVALID.test(domain)) throw new InvalidCookie(`Invalid cookie Domain ${JSON.stringify(domain)}.`);
@@ -7,7 +7,7 @@ function serializeCookie(cookies) {
7
7
  if (!cookies || !require_utils.isNotEmpty(cookies)) return;
8
8
  let set;
9
9
  let isArray = false;
10
- for (const key in cookies) {
10
+ for (const key of Object.keys(cookies)) {
11
11
  if (!key) continue;
12
12
  const property = cookies[key];
13
13
  if (!property) continue;