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
@@ -24,6 +24,15 @@ var ElysiaWS = class {
24
24
  this.raw = raw;
25
25
  if (context) for (const key in context) {
26
26
  if (key === "ws" || key === "body") continue;
27
+ if (key === "__proto__") {
28
+ Object.defineProperty(this, key, {
29
+ value: context[key],
30
+ writable: true,
31
+ enumerable: true,
32
+ configurable: true
33
+ });
34
+ continue;
35
+ }
27
36
  this[key] = context[key];
28
37
  }
29
38
  }
@@ -62,50 +71,59 @@ var ElysiaWS = class {
62
71
  get data() {
63
72
  return this.raw.data;
64
73
  }
65
- #prepare(data) {
66
- if (data === void 0) return null;
67
- if (data instanceof require_error.ElysiaStatus) return JSON.stringify({
68
- status: data.status,
69
- error: data.response
70
- });
71
- if (typeof data === "object") return JSON.stringify(data);
72
- return data;
73
- }
74
- #validatedOrError(data) {
74
+ /**
75
+ * Validate, redact and serialize an outbound value, or return the
76
+ * `ValidationError` the payload was refused with.
77
+ */
78
+ #frame(data) {
75
79
  const connectionData = this.raw.data;
76
80
  const v = pickValidator(connectionData?.validator, connectionData?.defaultValidator, data);
77
- if (!v) return;
78
- const value = data instanceof require_error.ElysiaStatus ? data.response : data;
79
- if (v.Check(value)) return;
80
- return new require_error.ValidationError("message", value, v.Errors(value)).message;
81
+ const status = data instanceof require_error.ElysiaStatus ? data : void 0;
82
+ let value = status ? status.response : data;
83
+ if (v) {
84
+ const encode = v.EncodeFrom;
85
+ let redacted;
86
+ if (typeof encode === "function" && !v.hasCodec && !v.mayReturnPromise) try {
87
+ redacted = encode.call(v, value, "message");
88
+ } catch {}
89
+ if (redacted !== void 0) value = redacted;
90
+ else if (!v.Check(value)) return new require_error.ValidationError("message", value, v.Errors(value));
91
+ }
92
+ if (status) return JSON.stringify({
93
+ status: status.status,
94
+ error: value
95
+ });
96
+ if (value === void 0) return null;
97
+ if (typeof value === "object") return JSON.stringify(value);
98
+ return value;
81
99
  }
82
100
  #send(data, compress) {
83
101
  if (data === void 0) return 0;
84
102
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.send(data, compress);
85
- const err = this.#validatedOrError(data);
86
- if (err !== void 0) return this.raw.send(err);
87
- return this.raw.send(this.#prepare(data), compress);
103
+ const frame = this.#frame(data);
104
+ if (frame instanceof require_error.ValidationError) return this.raw.send(frame.message);
105
+ return this.raw.send(frame, compress);
88
106
  }
89
107
  #ping(data) {
90
108
  if (data === void 0) return this.raw.ping();
91
109
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.ping(data);
92
- const err = this.#validatedOrError(data);
93
- if (err !== void 0) return this.raw.send(err);
94
- return this.raw.ping(this.#prepare(data));
110
+ const frame = this.#frame(data);
111
+ if (frame instanceof require_error.ValidationError) return this.raw.send(frame.message);
112
+ return this.raw.ping(frame);
95
113
  }
96
114
  #pong(data) {
97
115
  if (data === void 0) return this.raw.pong();
98
116
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.pong(data);
99
- const err = this.#validatedOrError(data);
100
- if (err !== void 0) return this.raw.send(err);
101
- return this.raw.pong(this.#prepare(data));
117
+ const frame = this.#frame(data);
118
+ if (frame instanceof require_error.ValidationError) return this.raw.send(frame.message);
119
+ return this.raw.pong(frame);
102
120
  }
103
121
  #publish(topic, data, compress) {
