elysia 1.4.29 → 1.4.31

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.
package/dist/error.mjs CHANGED
@@ -75,9 +75,10 @@ const mapValueError = (error) => {
75
75
  summary: isRoot ? "Value should be an email" : `Property '${property}' should be ${format}`
76
76
  };
77
77
  case 54:
78
+ const found = formatValidationSummaryValue(value);
78
79
  return {
79
80
  ...error,
80
- summary: `${message.slice(0, 9).trim()} property '${property}' to be ${message.slice(8).trim()} but found: ${value}`
81
+ summary: `${message.slice(0, 9).trim()} property '${property}' to be ${message.slice(8).trim()} but found: ${found}`
81
82
  };
82
83
  case 62:
83
84
  const union = error.schema.anyOf.map((x) => `'${x?.format ?? x.type}'`).join(", ");
@@ -88,6 +89,220 @@ const mapValueError = (error) => {
88
89
  default:
89
90
  return { summary: message, ...error };
90
91
  }
92
+ }, MAX_ERRORS = 64, MAX_VALIDATION_ERROR_DEPTH = 16, MAX_VALIDATION_ERROR_NODES = 8192, MAX_VALIDATION_ERROR_ENTRIES = 4096, MAX_VALIDATION_ERROR_CONTAINER_ENTRIES = 512, MAX_VALIDATION_ERROR_STRING_LENGTH = 4096, MAX_VALIDATION_ERROR_OUTPUT_LENGTH = 65536, VALIDATION_TRUNCATED = "[Truncated]", VALIDATION_UNSERIALIZABLE = "[Unserializable]", OMIT_VALIDATION_VALUE = Symbol("omitValidationValue"), boundValidationString = (value, state) => {
93
+ const remaining = state ? MAX_VALIDATION_ERROR_OUTPUT_LENGTH - state.strings : MAX_VALIDATION_ERROR_STRING_LENGTH, limit = Math.min(MAX_VALIDATION_ERROR_STRING_LENGTH, remaining);
94
+ return value.length <= limit ? (state && (state.strings += value.length), value) : (state && (state.strings += Math.max(limit, 0)), limit <= 0 ? "" : limit <= VALIDATION_TRUNCATED.length ? VALIDATION_TRUNCATED.slice(0, limit) : value.slice(0, limit - VALIDATION_TRUNCATED.length) + VALIDATION_TRUNCATED);
95
+ }, formatValidationSummaryValue = (value) => {
96
+ if (typeof value == "string") return boundValidationString(value);
97
+ if (value === null || typeof value == "number" || typeof value == "boolean" || typeof value == "bigint" || typeof value > "u")
98
+ return String(value);
99
+ try {
100
+ if (Array.isArray(value)) {
101
+ const length = Object.getOwnPropertyDescriptor(
102
+ value,
103
+ "length"
104
+ )?.value;
105
+ if (typeof length != "number" || length > MAX_VALIDATION_ERROR_CONTAINER_ENTRIES)
106
+ return "[object Object]";
107
+ const output = [];
108
+ let size = 0;
109
+ for (let index = 0; index < length; index++) {
110
+ const descriptor = Object.getOwnPropertyDescriptor(
111
+ value,
112
+ `${index}`
113
+ );
114
+ if (!descriptor || !("value" in descriptor)) {
115
+ output.push("");
116
+ continue;
117
+ }
118
+ const item = descriptor.value;
119
+ if (item == null) output.push("");
120
+ else if (typeof item == "string" || typeof item == "number" || typeof item == "boolean" || typeof item == "bigint") {
121
+ const part = String(item);
122
+ if (size += part.length + 1, size > MAX_VALIDATION_ERROR_STRING_LENGTH)
123
+ return boundValidationString(output.join(","));
124
+ output.push(part);
125
+ } else return "[object Object]";
126
+ }
127
+ return boundValidationString(output.join(","));
128
+ }
129
+ } catch {
130
+ }
131
+ return "[object Object]";
132
+ }, validationOutputFits = (value) => {
133
+ let bytes = 0;
134
+ for (let index = 0; index < value.length; index++) {
135
+ const code = value.charCodeAt(index);
136
+ if (code < 128 ? bytes++ : code < 2048 ? bytes += 2 : code >= 55296 && code <= 56319 && value.charCodeAt(index + 1) >= 56320 && value.charCodeAt(index + 1) <= 57343 ? (bytes += 4, index++) : bytes += 3, bytes > MAX_VALIDATION_ERROR_OUTPUT_LENGTH) return !1;
137
+ }
138
+ return !0;
139
+ }, projectValidationValue = (value, state, depth = 0) => {
140
+ if (state.nodes++ >= MAX_VALIDATION_ERROR_NODES) return VALIDATION_TRUNCATED;
141
+ switch (typeof value) {
142
+ case "string":
143
+ return boundValidationString(value, state);
144
+ case "number":
145
+ return Number.isFinite(value) ? value : null;
146
+ case "boolean":
147
+ return value;
148
+ case "bigint":
149
+ return "[BigInt]";
150
+ case "undefined":
151
+ case "function":
152
+ case "symbol":
153
+ return OMIT_VALIDATION_VALUE;
154
+ }
155
+ if (typeof value != "object" || value === null) return null;
156
+ if (depth >= MAX_VALIDATION_ERROR_DEPTH) return VALIDATION_TRUNCATED;
157
+ if (state.depth.has(value)) return "[Circular]";
158
+ try {
159
+ if (value instanceof Date) {
160
+ const timestamp = Date.prototype.getTime.call(value);
161
+ return Number.isFinite(timestamp) ? boundValidationString(
162
+ Date.prototype.toISOString.call(value),
163
+ state
164
+ ) : null;
165
+ }
166
+ } catch {
167
+ }
168
+ state.depth.add(value);
169
+ try {
170
+ if (Array.isArray(value)) {
171
+ const output2 = [], lengthDescriptor = Object.getOwnPropertyDescriptor(
172
+ value,
173
+ "length"
174
+ ), length = typeof lengthDescriptor?.value == "number" ? lengthDescriptor.value : 0;
175
+ let index = 0;
176
+ for (; index < length && index < MAX_VALIDATION_ERROR_CONTAINER_ENTRIES && state.entries < MAX_VALIDATION_ERROR_ENTRIES && state.nodes < MAX_VALIDATION_ERROR_NODES; index++) {
177
+ state.entries++;
178
+ const descriptor = Object.getOwnPropertyDescriptor(
179
+ value,
180
+ `${index}`
181
+ ), projected = descriptor ? "value" in descriptor ? projectValidationValue(
182
+ descriptor.value,
183
+ state,
184
+ depth + 1
185
+ ) : VALIDATION_UNSERIALIZABLE : OMIT_VALIDATION_VALUE;
186
+ output2.push(
187
+ projected === OMIT_VALIDATION_VALUE ? null : projected
188
+ );
189
+ }
190
+ return index < length && output2.push(VALIDATION_TRUNCATED), state.preservePrototype || Object.setPrototypeOf(output2, null), output2;
191
+ }
192
+ const output = state.preservePrototype ? {} : /* @__PURE__ */ Object.create(null);
193
+ let truncated = !1, entries = 0, inspected = 0;
194
+ for (const key in value) {
195
+ if (inspected++ >= MAX_VALIDATION_ERROR_CONTAINER_ENTRIES) {
196
+ truncated = !0;
197
+ break;
198
+ }
199
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
200
+ if (!descriptor?.enumerable) continue;
201
+ if (entries >= MAX_VALIDATION_ERROR_CONTAINER_ENTRIES || state.entries >= MAX_VALIDATION_ERROR_ENTRIES || state.nodes >= MAX_VALIDATION_ERROR_NODES) {
202
+ truncated = !0;
203
+ break;
204
+ }
205
+ entries++, state.entries++;
206
+ const projected = "value" in descriptor ? projectValidationValue(descriptor.value, state, depth + 1) : VALIDATION_UNSERIALIZABLE;
207
+ projected !== OMIT_VALIDATION_VALUE && Object.defineProperty(output, boundValidationString(key, state), {
208
+ value: projected,
209
+ enumerable: !0,
210
+ configurable: !0,
211
+ writable: !0
212
+ });
213
+ }
214
+ return truncated && Object.defineProperty(output, VALIDATION_TRUNCATED, {
215
+ value: !0,
216
+ enumerable: !0
217
+ }), output;
218
+ } catch {
219
+ return VALIDATION_UNSERIALIZABLE;
220
+ } finally {
221
+ state.depth.delete(value);
222
+ }
223
+ }, validationSerializationFallback = () => {
224
+ const fallback = /* @__PURE__ */ Object.create(null);
225
+ return fallback.type = "validation", fallback.message = "Validation details exceeded serialization limit", fallback;
226
+ }, projectValidationDetails = (value, preservePrototype = !1) => {
227
+ const projected = projectValidationValue(value, {
228
+ depth: /* @__PURE__ */ new WeakSet(),
229
+ nodes: 0,
230
+ entries: 0,
231
+ strings: 0,
232
+ preservePrototype
233
+ }), result = projected === OMIT_VALIDATION_VALUE ? null : projected;
234
+ try {
235
+ const serialized = JSON.stringify(result);
236
+ if (typeof serialized == "string" && validationOutputFits(serialized))
237
+ return result;
238
+ } catch {
239
+ }
240
+ return validationSerializationFallback();
241
+ }, stringifyValidationDetails = (value, space) => {
242
+ const projected = projectValidationDetails(value);
243
+ try {
244
+ const serialized = JSON.stringify(projected, null, space);
245
+ if (validationOutputFits(serialized)) return serialized;
246
+ } catch {
247
+ }
248
+ return JSON.stringify(validationSerializationFallback(), null, space);
249
+ }, stringifyCustomValidationError = (value) => {
250
+ if (value !== null && typeof value == "object")
251
+ return stringifyValidationDetails(value);
252
+ try {
253
+ return boundValidationString(String(value));
254
+ } catch {
255
+ return VALIDATION_UNSERIALIZABLE;
256
+ }
257
+ }, tryMapValueError = (error) => {
258
+ try {
259
+ return mapValueError(error);
260
+ } catch {
261
+ return;
262
+ }
263
+ }, readValidationDataProperty = (value, key) => {
264
+ if (!(value === null || typeof value != "object"))
265
+ try {
266
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
267
+ if (descriptor && "value" in descriptor) return descriptor.value;
268
+ } catch {
269
+ }
270
+ }, formatStandardValidationPath = (value) => {
271
+ try {
272
+ if (!Array.isArray(value)) return "root";
273
+ const length = Object.getOwnPropertyDescriptor(value, "length")?.value;
274
+ if (typeof length != "number") return "root";
275
+ const output = [];
276
+ let size = 0;
277
+ const limit = Math.min(length, MAX_VALIDATION_ERROR_CONTAINER_ENTRIES);
278
+ for (let index = 0; index < limit; index++) {
279
+ const descriptor = Object.getOwnPropertyDescriptor(
280
+ value,
281
+ `${index}`
282
+ );
283
+ if (!descriptor || !("value" in descriptor)) continue;
284
+ const part = descriptor.value;
285
+ if (typeof part == "string" || typeof part == "number" || typeof part == "boolean" || typeof part == "bigint") {
286
+ const formatted = boundValidationString(String(part));
287
+ if (size += formatted.length + 1, size > MAX_VALIDATION_ERROR_STRING_LENGTH) {
288
+ output.push(VALIDATION_TRUNCATED);
289
+ break;
290
+ }
291
+ output.push(formatted);
292
+ } else output.push(VALIDATION_UNSERIALIZABLE);
293
+ }
294
+ return limit < length && output.push(VALIDATION_TRUNCATED), boundValidationString(output.join(".")) || "root";
295
+ } catch {
296
+ return "root";
297
+ }
298
+ }, takeErrors = (iterator, limit = MAX_ERRORS) => {
299
+ const errors = [];
300
+ for (const error of iterator) {
301
+ if (!error) continue;
302
+ const mapped = tryMapValueError(error);
303
+ if (mapped && errors.push(mapped), errors.length >= limit) break;
304
+ }
305
+ return errors;
91
306
  };
