elysia 1.0.21 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/handler.mjs CHANGED
@@ -442,7 +442,7 @@ var validateFile = (options, value) => {
442
442
  }
443
443
  return true;
444
444
  };
445
- var File = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
445
+ var File2 = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
446
446
  var Files = TypeRegistry.Get("Files") ?? TypeSystem.Type(
447
447
  "Files",
448
448
  (options, value) => {
@@ -588,7 +588,7 @@ var ElysiaType = {
588
588
  return JSON.stringify(value);
589
589
  });
590
590
  },
591
- File,
591
+ File: File2,
592
592
  Files: (options = {}) => t.Transform(Files(options)).Decode((value) => {
593
593
  if (Array.isArray(value))
594
594
  return value;
@@ -750,6 +750,24 @@ var InvertedStatusMap = Object.fromEntries(
750
750
  Object.entries(StatusMap).map(([k, v]) => [v, k])
751
751
  );
752
752
  var encoder = new TextEncoder();
753
+ var ELYSIA_FORM_DATA = Symbol("ElysiaFormData");
754
+ var form = (items) => {
755
+ const formData = new FormData();
756
+ for (const [key, value] of Object.entries(items)) {
757
+ if (Array.isArray(value)) {
758
+ for (const v of value) {
759
+ if (value instanceof File)
760
+ formData.append(key, value, value.name);
761
+ formData.append(key, v);
762
+ }
763
+ continue;
764
+ }
765
+ if (value instanceof File)
766
+ formData.append(key, value, value.name);
767
+ formData.append(key, value);
768
+ }
769
+ return formData;
770
+ };
753
771
 
754
772
  // src/handler.ts
755
773
  var hasHeaderShorthand = "toJSON" in new Headers();
@@ -857,9 +875,21 @@ var mapResponse = (response, set, request) => {
857
875
  return new Response(response, set);
858
876
  case "Blob":
859
877
  return handleFile(response, set);
860
- case "Object":
861
878
  case "Array":
862
879
  return Response.json(response, set);
880
+ case "Object":
881
+ for (const value in Object.values(response)) {
882
+ switch (value?.constructor?.name) {
883
+ case "Blob":
884
+ case "File":
885
+ case "ArrayBuffer":
886
+ case "FileRef":
887
+ return new Response(form(response));
888
+ default:
889
+ break;
890
+ }
891
+ }
892
+ return Response.json(response, set);
863
893
  case "ReadableStream":
864
894
  if (!set.headers["content-type"]?.startsWith(
865
895
  "text/event-stream"
@@ -933,6 +963,8 @@ var mapResponse = (response, set, request) => {
933
963
  if (response instanceof Cookie)
934
964
  return new Response(response.value, set);
935
965
  return new Response(response?.toString(), set);
966
+ case "FormData":
967
+ return new Response(response, set);
936
968
  default:
937
969
  if (response instanceof Response) {
938
970
  let isCookieSet2 = false;
@@ -992,13 +1024,24 @@ var mapResponse = (response, set, request) => {
992
1024
  return new Response(response);
993
1025
  case "Blob":
994
1026
  return handleFile(response, set);
995
- case "Object":
996
1027
  case "Array":
997
- return new Response(JSON.stringify(response), {
998
- headers: {
999
- "content-type": "application/json"
1028
+ return Response.json(response);
1029
+ case "Object":
1030
+ for (const value in Object.values(response)) {
1031
+ switch (value?.constructor?.name) {
1032
+ case "Blob":
1033
+ case "File":
1034
+ case "ArrayBuffer":
1035
+ case "FileRef":
1036
+ return new Response(
1037
+ form(response),
1038
+ set
1039
+ );
1040
+ default:
1041
+ break;
1000
1042
  }
1001
- });
1043
+ }
1044
+ return Response.json(response, set);
1002
1045
  case "ReadableStream":
1003
1046
  request?.signal.addEventListener(
1004
1047
  "abort",
@@ -1045,6 +1088,8 @@ var mapResponse = (response, set, request) => {
1045
1088
  if (response instanceof Cookie)
1046
1089
  return new Response(response.value, set);
1047
1090
  return new Response(response?.toString(), set);
1091
+ case "FormData":
1092
+ return new Response(response, set);
1048
1093
  default:
1049
1094
  if (response instanceof Response)
1050
1095
  return new Response(response.body, {
@@ -1099,9 +1144,24 @@ var mapEarlyResponse = (response, set, request) => {
1099
1144
  return new Response(response, set);
1100
1145
  case "Blob":
1101
1146
  return handleFile(response, set);
1102
- case "Object":
1103
1147
  case "Array":
1104
1148
  return Response.json(response, set);
1149
+ case "Object":
1150
+ for (const value in Object.values(response)) {
1151
+ switch (value?.constructor?.name) {
1152
+ case "Blob":
1153
+ case "File":
1154
+ case "ArrayBuffer":
1155
+ case "FileRef":
1156
+ return new Response(
1157
+ form(response),
1158
+ set
1159
+ );
1160
+ default:
1161
+ break;
1162
+ }
1163
+ }
1164
+ return Response.json(response, set);
1105
1165
  case "ReadableStream":
1106
1166
  if (!set.headers["content-type"]?.startsWith(
1107
1167
  "text/event-stream"
@@ -1173,6 +1233,8 @@ var mapEarlyResponse = (response, set, request) => {
1173
1233
  response.toString(),
1174
1234
  set
1175
1235
  );
1236
+ case "FormData":
1237
+ return new Response(response);
1176
1238
  case "Cookie":
1177
1239
  if (response instanceof Cookie)
1178
1240
  return new Response(response.value, set);
@@ -1232,13 +1294,24 @@ var mapEarlyResponse = (response, set, request) => {
1232
1294
  return new Response(response);
1233
1295
  case "Blob":
1234
1296
  return handleFile(response, set);
1235
- case "Object":
1236
1297
  case "Array":
1237
- return new Response(JSON.stringify(response), {
1238
- headers: {
1239
- "content-type": "application/json"
1298
+ return Response.json(response);
1299
+ case "Object":
1300
+ for (const value in Object.values(response)) {
1301
+ switch (value?.constructor?.name) {
1302
+ case "Blob":
1303
+ case "File":
1304
+ case "ArrayBuffer":
1305
+ case "FileRef":
1306
+ return new Response(
1307
+ form(response),
1308
+ set
1309
+ );
1310
+ default:
1311
+ break;
1240
1312
  }
1241
- });
1313
+ }
1314
+ return Response.json(response, set);
1242
1315
  case "ReadableStream":
1243
1316
  request?.signal.addEventListener(
1244
1317
  "abort",
@@ -1284,6 +1357,8 @@ var mapEarlyResponse = (response, set, request) => {
1284
1357
  if (response instanceof Cookie)
1285
1358
  return new Response(response.value, set);
1286
1359
  return new Response(response?.toString(), set);
1360
+ case "FormData":
1361
+ return new Response(response);
1287
1362
  default:
1288
1363
  if (response instanceof Response)
1289
1364
  return new Response(response.body, {
@@ -1323,13 +1398,23 @@ var mapCompactResponse = (response, request) => {
1323
1398
  return new Response(response);
1324
1399
  case "Blob":
1325
1400
  return handleFile(response);
1326
- case "Object":
1327
1401
  case "Array":
1328
- return new Response(JSON.stringify(response), {
1329
- headers: {
1330
- "content-type": "application/json"
1331
- }
1332
- });
1402
+ return Response.json(response);
1403
+ case "Object":
1404
+ form:
1405
+ for (const value of Object.values(response))
1406
+ switch (value?.constructor?.name) {
1407
+ case "Blob":
1408
+ case "File":
1409
+ case "ArrayBuffer":
1410
+ case "FileRef":
1411
+ return new Response(form(response));
1412
+ case "Object":
1413
+ break form;
1414
+ default:
1415
+ break;
1416
+ }
1417
+ return Response.json(response);
1333
1418
  case "ReadableStream":
1334
1419
  request?.signal.addEventListener(
1335
1420
  "abort",
@@ -1369,6 +1454,8 @@ var mapCompactResponse = (response, request) => {
1369
1454
  case "Number":
1370
1455
  case "Boolean":
1371
1456
  return new Response(response.toString());
1457
+ case "FormData":
1458
+ return new Response(response);
1372
1459
  default:
1373
1460
  if (response instanceof Response)
1374
1461
  return new Response(response.body, {
package/dist/index.d.ts CHANGED
@@ -1418,7 +1418,7 @@ export { Elysia };
1418
1418
  export { mapResponse, mapCompactResponse, mapEarlyResponse } from './handler';
1419
1419
  export { t } from './type-system';
1420
1420
  export { Cookie, type CookieOptions } from './cookies';
1421
- export { getSchemaValidator, mergeHook, mergeObjectArray, getResponseSchemaValidator, redirect, StatusMap, InvertedStatusMap } from './utils';
1421
+ export { getSchemaValidator, mergeHook, mergeObjectArray, getResponseSchemaValidator, redirect, StatusMap, InvertedStatusMap, form, type ELYSIA_FORM_DATA } from './utils';
1422
1422
  export { error, ParseError, NotFoundError, ValidationError, InternalServerError, InvalidCookieSignature, ERROR_CODE, ELYSIA_RESPONSE } from './error';
1423
1423
  export type { Context, PreContext } from './context';
1424
1424
  export type { EphemeralType, CreateEden, ComposeElysiaResponse, ElysiaConfig, SingletonBase, DefinitionBase, RouteBase, Handler, ComposedHandler, InputSchema, LocalHook, MergeSchema, RouteSchema, UnwrapRoute, InternalRoute, HTTPMethod, SchemaValidator, VoidHandler, PreHandler, BodyHandler, OptionalHandler, ErrorHandler, AfterHandler, LifeCycleEvent, TraceEvent, LifeCycleStore, LifeCycleType, MaybePromise, ListenCallback, UnwrapSchema, TraceHandler, TraceProcess, TraceReporter, TraceStream, Checksum, DocumentDecoration, InferContext, InferHandler } from './types';
package/dist/index.mjs CHANGED
@@ -1135,9 +1135,21 @@ var mapResponse = (response, set, request) => {
1135
1135
  return new Response(response, set);
1136
1136
  case "Blob":
1137
1137
  return handleFile(response, set);
1138
- case "Object":
1139
1138
  case "Array":
1140
1139
  return Response.json(response, set);
1140
+ case "Object":
1141
+ for (const value in Object.values(response)) {
1142
+ switch (value?.constructor?.name) {
1143
+ case "Blob":
1144
+ case "File":
1145
+ case "ArrayBuffer":
1146
+ case "FileRef":
1147
+ return new Response(form(response));
1148
+ default:
1149
+ break;
1150
+ }
1151
+ }
1152
+ return Response.json(response, set);
1141
1153
  case "ReadableStream":
1142
1154
  if (!set.headers["content-type"]?.startsWith(
1143
1155
  "text/event-stream"
@@ -1211,6 +1223,8 @@ var mapResponse = (response, set, request) => {
1211
1223
  if (response instanceof Cookie)
1212
1224
  return new Response(response.value, set);
1213
1225
  return new Response(response?.toString(), set);
1226
+ case "FormData":
1227
+ return new Response(response, set);
1214
1228
  default:
1215
1229
  if (response instanceof Response) {
1216
1230
  let isCookieSet2 = false;
@@ -1270,13 +1284,24 @@ var mapResponse = (response, set, request) => {
1270
1284
  return new Response(response);
1271
1285
  case "Blob":
1272
1286
  return handleFile(response, set);
1273
- case "Object":
1274
1287
  case "Array":
1275
- return new Response(JSON.stringify(response), {
1276
- headers: {
1277
- "content-type": "application/json"
1288
+ return Response.json(response);
1289
+ case "Object":
1290
+ for (const value in Object.values(response)) {
1291
+ switch (value?.constructor?.name) {
1292
+ case "Blob":
1293
+ case "File":
1294
+ case "ArrayBuffer":
1295
+ case "FileRef":
1296
+ return new Response(
1297
+ form(response),
1298
+ set
1299
+ );
1300
+ default:
1301
+ break;
1278
1302
  }
1279
- });
1303
+ }
1304
+ return Response.json(response, set);
1280
1305
  case "ReadableStream":
1281
1306
  request?.signal.addEventListener(
1282
1307
  "abort",
@@ -1323,6 +1348,8 @@ var mapResponse = (response, set, request) => {
1323
1348
  if (response instanceof Cookie)
1324
1349
  return new Response(response.value, set);
1325
1350
  return new Response(response?.toString(), set);
1351
+ case "FormData":
1352
+ return new Response(response, set);
1326
1353
  default:
1327
1354
  if (response instanceof Response)
1328
1355
  return new Response(response.body, {
@@ -1377,9 +1404,24 @@ var mapEarlyResponse = (response, set, request) => {
1377
1404
  return new Response(response, set);
1378
1405
  case "Blob":
1379
1406
  return handleFile(response, set);
1380
- case "Object":
1381
1407
  case "Array":
1382
1408
  return Response.json(response, set);
1409
+ case "Object":
1410
+ for (const value in Object.values(response)) {
1411
+ switch (value?.constructor?.name) {
1412
+ case "Blob":
1413
+ case "File":
1414
+ case "ArrayBuffer":
1415
+ case "FileRef":
1416
+ return new Response(
1417
+ form(response),
1418
+ set
1419
+ );
1420
+ default:
1421
+ break;
1422
+ }
1423
+ }
1424
+ return Response.json(response, set);
1383
1425
  case "ReadableStream":
1384
1426
  if (!set.headers["content-type"]?.startsWith(
1385
1427
  "text/event-stream"
@@ -1451,6 +1493,8 @@ var mapEarlyResponse = (response, set, request) => {
1451
1493
  response.toString(),
1452
1494
  set
1453
1495
  );
1496
+ case "FormData":
1497
+ return new Response(response);
1454
1498
  case "Cookie":
1455
1499
  if (response instanceof Cookie)
1456
1500
  return new Response(response.value, set);
@@ -1510,13 +1554,24 @@ var mapEarlyResponse = (response, set, request) => {
1510
1554
  return new Response(response);
1511
1555
  case "Blob":
1512
1556
  return handleFile(response, set);
1513
- case "Object":
1514
1557
  case "Array":
1515
- return new Response(JSON.stringify(response), {
1516
- headers: {
1517
- "content-type": "application/json"
1558
+ return Response.json(response);
1559
+ case "Object":
1560
+ for (const value in Object.values(response)) {
1561
+ switch (value?.constructor?.name) {
1562
+ case "Blob":
1563
+ case "File":
1564
+ case "ArrayBuffer":
1565
+ case "FileRef":
1566
+ return new Response(
1567
+ form(response),
1568
+ set
1569
+ );
1570
+ default:
1571
+ break;
1518
1572
  }
1519
- });
1573
+ }
1574
+ return Response.json(response, set);
1520
1575
  case "ReadableStream":
1521
1576
  request?.signal.addEventListener(
1522
1577
  "abort",
@@ -1562,6 +1617,8 @@ var mapEarlyResponse = (response, set, request) => {
1562
1617
  if (response instanceof Cookie)
1563
1618
  return new Response(response.value, set);
1564
1619
  return new Response(response?.toString(), set);
1620
+ case "FormData":
1621
+ return new Response(response);
1565
1622
  default:
1566
1623
  if (response instanceof Response)
1567
1624
  return new Response(response.body, {
@@ -1601,13 +1658,23 @@ var mapCompactResponse = (response, request) => {
1601
1658
  return new Response(response);
1602
1659
  case "Blob":
1603
1660
  return handleFile(response);
1604
- case "Object":
1605
1661
  case "Array":
1606
- return new Response(JSON.stringify(response), {
1607
- headers: {
1608
- "content-type": "application/json"
1609
- }
1610
- });
1662
+ return Response.json(response);
1663
+ case "Object":
1664
+ form:
1665
+ for (const value of Object.values(response))
1666
+ switch (value?.constructor?.name) {
1667
+ case "Blob":
1668
+ case "File":
1669
+ case "ArrayBuffer":
1670
+ case "FileRef":
1671
+ return new Response(form(response));
1672
+ case "Object":
1673
+ break form;
1674
+ default:
1675
+ break;
1676
+ }
1677
+ return Response.json(response);
1611
1678
  case "ReadableStream":
1612
1679
  request?.signal.addEventListener(
1613
1680
  "abort",
@@ -1647,6 +1714,8 @@ var mapCompactResponse = (response, request) => {
1647
1714
  case "Number":
1648
1715
  case "Boolean":
1649
1716
  return new Response(response.toString());
1717
+ case "FormData":
1718
+ return new Response(response);
1650
1719
  default:
1651
1720
  if (response instanceof Response)
1652
1721
  return new Response(response.body, {
@@ -2365,12 +2434,25 @@ var cloneInference = (inference) => ({
2365
2434
  set: inference.trace.set
2366
2435
  }
2367
2436
  });
2368
- var redirect = (url, status = 301) => new Response(null, {
2369
- status,
2370
- headers: {
2371
- Location: url
2437
+ var redirect = (url, status = 301) => Response.redirect(url, status);
2438
+ var ELYSIA_FORM_DATA = Symbol("ElysiaFormData");
2439
+ var form = (items) => {
2440
+ const formData = new FormData();
2441
+ for (const [key, value] of Object.entries(items)) {
2442
+ if (Array.isArray(value)) {
2443
+ for (const v of value) {
2444
+ if (value instanceof File)
2445
+ formData.append(key, value, value.name);
2446
+ formData.append(key, v);
2447
+ }
2448
+ continue;
2449
+ }
2450
+ if (value instanceof File)
2451
+ formData.append(key, value, value.name);
2452
+ formData.append(key, value);
2372
2453
  }
2373
- });
2454
+ return formData;
2455
+ };
2374
2456
 
2375
2457
  // src/error.ts
2376
2458
  var env = typeof Bun !== "undefined" ? Bun.env : typeof process !== "undefined" ? process?.env : void 0;
@@ -4034,11 +4116,11 @@ var createDynamicHandler = (app) => async (request) => {
4034
4116
  break;
4035
4117
  case "multipart/form-data":
4036
4118
  body = {};
4037
- const form = await request.formData();
4038
- for (const key of form.keys()) {
4119
+ const form2 = await request.formData();
4120
+ for (const key of form2.keys()) {
4039
4121
  if (body[key])
4040
4122
  continue;
4041
- const value = form.getAll(key);
4123
+ const value = form2.getAll(key);
4042
4124
  if (value.length === 1)
4043
4125
  body[key] = value[0];
4044
4126
  else
@@ -4080,11 +4162,11 @@ var createDynamicHandler = (app) => async (request) => {
4080
4162
  break;
4081
4163
  case "multipart/form-data":
4082
4164
  body = {};
4083
- const form = await request.formData();
4084
- for (const key of form.keys()) {
4165
+ const form2 = await request.formData();
4166
+ for (const key of form2.keys()) {
4085
4167
  if (body[key])
4086
4168
  continue;
4087
- const value = form.getAll(key);
4169
+ const value = form2.getAll(key);
4088
4170
  if (value.length === 1)
4089
4171
  body[key] = value[0];
4090
4172
  else
@@ -4484,7 +4566,7 @@ var validateFile = (options, value) => {
4484
4566
  }
4485
4567
  return true;
4486
4568
  };
4487
- var File = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
4569
+ var File2 = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
4488
4570
  var Files = TypeRegistry.Get("Files") ?? TypeSystem.Type(
4489
4571
  "Files",
4490
4572
  (options, value) => {
@@ -4630,7 +4712,7 @@ var ElysiaType = {
4630
4712
  return JSON.stringify(value);
4631
4713
  });
4632
4714
  },
4633
- File,
4715
+ File: File2,
4634
4716
  Files: (options = {}) => t2.Transform(Files(options)).Decode((value) => {
4635
4717
  if (Array.isArray(value))
4636
4718
  return value;
@@ -4911,7 +4993,9 @@ var Elysia = class _Elysia {
4911
4993
  aot: true,
4912
4994
  strictPath: false,
4913
4995
  global: false,
4914
- cookie: {},
4996
+ cookie: {
4997
+ path: "/"
4998
+ },
4915
4999
  analytic: false,
4916
5000
  ...config,
4917
5001
  experimental: config?.experimental ?? {},
@@ -6592,6 +6676,7 @@ export {
6592
6676
  ValidationError,
6593
6677
  Elysia as default,
6594
6678
  error,
6679
+ form,
6595
6680
  getResponseSchemaValidator,
6596
6681
  getSchemaValidator,
6597
6682
  mapCompactResponse,
@@ -262,6 +262,7 @@ var InvertedStatusMap = Object.fromEntries(
262
262
  Object.entries(StatusMap).map(([k, v]) => [v, k])
263
263
  );
264
264
  var encoder = new TextEncoder();
265
+ var ELYSIA_FORM_DATA = Symbol("ElysiaFormData");
265
266
 
266
267
  // src/error.ts
267
268
  var env = typeof Bun !== "undefined" ? Bun.env : typeof process !== "undefined" ? process?.env : void 0;
@@ -427,7 +428,7 @@ var validateFile = (options, value) => {
427
428
  }
428
429
  return true;
429
430
  };
430
- var File = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
431
+ var File2 = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
431
432
  var Files = TypeRegistry.Get("Files") ?? TypeSystem.Type(
432
433
  "Files",
433
434
  (options, value) => {
@@ -573,7 +574,7 @@ var ElysiaType = {
573
574
  return JSON.stringify(value);
574
575
  });
575
576
  },
576
- File,
577
+ File: File2,
577
578
  Files: (options = {}) => t.Transform(Files(options)).Decode((value) => {
578
579
  if (Array.isArray(value))
579
580
  return value;
package/dist/types.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /// <reference types="bun-types" />
2
2
  /// <reference types="node" />
3
3
  /// <reference types="bun-types" />
4
+ /// <reference types="bun-types" />
4
5
  import type { Elysia } from '.';
5
- import type { Serve, Server, WebSocketHandler } from 'bun';
6
+ import type { BunFile, Serve, Server, WebSocketHandler } from 'bun';
6
7
  import type { TSchema, TObject, StaticDecode, TAnySchema } from '@sinclair/typebox';
7
8
  import type { TypeCheck } from '@sinclair/typebox/compiler';
8
9
  import type { OpenAPIV3 } from 'openapi-types';
@@ -176,8 +177,8 @@ export interface UnwrapRoute<in out Schema extends InputSchema<any>, in out Defi
176
177
  query: UnwrapSchema<Schema['query'], Definitions>;
177
178
  params: UnwrapSchema<Schema['params'], Definitions>;
178
179
  cookie: UnwrapSchema<Schema['cookie'], Definitions>;
179
- response: Schema['response'] extends TSchema | string ? UnwrapSchema<Schema['response'], Definitions> : Schema['response'] extends SuccessfulResponse<TAnySchema | string> ? {
180
- [k in keyof Schema['response']]: UnwrapSchema<Schema['response'][k], Definitions>;
180
+ response: Schema['response'] extends TSchema | string ? CoExist<UnwrapSchema<Schema['response'], Definitions>, File, BunFile> : Schema['response'] extends SuccessfulResponse<TAnySchema | string> ? {
181
+ [k in keyof Schema['response']]: CoExist<UnwrapSchema<Schema['response'][k], Definitions>, File, BunFile>;
181
182
  } : unknown | void;
182
183
  }
183
184
  export interface UnwrapGroupGuardRoute<in out Schema extends InputSchema<any>, in out Definitions extends Record<string, unknown> = {}, Path extends string = ''> {
@@ -235,6 +236,12 @@ export type Handler<in out Route extends RouteSchema = {}, in out Singleton exte
235
236
  derive: {};
236
237
  resolve: {};
237
238
  }, Path extends string = ''> = (context: Context<Route, Singleton, Path>) => Route['response'] extends SuccessfulResponse ? Response | MaybePromise<Route['response'][keyof Route['response']]> : Response | MaybePromise<Route['response']>;
239
+ export type Replace<Original, Target, With> = Original extends Record<string, unknown> ? {
240
+ [K in keyof Original]: Original[K] extends Target ? With : Original[K];
241
+ } : Original extends Target ? With : Original;
242
+ export type CoExist<Original, Target, With> = Original extends Record<string, unknown> ? {
243
+ [K in keyof Original]: Original[K] extends Target ? Original[K] | With : Original[K];
244
+ } : Original extends Target ? Original | With : Original;
238
245
  export type InlineHandler<Route extends RouteSchema = {}, Singleton extends SingletonBase = {
239
246
  decorator: {};
240
247
  store: {};
@@ -572,7 +579,7 @@ type _CreateEden<Path extends string, Property extends Record<string, unknown> =
572
579
  [x in Path]: Property;
573
580
  };
574
581
  export type CreateEden<Path extends string, Property extends Record<string, unknown> = {}> = Path extends `/${infer Rest}` ? _CreateEden<Rest, Property> : Path extends '' ? _CreateEden<'index', Property> : _CreateEden<Path, Property>;
575
- export type ComposeElysiaResponse<Response, Handle> = Handle extends (...a: any[]) => infer A ? _ComposeElysiaResponse<Response, Awaited<A>> : _ComposeElysiaResponse<Response, Awaited<Handle>>;
582
+ export type ComposeElysiaResponse<Response, Handle> = Handle extends (...a: any[]) => infer A ? _ComposeElysiaResponse<Response, Replace<Awaited<A>, BunFile, File>> : _ComposeElysiaResponse<Response, Replace<Awaited<Handle>, BunFile, File>>;
576
583
  type _ComposeElysiaResponse<Response, Handle> = Prettify<unknown extends Response ? {
577
584
  200: Exclude<Handle, {
578
585
  [ELYSIA_RESPONSE]: any;
package/dist/utils.d.ts CHANGED
@@ -1,8 +1,13 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="bun-types" />
3
+ /// <reference types="bun-types" />
4
+ /// <reference types="bun-types" />
1
5
  import { TSchema } from '@sinclair/typebox';
2
6
  import { TypeCheck } from '@sinclair/typebox/compiler';
3
- import type { LifeCycleStore, LocalHook, MaybeArray, InputSchema, LifeCycleType, HookContainer } from './types';
7
+ import type { LifeCycleStore, LocalHook, MaybeArray, InputSchema, LifeCycleType, HookContainer, Replace } from './types';
4
8
  import type { CookieOptions } from './cookies';
5
9
  import { Sucrose } from './sucrose';
10
+ import { BunFile } from 'bun';
6
11
  export declare const replaceUrlPath: (url: string, pathname: string) => string;
7
12
  export declare const mergeDeep: <A extends Record<string, any>, B extends Record<string, any>>(target: A, source: B, { skipKeys }?: {
8
13
  skipKeys?: string[];
@@ -210,5 +215,12 @@ export declare const cloneInference: (inference: {
210
215
  * @param url URL to redirect to
211
216
  * @param HTTP status code to send,
212
217
  */
213
- export declare const redirect: (url: string, status?: number) => import("undici-types").Response;
218
+ export declare const redirect: (url: string, status?: 301 | 302 | 303 | 307 | 308) => import("undici-types").Response;
214
219
  export type redirect = typeof redirect;
220
+ export declare const ELYSIA_FORM_DATA: unique symbol;
221
+ export type ELYSIA_FORM_DATA = typeof ELYSIA_FORM_DATA;
222
+ type ElysiaFormData<T extends Record<string | number, unknown>> = FormData & {
223
+ [ELYSIA_FORM_DATA]: Replace<T, BunFile, File>;
224
+ };
225
+ export declare const form: <const T extends Record<string | number, unknown>>(items: T) => ElysiaFormData<T>;
226
+ export {};
package/dist/utils.mjs CHANGED
@@ -337,7 +337,7 @@ var validateFile = (options, value) => {
337
337
  }
338
338
  return true;
339
339
  };
340
- var File = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
340
+ var File2 = TypeRegistry.Get("Files") ?? TypeSystem.Type("File", validateFile);
341
341
  var Files = TypeRegistry.Get("Files") ?? TypeSystem.Type(
342
342
  "Files",
343
343
  (options, value) => {
@@ -483,7 +483,7 @@ var ElysiaType = {
483
483
  return JSON.stringify(value);
484
484
  });
485
485
  },
486
- File,
486
+ File: File2,
487
487
  Files: (options = {}) => t.Transform(Files(options)).Decode((value) => {
488
488
  if (Array.isArray(value))
489
489
  return value;
@@ -1233,13 +1233,27 @@ var cloneInference = (inference) => ({
1233
1233
  set: inference.trace.set
1234
1234
  }
1235
1235
  });
1236
- var redirect = (url, status = 301) => new Response(null, {
1237
- status,
1238
- headers: {
1239
- Location: url
1236
+ var redirect = (url, status = 301) => Response.redirect(url, status);
1237
+ var ELYSIA_FORM_DATA = Symbol("ElysiaFormData");
1238
+ var form = (items) => {
1239
+ const formData = new FormData();
1240
+ for (const [key, value] of Object.entries(items)) {
1241
+ if (Array.isArray(value)) {
1242
+ for (const v of value) {
1243
+ if (value instanceof File)
1244
+ formData.append(key, value, value.name);
1245
+ formData.append(key, v);
1246
+ }
1247
+ continue;
1248
+ }
1249
+ if (value instanceof File)
1250
+ formData.append(key, value, value.name);
1251
+ formData.append(key, value);
1240
1252
  }
1241
- });
1253
+ return formData;
1254
+ };
1242
1255
  export {
1256
+ ELYSIA_FORM_DATA,
1243
1257
  InvertedStatusMap,
1244
1258
  PromiseGroup,
1245
1259
  StatusMap,
@@ -1249,6 +1263,7 @@ export {
1249
1263
  createMacroManager,
1250
1264
  filterGlobalHook,
1251
1265
  fnToContainer,
1266
+ form,
1252
1267
  getCookieValidator,
1253
1268
  getResponseSchemaValidator,
1254
1269
  getSchemaValidator,