104
122
  if (data === void 0) return 0;
105
123
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.publish(topic, data, compress);
106
- const err = this.#validatedOrError(data);
107
- if (err !== void 0) return this.raw.send(err);
108
- return this.raw.publish(topic, this.#prepare(data), compress);
124
+ const frame = this.#frame(data);
125
+ if (frame instanceof require_error.ValidationError) return this.raw.send(frame.message);
126
+ return this.raw.publish(topic, frame, compress);
109
127
  }
110
128
  #close(code, reason) {
111
129
  const data = this.raw.data;
@@ -23,6 +23,15 @@ var ElysiaWS = class {
23
23
  this.raw = raw;
24
24
  if (context) for (const key in context) {
25
25
  if (key === "ws" || key === "body") continue;
26
+ if (key === "__proto__") {
27
+ Object.defineProperty(this, key, {
28
+ value: context[key],
29
+ writable: true,
30
+ enumerable: true,
31
+ configurable: true
32
+ });
33
+ continue;
34
+ }
26
35
  this[key] = context[key];
27
36
  }
28
37
  }
@@ -61,50 +70,59 @@ var ElysiaWS = class {
61
70
  get data() {
62
71
  return this.raw.data;
63
72
  }
64
- #prepare(data) {
65
- if (data === void 0) return null;
66
- if (data instanceof ElysiaStatus) return JSON.stringify({
67
- status: data.status,
68
- error: data.response
69
- });
70
- if (typeof data === "object") return JSON.stringify(data);
71
- return data;
72
- }
73
- #validatedOrError(data) {
73
+ /**
74
+ * Validate, redact and serialize an outbound value, or return the
75
+ * `ValidationError` the payload was refused with.
76
+ */
77
+ #frame(data) {
74
78
  const connectionData = this.raw.data;
75
79
  const v = pickValidator(connectionData?.validator, connectionData?.defaultValidator, data);
76
- if (!v) return;
77
- const value = data instanceof ElysiaStatus ? data.response : data;
78
- if (v.Check(value)) return;
79
- return new ValidationError("message", value, v.Errors(value)).message;
80
+ const status = data instanceof ElysiaStatus ? data : void 0;
81
+ let value = status ? status.response : data;
82
+ if (v) {
83
+ const encode = v.EncodeFrom;
84
+ let redacted;
85
+ if (typeof encode === "function" && !v.hasCodec && !v.mayReturnPromise) try {
86
+ redacted = encode.call(v, value, "message");
87
+ } catch {}
88
+ if (redacted !== void 0) value = redacted;
89
+ else if (!v.Check(value)) return new ValidationError("message", value, v.Errors(value));
90
+ }
91
+ if (status) return JSON.stringify({
92
+ status: status.status,
93
+ error: value
94
+ });
95
+ if (value === void 0) return null;
96
+ if (typeof value === "object") return JSON.stringify(value);
97
+ return value;
80
98
  }
81
99
  #send(data, compress) {
82
100
  if (data === void 0) return 0;
83
101
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.send(data, compress);
84
- const err = this.#validatedOrError(data);
85
- if (err !== void 0) return this.raw.send(err);
86
- return this.raw.send(this.#prepare(data), compress);
102
+ const frame = this.#frame(data);
103
+ if (frame instanceof ValidationError) return this.raw.send(frame.message);
104
+ return this.raw.send(frame, compress);
87
105
  }
88
106
  #ping(data) {
89
107
  if (data === void 0) return this.raw.ping();
90
108
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.ping(data);
91
- const err = this.#validatedOrError(data);
92
- if (err !== void 0) return this.raw.send(err);
93
- return this.raw.ping(this.#prepare(data));
109
+ const frame = this.#frame(data);
110
+ if (frame instanceof ValidationError) return this.raw.send(frame.message);
111
+ return this.raw.ping(frame);
94
112
  }
95
113
  #pong(data) {