92
307
  class InvalidFileType extends Error {
93
308
  constructor(property, expected, message = `"${property}" has invalid file type`) {
@@ -142,27 +357,39 @@ class ValidationError extends Error {
142
357
  const standard = (
143
358
  // @ts-ignore
144
359
  ("~standard" in validator ? validator : validator.schema)["~standard"]
360
+ ), _errors = errors ?? standard.validate(value).issues;
361
+ error = readValidationDataProperty(_errors, 0);
362
+ const standardErrorPath = readValidationDataProperty(error, "path"), standardErrorMessage = readValidationDataProperty(
363
+ error,
364
+ "message"
365
+ ), standardErrorProblem = readValidationDataProperty(
366
+ error,
367
+ "problem"
145
368
  );
146
- error = (errors ?? standard.validate(value).issues)?.[0], isProduction && !allowUnsafeValidationDetails ? message = JSON.stringify({
369
+ isProduction && !allowUnsafeValidationDetails ? message = stringifyValidationDetails({
147
370
  type: "validation",
148
371
  on: type,
149
372
  found: value
150
- }) : message = JSON.stringify(
373
+ }) : message = stringifyValidationDetails(
151
374
  {
152
375
  type: "validation",
153
376
  on: type,
154
- property: error.path?.[0] || "root",
155
- message: error?.message,
156
- summary: error?.problem,
377
+ property: readValidationDataProperty(standardErrorPath, 0) || "root",
378
+ message: standardErrorMessage,
379
+ summary: standardErrorProblem,
157
380
  expected,
158
381
  found: value,
159
382
  errors
160
383
  },
161
- null,
162
384
  2
163
- ), customError = error?.message;
385
+ ), customError = standardErrorMessage;
164
386
  } else {
165
- value && typeof value == "object" && value instanceof ElysiaCustomStatusResponse && (value = value.response), error = errors?.First() ?? ("Errors" in validator ? validator.Errors(value).First() : Value.Errors(validator, value).First());
387
+ if (value && typeof value == "object")
388
+ try {
389
+ value instanceof ElysiaCustomStatusResponse && (value = value.response);
390
+ } catch {
391
+ }
392
+ error = errors?.First() ?? ("Errors" in validator ? validator.Errors(value).First() : Value.Errors(validator, value).First());
166
393
  const accessor = error?.path || "root", schema = validator?.schema ?? validator;
167
394
  if (!isProduction && !allowUnsafeValidationDetails)
168
395
  try {
@@ -186,41 +413,36 @@ class ValidationError extends Error {
186
413
  value,
187
414
  property: accessor,
188
415
  message: error?.message,
189
- summary: mapValueError(error)?.summary,
416
+ summary: tryMapValueError(error)?.summary,
190
417
  found: value,
191
418
  expected,
192
- errors: "Errors" in validator ? [
193
- ...validator.Errors(
419
+ errors: "Errors" in validator ? takeErrors(
420
+ validator.Errors(
194
421
  value
195
422
  )
196
- ].map(mapValueError) : [
197
- ...Value.Errors(
423
+ ) : takeErrors(
424
+ Value.Errors(
198
425
  validator,
199
426
  value
200
427
  )
201
- ].map(mapValueError)
428
+ )
202
429
  },
203
430
  validator
204
- ) : error.schema.error : void 0, customError !== void 0 ? message = typeof customError == "object" ? JSON.stringify(customError) : customError + "" : isProduction && !allowUnsafeValidationDetails ? message = JSON.stringify({
431
+ ) : error.schema.error : void 0, customError !== void 0 ? message = stringifyCustomValidationError(customError) : isProduction && !allowUnsafeValidationDetails ? message = stringifyValidationDetails({
205
432
  type: "validation",
206
433
  on: type,
207
434
  found: value
208
- }) : message = JSON.stringify(
435
+ }) : message = stringifyValidationDetails(
209
436
  {
210
437
  type: "validation",
211
438
  on: type,
212
439
  property: accessor,
213
440
  message: error?.message,
214
- summary: mapValueError(error)?.summary,
441
+ summary: tryMapValueError(error)?.summary,
215
442
  expected,
216
443
  found: value,
217
- errors: "Errors" in validator ? [...validator.Errors(value)].map(
218
- mapValueError
219
- ) : [...Value.Errors(validator, value)].map(
220
- mapValueError
221
- )
444
+ errors: "Errors" in validator ? takeErrors(validator.Errors(value)) : takeErrors(Value.Errors(validator, value))
222
445
  },
223
- null,
224
446
  2
225
447
  );
226
448
  }
@@ -248,14 +470,19 @@ class ValidationError extends Error {
248
470
  "~standard" in this.validator.schema ? /* @ts-ignore */ ("~standard" in this.validator ? this.validator : (
249
471
  // @ts-ignore
250
472
  this.validator.schema
251
- ))["~standard"].validate(this.value).issues?.map((issue) => ({
252
- summary: issue.message,
253
- path: issue.path?.join(".") || "root",
254
- message: issue.message,
255
- value: this.value
256
- })) || [] : "Errors" in this.validator ? [...this.validator.Errors(this.value)].filter((x) => x).map((x) => mapValueError(x)) : (
473
+ ))["~standard"].validate(this.value).issues?.slice(0, MAX_ERRORS).map((issue) => {
474
+ const message = readValidationDataProperty(issue, "message");
475
+ return {
476
+ summary: message,
477
+ path: formatStandardValidationPath(
478
+ readValidationDataProperty(issue, "path")
479
+ ),
480
+ message,
481
+ value: this.value
482
+ };
483
+ }) || [] : "Errors" in this.validator ? takeErrors(this.validator.Errors(this.value)) : (
257
484
  // @ts-ignore
258
- [...Value.Errors(this.validator, this.value)].map(mapValueError)
485
+ takeErrors(Value.Errors(this.validator, this.value))
259
486
  )
260
487
  );
261
488
  }
@@ -301,22 +528,30 @@ class ValidationError extends Error {
301
528
  */
302
529
  detail(message, allowUnsafeValidatorDetails = this.allowUnsafeValidationDetails) {
303
530
  if (!this.customError) return this.message;
304
- const value = this.value, expected = this.expected, errors = this.all;
305
- return isProduction && !allowUnsafeValidatorDetails ? {
306
- type: "validation",
307
- on: this.type,
308
- found: value,
309
- message
310
- } : {
311
- type: "validation",
312
- on: this.type,
313
- property: this.valueError?.path || "root",
314
- message,
315
- summary: mapValueError(this.valueError)?.summary,
316
- found: value,
317
- expected,
318
- errors
319
- };
531
+ const value = this.value, expected = this.expected;
532
+ let errors = [], property = "root", summary;
533
+ try {
534
+ errors = this.all, property = this.valueError?.path || "root", summary = tryMapValueError(this.valueError)?.summary;
535
+ } catch {
536
+ }
537
+ return projectValidationDetails(
538
+ isProduction && !allowUnsafeValidatorDetails ? {
539
+ type: "validation",
540
+ on: this.type,
541
+ found: value,
542
+ message
543
+ } : {
544
+ type: "validation",
545
+ on: this.type,
546
+ property,
547
+ message,
548
+ summary,
549
+ found: value,
550
+ expected,
551
+ errors
552
+ },
553
+ !0
554
+ );
320
555
  }
321
556
  }
322
557
  export {
@@ -326,6 +561,13 @@ export {
326
561
  InternalServerError,
327
562
  InvalidCookieSignature,
328
563
  InvalidFileType,
564
+ MAX_ERRORS,
565
+ MAX_VALIDATION_ERROR_CONTAINER_ENTRIES,
566
+ MAX_VALIDATION_ERROR_DEPTH,
567
+ MAX_VALIDATION_ERROR_ENTRIES,
568
+ MAX_VALIDATION_ERROR_NODES,
569
+ MAX_VALIDATION_ERROR_OUTPUT_LENGTH,
570
+ MAX_VALIDATION_ERROR_STRING_LENGTH,
329
571
  NotFoundError,
330
572
  ParseError,
331
573
  ValidationError,
@@ -0,0 +1,3 @@
1
+ export declare const parseFormData: (form?: {
2
+ forEach(callback: (value: unknown, key: string, parent: unknown) => void): void;
3
+ }) => Record<string, unknown>;
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: !0 });
9
+ }, __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from == "object" || typeof from == "function")
11
+ for (let key of __getOwnPropNames(from))
12
+ !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ return to;
14
+ };
15
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
16
+ var form_data_exports = {};
17
+ __export(form_data_exports, {
18
+ parseFormData: () => parseFormData
19
+ });
20
+ module.exports = __toCommonJS(form_data_exports);
21
+ const ARRAY_INDEX_REGEX = /^(.+)\[(\d+)\]$/, DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]), MAX_PATH_DEPTH = 32, MAX_ARRAY_INDEX = 1e4, MAX_ASSIGNMENTS = 2e4, spend = (budget, cost = 1) => budget.remaining < cost ? !1 : (budget.remaining -= cost, !0), growArray = (array, index, budget) => index < array.length || spend(budget, index - array.length + 1), isDangerousKey = (key) => {
22
+ if (DANGEROUS_KEYS.has(key)) return !0;
23
+ const match = key.match(ARRAY_INDEX_REGEX);
24
+ return match ? DANGEROUS_KEYS.has(match[1]) : !1;
25
+ }, parseArrayKey = (key) => {
26
+ const match = key.match(ARRAY_INDEX_REGEX);
27
+ if (!match) return;
28
+ const index = Number(match[2]);
29
+ return !Number.isSafeInteger(index) || index > MAX_ARRAY_INDEX ? null : {
30
+ name: match[1],
31
+ index
32
+ };
33
+ }, parseObjectString = (entry) => {
34
+ if (!(typeof entry != "string" || entry.charCodeAt(0) !== 123))
35
+ try {
36
+ const parsed = JSON.parse(entry);
37
+ if (parsed && typeof parsed == "object" && !Array.isArray(parsed))
38
+ return parsed;
39
+ } catch {
40
+ }
41
+ }, normalizeFormValue = (value) => {
42
+ if (value.length === 1) {
43
+ const stringValue2 = value[0];
44
+ if (typeof stringValue2 == "string" && (stringValue2.charCodeAt(0) === 123 || stringValue2.charCodeAt(0) === 91))
45
+ try {
46
+ const parsed2 = JSON.parse(stringValue2);
47
+ if (parsed2 && typeof parsed2 == "object") return parsed2;
48
+ } catch {
49
+ }
50
+ return value[0];
51
+ }
52
+ const stringValue = value.find(
53
+ (entry) => typeof entry == "string"
54
+ );
55
+ if (!stringValue || typeof File > "u") return value;
56
+ const files = value.filter((entry) => entry instanceof File);
57
+ if (!files.length || stringValue.charCodeAt(0) !== 123) return value;
58
+ const parsed = parseObjectString(stringValue);
59
+ return parsed ? (!("file" in parsed) && files.length === 1 ? parsed.file = files[0] : !("files" in parsed) && files.length > 1 && (parsed.files = files), parsed) : value;
60
+ }, setNestedValue = (obj, path, value, budget) => {
61
+ const keys = path.split(".");
62
+ if (keys.length > MAX_PATH_DEPTH) return;
63
+ const lastKey = keys.pop();
64
+ if (isDangerousKey(lastKey) || keys.some(isDangerousKey)) return;
65
+ let current = obj;
66
+ for (const key of keys) {
67
+ const arrayInfo2 = parseArrayKey(key);
68
+ if (arrayInfo2 === null) return;
69
+ if (arrayInfo2) {
70
+ if (!Array.isArray(current[arrayInfo2.name])) {
71
+ if (!spend(budget)) return;
72
+ current[arrayInfo2.name] = [];
73
+ }
74
+ const array = current[arrayInfo2.name];
75
+ if (!growArray(array, arrayInfo2.index, budget)) return;
76
+ const existing = array[arrayInfo2.index], isFile = typeof File < "u" && existing instanceof File;
77
+ if (!existing || typeof existing != "object" || Array.isArray(existing) || isFile) {
78
+ if (!spend(budget)) return;
79
+ array[arrayInfo2.index] = parseObjectString(existing) ?? {};
80
+ }
81
+ current = array[arrayInfo2.index];
82
+ continue;
83
+ }
84
+ if (!current[key] || typeof current[key] != "object") {
85
+ if (!spend(budget)) return;
86
+ current[key] = {};
87
+ }
88
+ current = current[key];
89
+ }
90
+ const arrayInfo = parseArrayKey(lastKey);
91
+ if (arrayInfo !== null) {
92
+ if (arrayInfo) {
93
+ if (!Array.isArray(current[arrayInfo.name])) {
94
+ if (!spend(budget)) return;
95
+ current[arrayInfo.name] = [];
96
+ }
97
+ const array = current[arrayInfo.name];
98
+ if (!growArray(array, arrayInfo.index, budget) || !spend(budget)) return;
99
+ array[arrayInfo.index] = value;
100
+ return;
101
+ }
102
+ spend(budget) && (current[lastKey] = value);
103
+ }
104
+ }, parseFormData = (form) => {
105
+ const body = {};
106
+ if (!form) return body;
107
+ const grouped = /* @__PURE__ */ new Map();
108
+ form.forEach((value, key) => {
109
+ const entries = grouped.get(key);
110
+ entries ? entries.push(value) : grouped.set(key, [value]);
111
+ });
112
+ const budget = { remaining: MAX_ASSIGNMENTS };
113
+ for (const [key, value] of grouped) {
114
+ if (isDangerousKey(key) || Object.prototype.hasOwnProperty.call(body, key))
115
+ continue;
116
+ const finalValue = normalizeFormValue(value);
117
+ key.includes(".") || key.includes("[") ? setNestedValue(body, key, finalValue, budget) : spend(budget) && (body[key] = finalValue);
118
+ }
119
+ return body;
120
+ };
121
+ // Annotate the CommonJS export names for ESM import in node:
122
+ 0 && (module.exports = {
123
+ parseFormData
124
+ });
@@ -0,0 +1,103 @@
1
+ const ARRAY_INDEX_REGEX = /^(.+)\[(\d+)\]$/, DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]), MAX_PATH_DEPTH = 32, MAX_ARRAY_INDEX = 1e4, MAX_ASSIGNMENTS = 2e4, spend = (budget, cost = 1) => budget.remaining < cost ? !1 : (budget.remaining -= cost, !0), growArray = (array, index, budget) => index < array.length || spend(budget, index - array.length + 1), isDangerousKey = (key) => {
2
+ if (DANGEROUS_KEYS.has(key)) return !0;
3
+ const match = key.match(ARRAY_INDEX_REGEX);
4
+ return match ? DANGEROUS_KEYS.has(match[1]) : !1;
5
+ }, parseArrayKey = (key) => {
6
+ const match = key.match(ARRAY_INDEX_REGEX);
7
+ if (!match) return;
8
+ const index = Number(match[2]);
9
+ return !Number.isSafeInteger(index) || index > MAX_ARRAY_INDEX ? null : {
10
+ name: match[1],
11
+ index
12
+ };
13
+ }, parseObjectString = (entry) => {
14
+ if (!(typeof entry != "string" || entry.charCodeAt(0) !== 123))
15
+ try {
16
+ const parsed = JSON.parse(entry);
17
+ if (parsed && typeof parsed == "object" && !Array.isArray(parsed))
18
+ return parsed;
19
+ } catch {
20
+ }
21
+ }, normalizeFormValue = (value) => {
22
+ if (value.length === 1) {
23
+ const stringValue2 = value[0];
24
+ if (typeof stringValue2 == "string" && (stringValue2.charCodeAt(0) === 123 || stringValue2.charCodeAt(0) === 91))
25
+ try {
26
+ const parsed2 = JSON.parse(stringValue2);
27
+ if (parsed2 && typeof parsed2 == "object") return parsed2;
28
+ } catch {
29
+ }
30
+ return value[0];
31
+ }
32
+ const stringValue = value.find(
33
+ (entry) => typeof entry == "string"
34
+ );
35
+ if (!stringValue || typeof File > "u") return value;
36
+ const files = value.filter((entry) => entry instanceof File);
37
+ if (!files.length || stringValue.charCodeAt(0) !== 123) return value;
38
+ const parsed = parseObjectString(stringValue);
39
+ return parsed ? (!("file" in parsed) && files.length === 1 ? parsed.file = files[0] : !("files" in parsed) && files.length > 1 && (parsed.files = files), parsed) : value;
40
+ }, setNestedValue = (obj, path, value, budget) => {
41
+ const keys = path.split(".");
42
+ if (keys.length > MAX_PATH_DEPTH) return;
43
+ const lastKey = keys.pop();
44
+ if (isDangerousKey(lastKey) || keys.some(isDangerousKey)) return;
45
+ let current = obj;
46
+ for (const key of keys) {
47
+ const arrayInfo2 = parseArrayKey(key);
48
+ if (arrayInfo2 === null) return;
49
+ if (arrayInfo2) {
50
+ if (!Array.isArray(current[arrayInfo2.name])) {
51
+ if (!spend(budget)) return;
52
+ current[arrayInfo2.name] = [];
53
+ }
54
+ const array = current[arrayInfo2.name];
55
+ if (!growArray(array, arrayInfo2.index, budget)) return;
56
+ const existing = array[arrayInfo2.index], isFile = typeof File < "u" && existing instanceof File;
57
+ if (!existing || typeof existing != "object" || Array.isArray(existing) || isFile) {
58
+ if (!spend(budget)) return;
59
+ array[arrayInfo2.index] = parseObjectString(existing) ?? {};
60
+ }
61
+ current = array[arrayInfo2.index];
62
+ continue;
63
+ }
64
+ if (!current[key] || typeof current[key] != "object") {
65
+ if (!spend(budget)) return;
66
+ current[key] = {};
67
+ }
68
+ current = current[key];
69
+ }
70
+ const arrayInfo = parseArrayKey(lastKey);
71
+ if (arrayInfo !== null) {
72
+ if (arrayInfo) {
73
+ if (!Array.isArray(current[arrayInfo.name])) {
74
+ if (!spend(budget)) return;
75
+ current[arrayInfo.name] = [];
76
+ }
77
+ const array = current[arrayInfo.name];
78
+ if (!growArray(array, arrayInfo.index, budget) || !spend(budget)) return;
79
+ array[arrayInfo.index] = value;
80
+ return;
81
+ }
82
+ spend(budget) && (current[lastKey] = value);
83
+ }
84
+ }, parseFormData = (form) => {
85
+ const body = {};
86
+ if (!form) return body;
87
+ const grouped = /* @__PURE__ */ new Map();
88
+ form.forEach((value, key) => {
89
+ const entries = grouped.get(key);
90
+ entries ? entries.push(value) : grouped.set(key, [value]);
91
+ });
92
+ const budget = { remaining: MAX_ASSIGNMENTS };
93
+ for (const [key, value] of grouped) {
94
+ if (isDangerousKey(key) || Object.prototype.hasOwnProperty.call(body, key))
95
+ continue;
96
+ const finalValue = normalizeFormValue(value);
97
+ key.includes(".") || key.includes("[") ? setNestedValue(body, key, finalValue, budget) : spend(budget) && (body[key] = finalValue);
98
+ }
99
+ return body;
100
+ };
101
+ export {
102
+ parseFormData
103
+ };
package/dist/index.d.ts CHANGED
@@ -61,6 +61,7 @@ export default class Elysia<const in out BasePath extends string = '', const in
61
61
  '~Ephemeral': Ephemeral;
62
62
  '~Volatile': Volatile;
63
63
  '~Routes': Routes;
64
+ '~cookieConfig': ElysiaConfig<any>['cookie'] | undefined;
64
65
  protected singleton: SingletonBase;
65
66
  get store(): Singleton['store'];
66
67
  get decorator(): Singleton['decorator'];
@@ -1736,6 +1737,7 @@ export default class Elysia<const in out BasePath extends string = '', const in
1736
1737
  config?: {
1737
1738
  allowMeta?: boolean;
1738
1739
  mount?: Function;
1740
+ cookie?: ElysiaConfig<any>['cookie'];
1739
1741
  };
1740
1742
  }): Elysia<BasePath, Singleton, Definitions, Metadata, Routes & CreateEden<JoinPath<BasePath, Path>, {
1741
1743
  [method in Method]: CreateEdenResponse<Path, Schema, MacroContext, ComposeElysiaResponse<Schema & MacroContext & Metadata['standaloneSchema'] & Ephemeral['standaloneSchema'] & Volatile['standaloneSchema'], Handle, UnionResponseStatus<Metadata['response'], UnionResponseStatus<Ephemeral['response'], UnionResponseStatus<Volatile['response'], MacroContext['return'] & {}>>>>>;