96
114
  if (data === void 0) return this.raw.pong();
97
115
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.pong(data);
98
- const err = this.#validatedOrError(data);
99
- if (err !== void 0) return this.raw.send(err);
100
- return this.raw.pong(this.#prepare(data));
116
+ const frame = this.#frame(data);
117
+ if (frame instanceof ValidationError) return this.raw.send(frame.message);
118
+ return this.raw.pong(frame);
101
119
  }
102
120
  #publish(topic, data, compress) {
103
121
  if (data === void 0) return 0;
104
122
  if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) return this.raw.publish(topic, data, compress);
105
- const err = this.#validatedOrError(data);
106
- if (err !== void 0) return this.raw.send(err);
107
- return this.raw.publish(topic, this.#prepare(data), compress);
123
+ const frame = this.#frame(data);
124
+ if (frame instanceof ValidationError) return this.raw.send(frame.message);
125
+ return this.raw.publish(topic, frame, compress);
108
126
  }
109
127
  #close(code, reason) {
110
128
  const data = this.raw.data;
package/dist/ws/route.js CHANGED
@@ -2,11 +2,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_universal_constants = require('../universal/constants.js');
3
3
  const require_utils = require('../utils.js');
4
4
  const require_type_bridge = require('../type/bridge.js');
5
- const require_universal_is_production = require('../universal/is-production.js');
6
5
  const require_error = require('../error.js');
7
6
  const require_adapter_web_standard_handler = require('../adapter/web-standard/handler.js');
8
7
  const require_parse_query = require('../parse-query.js');
9
8
  const require_generation = require('../generation.js');
9
+ const require_cookie_config = require('../cookie/config.js');
10
+ const require_cookie_utils = require('../cookie/utils.js');
10
11
  const require_handler_error = require('../handler/error.js');
11
12
  const require_compile_handler_utils = require('../compile/handler/utils.js');
12
13
  const require_validator_index = require('../validator/index.js');
@@ -181,9 +182,45 @@ function wsErrorFrame(error) {
181
182
  }
182
183
  return wsErrorFrameFallback(error);
183
184
  }
185
+ /**
186
+ * Frame served by an error that claims an RFC 9457 problem document, mirroring
187
+ * the HTTP tiers in `handler/error.ts`: `value` replaces the whole frame,
188
+ * `detail` fills the `detail` member, the message is the last resort.
189
+ *
190
+ * A frame carries no headers, so a `headers` annotation is ignored outright
191
+ * rather than half-applied
192
+ */
193
+ function wsProblemFrame(error) {
194
+ const status = require_handler_error.resolveStatus(error.status);
195
+ const served = typeof status === "number" && status >= 100 ? status : 500;
196
+ const stringify = (value) => typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
197
+ const problemFrame = (detail) => JSON.stringify(require_error.problemBody({
198
+ type: error.type ?? "about:blank",
199
+ detail,
200
+ status: served
201
+ }));
202
+ const serveMessage = () => problemFrame(require_handler_error.statusFallbackBody(error, served));
203
+ const serveDetail = () => {
204
+ const detail = require_handler_error.readAnnotation(error, "detail", true);
205
+ if (detail === void 0) return serveMessage();
206
+ if (detail instanceof Promise) return detail.then((resolved) => resolved === void 0 ? serveMessage() : problemFrame(resolved)).catch(() => wsLegacyFrame(error));
207
+ return problemFrame(detail);
208
+ };
209
+ const value = require_handler_error.readAnnotation(error, "value", true);
210
+ if (value === void 0) return serveDetail();
211
+ if (value instanceof Promise) return value.then((resolved) => resolved === void 0 ? serveDetail() : stringify(resolved)).catch(() => wsLegacyFrame(error));
212
+ return stringify(value);
213
+ }
184
214
  function wsErrorFrameFallback(error) {
215
+ if (require_handler_error.claimsProblemType(error)) try {
216
+ return wsProblemFrame(error);
217
+ } catch {}
218
+ return wsLegacyFrame(error);
219
+ }
220
+ /** Frame an error that never self-described has always served */
221
+ function wsLegacyFrame(error) {
185
222
  if (error?.status) {
186
- const body = error.response !== void 0 ? error.response : require_universal_is_production.isProduction() ? error.status >= 500 ? "Internal Server Error" : "" : error.message ?? "";
223
+ const body = require_handler_error.statusFallbackBody(error, error.status);
187
224
  return typeof body === "object" ? JSON.stringify(body) : String(body);
188
225
  }
189
226
  return require_error.internalServerErrorBodyString(error);
@@ -218,13 +255,20 @@ const wsOptions = [
218
255
  ];
219
256
  function buildWSRoute(route, app) {
220
257
  const hook = require_compile_handler_index.resolveWSLocalHook(require_compile_handler_index.localMacroRoot(route[7] ?? route[3] ?? app, app), route[4], app) ?? require_utils.nullObject();
258
+ const instance = route[3] ?? app;
259
+ const appHookChain = route[5];
260
+ const inheritedChain = route[6];
261
+ const composed = require_compile_handler_index.composeRouteHook(instance, route[4], appHookChain, inheritedChain, app, route[7]) ?? hook;
221
262
  let validators;
222
- const frozenEager = require_type_bridge.isBridgeLive() ? void 0 : require_compile_handler_frozen_validator.buildFrozenRouteValidator(hook, app, "WS", route[1]);
263
+ const frozenEager = require_type_bridge.isBridgeLive() ? void 0 : require_compile_handler_frozen_validator.buildFrozenRouteValidator(composed, app, "WS", route[1]);
223
264
  if (frozenEager) validators = frozenEager;
224
265
  else try {
225
- validators = new require_validator_route.RouteValidator(hook, {
266
+ validators = new require_validator_route.RouteValidator(composed, {
226
267
  models: require_generation.frozenRootOf(app)["~ext"]?.models,
227
268
  app,
269
+ normalize: require_generation.frozenRootOf(app)["~config"]?.normalize,
270
+ sanitize: require_generation.frozenRootOf(app)["~config"]?.sanitize,
271
+ schemas: composed.schemas,
228
272
  aot: {
229
273
  method: "WS",
230
274
  path: route[1]
@@ -233,18 +277,17 @@ function buildWSRoute(route, app) {
233
277
  });
234
278
  } catch (error) {
235
279
  if (!require_compile_handler_frozen_validator.isBridgeNotInitialized(error)) throw error;
236
- const frozen = require_compile_handler_frozen_validator.buildFrozenRouteValidator(hook, app, "WS", route[1]);
280
+ const frozen = require_compile_handler_frozen_validator.buildFrozenRouteValidator(composed, app, "WS", route[1]);
237
281
  if (!frozen) throw error;
238
282
  validators = frozen;
239
283
  }
240
284
  const responseValidator = validators.response;
241
285
  const defaultResponseValidator = responseValidator ? responseValidator[200] ?? responseValidator[Object.keys(responseValidator)[0]] : void 0;
286
+ const cookieConfig = validators.cookie ? require_cookie_config.compileCookieConfig(composed.cookie, require_generation.frozenRootOf(app)["~config"]?.cookie) : void 0;
287
+ const cookieIsOptional = !!composed.cookie?.["~optional"];
242
288
  const queryChannels = require_compile_handler_utils.getQueryParseChannels(validators.query?.schema);
243
289
  const queryArray = queryChannels?.array;
244
290
  const queryObject = queryChannels?.object;
245
- const instance = route[3] ?? app;
246
- const appHookChain = route[5];
247
- const inheritedChain = route[6];
248
291
  const flatAppHook = require_compile_handler_index.composeRouteHook(instance, void 0, appHookChain, inheritedChain, app, route[7]) ?? {};
249
292
  const parseHooks = hook.parse == null ? [] : Array.isArray(hook.parse) ? hook.parse : [hook.parse];
250
293
  const transforms = concatHooks(flatAppHook.transform, hook.transform);
@@ -272,6 +315,7 @@ function buildWSRoute(route, app) {
272
315
  break;
273
316
  }
274
317
  if (r !== void 0) {
318
+ r = require_handler_error.adoptErrorType(r, error);
275
319
  try {
276
320
  await handleWSResponse(ws, r, mapResponses);
277
321
  } catch {}
@@ -419,6 +463,15 @@ function buildWSRoute(route, app) {
419
463
  if (r instanceof Promise) r = await r;
420
464
  context.headers = r;
421
465
  }
466
+ if (cookieConfig) {
467
+ const raw = await require_cookie_utils.parseCookieRaw(request.headers.get("cookie"), cookieConfig);
468
+ let r = raw;
469
+ if (!cookieIsOptional || Object.keys(raw).length) {
470
+ r = validateUpgradeChannel(validators.cookie, raw, "cookie");
471
+ if (r instanceof Promise) r = await r;
472
+ }
473
+ context.cookie = require_cookie_utils.buildCookieJar(context.set, r, cookieConfig);
474
+ }
422
475
  for (let i = 0; i < transforms.length; i++) {
423
476
  const r = transforms[i](context);
424
477
  if (r instanceof Promise) await r;
@@ -430,7 +483,7 @@ function buildWSRoute(route, app) {
430
483
  const deriveMode = upgradeDeriveModes?.[i];
431
484
  if (deriveMode !== void 0 && !(r instanceof require_error.ElysiaStatus)) {
432
485
  if (r && typeof r === "object") if (deriveMode) context = require_compile_handler_utils.replaceDeriveContext(context, r);
433
- else Object.assign(context, r);
486
+ else require_utils.assignOwn(context, r);
434
487
  } else if (r !== void 0) {
435
488
  if (r instanceof Response) return r;
436
489
  return require_adapter_web_standard_handler.mapResponse(r, context.set, context.request);
@@ -485,22 +538,37 @@ function resolveWSOptions(entries) {
485
538
  const incoming = entry.value[key];
486
539
  if (key in result && result[key] !== incoming && !warned?.has(key)) {
487
540
  (warned ??= /* @__PURE__ */ new Set()).add(key);
488
- console.warn(`[Elysia] Conflicting WebSocket option '${key}' across .use(websocket()) registrations; the shallowest (nearest-root) registration wins.`);
541
+ console.warn(`[Elysia] Conflicting WebSocket option '${key}' across .use(websocket()). Using nearest-root registration.`);
489
542
  }
490
543
  result[key] = incoming;
491
544
  }
492
545
  return result;
493
546
  }
547
+ const wsLimits = [
548
+ "maxPayloadLength",
549
+ "backpressureLimit",
550
+ "idleTimeout"
551
+ ];
552
+ const routeOwnedKeys = /* @__PURE__ */ new WeakMap();
494
553
  function accumulateWSOptions(target, routeOptions, _path) {
495
554
  if (!require_utils.isNotEmpty(routeOptions)) return;
496
- if (require_universal_constants.isBun) {
497
- for (const key in routeOptions) if (key in target && target[key] !== routeOptions[key]) {
498
- console.warn(`[Elysia] Conflicting per-route WebSocket option '${key}'\nBun uses one global WebSocket config per server, per-route values are not enforced (the last-registered route wins).`);
499
- console.warn((/* @__PURE__ */ new Error()).stack);
555
+ let owned = routeOwnedKeys.get(target);
556
+ if (!owned) routeOwnedKeys.set(target, owned = /* @__PURE__ */ new Set());
557
+ for (const key in routeOptions) {
558
+ const incoming = routeOptions[key];
559
+ const current = target[key];
560
+ if (key in target && current !== incoming) {
561
+ if (require_universal_constants.isBun) {
562
+ console.warn(`[Elysia] Conflicting per-route WebSocket option '${key}'\nBun uses one global WebSocket config per server, per-route values are not enforced (for limits the strictest route wins, otherwise the last-registered route).`);
563
+ console.warn((/* @__PURE__ */ new Error()).stack);
564
+ }
565
+ if (owned.has(key) && typeof current === "number" && typeof incoming === "number" && current < incoming && wsLimits.includes(key)) continue;
500
566
  }
567
+ owned.add(key);
568
+ target[key] = incoming;
501
569
  }
502
- Object.assign(target, routeOptions);
503
570
  }
571
+ const MAX_INFLIGHT_MESSAGES = 256;
504
572
  function buildGlobalWSHandler() {
505
573
  function getElysia(ws) {
506
574
  let elysia = ws.data.elysia;
@@ -516,19 +584,52 @@ function buildGlobalWSHandler() {
516
584
  ws.send(typeof error?.message === "string" ? error.message : "Internal Server Error");
517
585
  } catch {}
518
586
  };
587
+ const release = (ws) => {
588
+ const inflight = ws.data.inflight;
589
+ if (inflight) ws.data.inflight = inflight - 1;
590
+ };
591
+ function dispatch(ws, message) {
592
+ let result;
593
+ try {
594
+ result = ws.data.message(getElysia(ws), message);
595
+ } catch (error) {
596
+ release(ws);
597
+ sendErrMsg(ws, error);
598
+ return;
599
+ }
600
+ if (result instanceof Promise) result.then(() => release(ws), (error) => {
601
+ release(ws);
602
+ sendErrMsg(ws, error);
603
+ });
604
+ else release(ws);
605
+ }
519
606
  return {
520
607
  message(ws, message) {
521
- let result;
522
- try {
523
- result = ws.data.message?.(getElysia(ws), message);
524
- } catch (error) {
525
- sendErrMsg(ws, error);
608
+ const data = ws.data;
609
+ if (!data.message) return;
610
+ const inflight = (data.inflight ?? 0) + 1;
611
+ if (inflight > MAX_INFLIGHT_MESSAGES) {
612
+ try {
613
+ ws.close(1013, "Too many in-flight messages");
614
+ } catch {}
526
615
  return;
527
616
  }
528
- if (result instanceof Promise) result.catch((error) => sendErrMsg(ws, error));
617
+ data.inflight = inflight;
618
+ const opening = data.opening;
619
+ if (opening) return void opening.then(() => {
620
+ if (ws.readyState > 1) return release(ws);
621
+ dispatch(ws, message);
622
+ });
623
+ dispatch(ws, message);
529
624
  },
530
625
  open(ws) {
531
- ws.data.open?.(getElysia(ws));
626
+ const result = ws.data.open?.(getElysia(ws));
627
+ if (result instanceof Promise) {
628
+ const clear = () => {
629
+ ws.data.opening = void 0;
630
+ };
631
+ ws.data.opening = result.then(clear, clear);
632
+ }
532
633
  },
533
634
  drain(ws) {
534
635
  const elyWs = getElysia(ws);
@@ -538,9 +639,11 @@ function buildGlobalWSHandler() {
538
639
  close(ws, code, reason) {
539
640
  const elyWs = getElysia(ws);
540
641
  drainWaiters(elyWs);
642
+ ws.data.opening = void 0;
541
643
  if (ws.data.closeHandlerInvoked) return;
542
644
  ws.data.closeHandlerInvoked = true;
543
- ws.data.close?.(elyWs, code, reason);
645
+ const result = ws.data.close?.(elyWs, code, reason);
646
+ if (result instanceof Promise) result.catch(() => {});
544
647
  },
545
648
  ping(ws, data) {
546
649
  ws.data.ping?.(getElysia(ws), data);