@bepalo/spine 1.0.6 → 1.1.7

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.
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.parseMultipart = exports.parseHeaders = exports.parseBody = exports.SUPPORTED_MEDIA_TYPES_LIST = exports.SUPPORTED_MEDIA_TYPES = exports.parseCookie = exports.parseCookieFromRequest = exports.parseQuery = void 0;
12
+ exports.parseUpload = exports.parseMultipart = exports.defaultFieldParser = exports.parseHeaders = exports.parseBody = exports.SUPPORTED_MEDIA_TYPES_LIST = exports.SUPPORTED_MEDIA_TYPES = exports.parseCookie = exports.parseCookieFromRequest = exports.parseQuery = void 0;
13
13
  const rjson_1 = require("@bepalo/rjson");
14
14
  const types_ts_1 = require("./types.js");
15
15
  const helpers_ts_1 = require("./helpers.js");
@@ -438,6 +438,24 @@ const parseHeaders = (rawHeaders, contentDisposition) => {
438
438
  return headers;
439
439
  };
440
440
  exports.parseHeaders = parseHeaders;
441
+ const defaultFieldParser = (field, contentType) => {
442
+ switch (contentType) {
443
+ case "application/x-www-form-urlencoded": {
444
+ const searchParams = new URLSearchParams(field);
445
+ const parsed = {};
446
+ for (const key of searchParams.keys()) {
447
+ parsed[key] = searchParams.get(key);
448
+ }
449
+ return parsed;
450
+ }
451
+ case "application/json":
452
+ return JSON.parse(field);
453
+ case "application/rjson":
454
+ return rjson_1.RJSON.parse(field);
455
+ }
456
+ return field;
457
+ };
458
+ exports.defaultFieldParser = defaultFieldParser;
441
459
  var ParseMultipartState;
442
460
  (function (ParseMultipartState) {
443
461
  ParseMultipartState[ParseMultipartState["Initializing"] = 0] = "Initializing";
@@ -448,7 +466,7 @@ var ParseMultipartState;
448
466
  ParseMultipartState[ParseMultipartState["ParsingChunk"] = 5] = "ParsingChunk";
449
467
  ParseMultipartState[ParseMultipartState["Done"] = 6] = "Done";
450
468
  })(ParseMultipartState || (ParseMultipartState = {}));
451
- const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataCompletion, }) => {
469
+ const parseMultipart = ({ dontCatch, maxFields, maxFiles, maxFieldSize, maxFileSize, maxTotalSize, idGenerator, onStart, onEnd, onHeader, onData, onDataComplete, onFileLimit, onFieldLimit, onFileSizeLimit, onFieldSizeLimit, onTotalSizeLimit, }) => {
452
470
  const prefix = new TextEncoder().encode("--");
453
471
  const crlfPrefix = new TextEncoder().encode("\r\n--");
454
472
  const endSuffix = new TextEncoder().encode("--");
@@ -459,81 +477,140 @@ const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataC
459
477
  const { request } = ctx;
460
478
  const headers = request.headers;
461
479
  const contentTypeHedaer = (_a = headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.trim();
462
- let error;
463
480
  let boundary = new Uint8Array();
464
481
  let boundaryPre = new Uint8Array();
465
482
  let boundaryPost = new Uint8Array();
483
+ // let error: HttpError | undefined;
466
484
  let response = undefined;
467
- if (request.body == null) {
468
- error = new types_ts_1.HttpError(400, "Empty body");
469
- }
470
- if (error == null &&
471
- (contentTypeHedaer == null ||
485
+ try {
486
+ if (request.body == null) {
487
+ throw new types_ts_1.HttpError(400, "Empty body");
488
+ }
489
+ if (
490
+ // error == null &&
491
+ contentTypeHedaer == null ||
472
492
  !(contentTypeHedaer.length === 19
473
493
  ? contentTypeHedaer.startsWith("multipart/form-data")
474
- : contentTypeHedaer.startsWith("multipart/form-data;")))) {
475
- error = new types_ts_1.HttpError(415, "Invalid header");
476
- }
477
- if (error == null && contentTypeHedaer != null) {
478
- const separatorIndex = contentTypeHedaer.indexOf(";");
479
- const boundaryHeader = separatorIndex != -1 &&
480
- contentTypeHedaer.substring(separatorIndex).trim();
481
- const equalsIndex = boundaryHeader && boundaryHeader.indexOf("=");
482
- const boundaryStr = equalsIndex &&
483
- equalsIndex > -1 &&
484
- boundaryHeader.substring(equalsIndex + 1).trim();
485
- if (!boundaryStr) {
486
- error = new types_ts_1.HttpError(415, "Invalid boundary");
494
+ : contentTypeHedaer.startsWith("multipart/form-data;"))) {
495
+ throw new types_ts_1.HttpError(415, "Invalid header");
487
496
  }
488
- else {
489
- const boundaryBytes = new TextEncoder().encode(boundaryStr);
490
- const boundaryLen = boundaryBytes.length;
491
- const crlfPrefixLen = crlfPrefix.length;
492
- //
493
- boundary = new Uint8Array(prefix.length + boundaryLen);
494
- boundary.set(prefix, 0);
495
- boundary.set(boundaryBytes, prefix.length);
496
- //
497
- boundaryPre = new Uint8Array(crlfPrefixLen + boundaryLen);
498
- boundaryPre.set(crlfPrefix, 0);
499
- boundaryPre.set(boundaryBytes, crlfPrefixLen);
500
- //
501
- boundaryPost = new Uint8Array(prefix.length + boundaryLen + crlf1.length);
502
- boundaryPost.set(prefix, 0);
503
- boundaryPost.set(boundaryBytes, prefix.length);
504
- boundaryPost.set(crlf1, prefix.length + boundaryLen);
497
+ if (contentTypeHedaer != null) {
498
+ const separatorIndex = contentTypeHedaer.indexOf(";");
499
+ const boundaryHeader = separatorIndex != -1 &&
500
+ contentTypeHedaer.substring(separatorIndex).trim();
501
+ const equalsIndex = boundaryHeader && boundaryHeader.indexOf("=");
502
+ const boundaryStr = equalsIndex &&
503
+ equalsIndex > -1 &&
504
+ boundaryHeader.substring(equalsIndex + 1).trim();
505
+ if (!boundaryStr) {
506
+ throw new types_ts_1.HttpError(415, "Invalid boundary");
507
+ }
508
+ else {
509
+ const boundaryBytes = new TextEncoder().encode(boundaryStr);
510
+ const boundaryLen = boundaryBytes.length;
511
+ const crlfPrefixLen = crlfPrefix.length;
512
+ //
513
+ boundary = new Uint8Array(prefix.length + boundaryLen);
514
+ boundary.set(prefix, 0);
515
+ boundary.set(boundaryBytes, prefix.length);
516
+ //
517
+ boundaryPre = new Uint8Array(crlfPrefixLen + boundaryLen);
518
+ boundaryPre.set(crlfPrefix, 0);
519
+ boundaryPre.set(boundaryBytes, crlfPrefixLen);
520
+ //
521
+ boundaryPost = new Uint8Array(prefix.length + boundaryLen + crlf1.length);
522
+ boundaryPost.set(prefix, 0);
523
+ boundaryPost.set(boundaryBytes, prefix.length);
524
+ boundaryPost.set(crlf1, prefix.length + boundaryLen);
525
+ }
505
526
  }
506
- }
507
- // initialize context
508
- ctx.fields = new Map();
509
- ctx.files = new Map();
510
- // start processing body as a stream of chunks
511
- if (error == null && response == null && onStart != null) {
512
- response = yield onStart(ctx);
513
- }
514
- if (error == null && response == null) {
515
- const reader = request.body.getReader();
516
- const crlf_len_1 = crlf2.length - 1;
517
- let parserState = ParseMultipartState.Initializing;
518
- let boundaryIdx = 0;
519
- let crlfIdx = 0;
520
- // find boundary starting from offset and based on boundaryIdx previously set
521
- const findBoundary = (chunk, boundary, offset = 0) => {
522
- const boundary_len_1 = boundary.length - 1;
523
- let i = 0;
524
- let startIdx = -1;
525
- let matching = false;
526
- // check unfinished boundary
527
- if (boundaryIdx > 0) {
527
+ // initialize context
528
+ ctx.fields = new Map();
529
+ ctx.files = new Map();
530
+ ////////////////////////
531
+ // intialize states
532
+ ////////////////////////////
533
+ let initializationStepDone = false;
534
+ let activeHeaders = undefined;
535
+ let activeId = "";
536
+ let activeName = "";
537
+ let activeFilename = undefined;
538
+ let activeChunk = undefined;
539
+ let activeHeaderStart = -1;
540
+ let activeHeaderEnd = -1;
541
+ let activeBodyStart = -1;
542
+ let activeBodyEnd = -1;
543
+ let leftOverBoundary = undefined;
544
+ let leftOverHeader = undefined;
545
+ let expectBoundaryCRLF = 0;
546
+ let headersChunks = [];
547
+ let fileInfo = undefined;
548
+ let totalFields = 0;
549
+ let totalFiles = 0;
550
+ let activeFieldSize = 0;
551
+ let activeFileSize = 0;
552
+ let streamIsDone = false;
553
+ // start processing body as a stream of chunks
554
+ if (response == null && onStart != null) {
555
+ response = yield onStart(ctx);
556
+ }
557
+ if (response == null) {
558
+ const reader = request.body.getReader();
559
+ const crlf_len_1 = crlf2.length - 1;
560
+ let parserState = ParseMultipartState.Initializing;
561
+ let boundaryIdx = 0;
562
+ let crlfIdx = 0;
563
+ const getNextChunk = () => __awaiter(void 0, void 0, void 0, function* () {
564
+ const { done, value } = yield reader.read();
565
+ if (done) {
566
+ streamIsDone = done;
567
+ }
568
+ return value;
569
+ });
570
+ // find boundary starting from offset and based on boundaryIdx previously set
571
+ const findBoundary = (chunk, boundary, offset = 0) => {
572
+ const boundary_len_1 = boundary.length - 1;
573
+ let i = 0;
574
+ let startIdx = -1;
575
+ let matching = false;
576
+ // check unfinished boundary
577
+ if (boundaryIdx > 0) {
578
+ for (i = offset; i < chunk.length; i++) {
579
+ if (chunk[i] === boundary[boundaryIdx]) {
580
+ if (!matching && boundaryIdx < boundary_len_1) {
581
+ matching = true;
582
+ startIdx = i;
583
+ }
584
+ else if (boundaryIdx === boundary_len_1) {
585
+ boundaryIdx = 0;
586
+ return [!matching ? 0 : startIdx, i + 1, true, false];
587
+ }
588
+ boundaryIdx++;
589
+ }
590
+ else if (matching) {
591
+ boundaryIdx = 0;
592
+ startIdx = -1;
593
+ matching = false;
594
+ }
595
+ }
596
+ // boundary spans whole chunk
597
+ if (matching && i >= chunk.length) {
598
+ return [startIdx < 0 ? 0 : startIdx, -1, false, true];
599
+ }
600
+ else {
601
+ boundaryIdx = 0;
602
+ matching = false;
603
+ }
604
+ }
528
605
  for (i = offset; i < chunk.length; i++) {
529
606
  if (chunk[i] === boundary[boundaryIdx]) {
530
- if (!matching && boundaryIdx < boundary_len_1) {
607
+ if (!matching) {
531
608
  matching = true;
532
609
  startIdx = i;
533
610
  }
534
611
  else if (boundaryIdx === boundary_len_1) {
535
612
  boundaryIdx = 0;
536
- return [!matching ? 0 : startIdx, i + 1, true, false];
613
+ return [startIdx, i + 1, false, false];
537
614
  }
538
615
  boundaryIdx++;
539
616
  }
@@ -543,50 +620,44 @@ const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataC
543
620
  matching = false;
544
621
  }
545
622
  }
546
- // boundary spans whole chunk
547
- if (matching && i >= chunk.length) {
548
- return [startIdx < 0 ? 0 : startIdx, -1, false, true];
549
- }
550
- else {
551
- boundaryIdx = 0;
552
- matching = false;
553
- }
554
- }
555
- for (i = offset; i < chunk.length; i++) {
556
- if (chunk[i] === boundary[boundaryIdx]) {
557
- if (!matching) {
558
- matching = true;
559
- startIdx = i;
560
- }
561
- else if (boundaryIdx === boundary_len_1) {
562
- boundaryIdx = 0;
563
- return [startIdx, i + 1, false, false];
623
+ return [startIdx, -1, false, false];
624
+ };
625
+ // find \r\n\r\n starting from offset and based on crlfIdx previously set
626
+ const findCRLF = (chunk, offset = 0) => {
627
+ let i = 0;
628
+ let startIdx = -1;
629
+ let matching = false;
630
+ if (crlfIdx > 0) {
631
+ for (i = offset; i < chunk.length; i++) {
632
+ if (chunk[i] === crlf2[crlfIdx]) {
633
+ if (!matching && crlfIdx < crlf_len_1) {
634
+ matching = true;
635
+ startIdx = i;
636
+ }
637
+ else if (crlfIdx === crlf_len_1) {
638
+ crlfIdx = 0;
639
+ return [!matching ? 0 : startIdx, i + 1, true];
640
+ }
641
+ crlfIdx++;
642
+ }
643
+ else if (matching) {
644
+ crlfIdx = 0;
645
+ startIdx = -1;
646
+ matching = false;
647
+ }
564
648
  }
565
- boundaryIdx++;
566
- }
567
- else if (matching) {
568
- boundaryIdx = 0;
569
- startIdx = -1;
649
+ crlfIdx = 0;
570
650
  matching = false;
571
651
  }
572
- }
573
- return [startIdx, -1, false, false];
574
- };
575
- // find \r\n\r\n starting from offset and based on crlfIdx previously set
576
- const findCRLF = (chunk, offset = 0) => {
577
- let i = 0;
578
- let startIdx = -1;
579
- let matching = false;
580
- if (crlfIdx > 0) {
581
652
  for (i = offset; i < chunk.length; i++) {
582
653
  if (chunk[i] === crlf2[crlfIdx]) {
583
- if (!matching && crlfIdx < crlf_len_1) {
654
+ if (!matching) {
584
655
  matching = true;
585
656
  startIdx = i;
586
657
  }
587
658
  else if (crlfIdx === crlf_len_1) {
588
659
  crlfIdx = 0;
589
- return [!matching ? 0 : startIdx, i + 1, true];
660
+ return [startIdx, i + 1, false];
590
661
  }
591
662
  crlfIdx++;
592
663
  }
@@ -596,143 +667,92 @@ const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataC
596
667
  matching = false;
597
668
  }
598
669
  }
599
- crlfIdx = 0;
600
- matching = false;
601
- }
602
- for (i = offset; i < chunk.length; i++) {
603
- if (chunk[i] === crlf2[crlfIdx]) {
604
- if (!matching) {
605
- matching = true;
606
- startIdx = i;
607
- }
608
- else if (crlfIdx === crlf_len_1) {
609
- crlfIdx = 0;
610
- return [startIdx, i + 1, false];
670
+ return [startIdx, -1, false];
671
+ };
672
+ // onData wrapper
673
+ const _onData = (ctx, chunk, info) => __awaiter(void 0, void 0, void 0, function* () {
674
+ let response = undefined;
675
+ const { file } = info;
676
+ if (file != null) {
677
+ file.size += chunk.length;
678
+ activeFileSize += chunk.length;
679
+ if (maxFileSize != null &&
680
+ ((file.totalSize && file.totalSize > maxFileSize) ||
681
+ activeFileSize > maxFileSize)) {
682
+ if (onFileSizeLimit != null) {
683
+ response = yield onFileSizeLimit(ctx, info);
684
+ }
685
+ if (response == null) {
686
+ throw new types_ts_1.HttpError(413, "File too large");
687
+ // return undefined;
688
+ }
611
689
  }
612
- crlfIdx++;
613
690
  }
614
- else if (matching) {
615
- crlfIdx = 0;
616
- startIdx = -1;
617
- matching = false;
618
- }
619
- }
620
- return [startIdx, -1, false];
621
- };
622
- ////////////////////////
623
- let streamIsDone = false;
624
- const getNextChunk = () => __awaiter(void 0, void 0, void 0, function* () {
625
- const { done, value } = yield reader.read();
626
- if (done) {
627
- streamIsDone = done;
628
- }
629
- return value;
630
- });
631
- ////////////////////////////
632
- let initializationStepDone = false;
633
- let activeHeaders = undefined;
634
- let activeId = "";
635
- let activeName = "";
636
- let activeFilename = undefined;
637
- let activeChunk = undefined;
638
- let activeHeaderStart = -1;
639
- let activeHeaderEnd = -1;
640
- let activeBodyStart = -1;
641
- let activeBodyEnd = -1;
642
- let leftOverBoundary = undefined;
643
- let leftOverHeader = undefined;
644
- let expectBoundaryCRLF = 0;
645
- let headersChunks = [];
646
- let fileInfo = undefined;
647
- ///////////////////////////////////////
648
- away: while (parserState !== ParseMultipartState.Done) {
649
- switch (parserState) {
650
- case ParseMultipartState.Initializing: {
651
- activeChunk = yield getNextChunk();
652
- parserState = ParseMultipartState.FindingBoundary;
653
- activeHeaderStart = -1;
654
- activeHeaderEnd = -1;
655
- activeBodyStart = -1;
656
- activeBodyEnd = -1;
657
- break;
658
- }
659
- case ParseMultipartState.FindingBoundary: {
660
- if (activeChunk == null) {
661
- if (!streamIsDone) {
662
- error = new types_ts_1.HttpError(400, "Invalid body");
691
+ else {
692
+ activeFieldSize += chunk.length;
693
+ if (maxFieldSize != null && activeFieldSize > maxFieldSize) {
694
+ if (onFieldSizeLimit != null) {
695
+ response = yield onFieldSizeLimit(ctx, info);
696
+ }
697
+ if (response == null) {
698
+ throw new types_ts_1.HttpError(413, "Field too large");
699
+ // return undefined;
663
700
  }
664
- break away;
665
701
  }
666
- // find start boundary
667
- const [boundaryStart, boundaryEnd, leftOverMatch, leftOverCompleteMatch,] = findBoundary(activeChunk, initializationStepDone ? boundaryPre : boundary, activeHeaderEnd < 0 ? 0 : activeHeaderEnd + 2);
668
- if (streamIsDone &&
669
- ((boundaryEnd != -1 &&
670
- activeChunk[boundaryEnd] === endSuffix[0] &&
671
- activeChunk[boundaryEnd + 1] === endSuffix[1]) ||
672
- boundaryStart + 2 >= boundaryEnd)) {
673
- break away;
702
+ }
703
+ if (maxTotalSize != null &&
704
+ activeFileSize + activeFieldSize > maxTotalSize) {
705
+ if (onTotalSizeLimit != null) {
706
+ response = yield onTotalSizeLimit(ctx, info);
674
707
  }
675
- if (!initializationStepDone && boundaryStart < 0) {
676
- error = new types_ts_1.HttpError(400, "Invalid body");
677
- break away;
708
+ if (response == null) {
709
+ throw new types_ts_1.HttpError(413, "Payload too large");
710
+ // return undefined;
678
711
  }
679
- // check for leftOverBoundary
680
- if (leftOverBoundary != null &&
681
- !leftOverMatch &&
682
- !leftOverCompleteMatch &&
683
- boundaryIdx === 0) {
684
- if (fileInfo != null) {
685
- fileInfo.size += leftOverBoundary.length;
686
- }
687
- response = yield onData(ctx, {
688
- chunk: leftOverBoundary,
689
- headers: activeHeaders,
690
- id: activeId,
691
- name: activeName,
692
- filename: activeFilename,
693
- file: fileInfo,
694
- });
695
- if (response != null) {
696
- break away;
697
- }
698
- leftOverBoundary = undefined;
712
+ }
713
+ if (response == null) {
714
+ response = yield onData(ctx, chunk, info);
715
+ }
716
+ return response;
717
+ });
718
+ ///////////////////////////////////////
719
+ away: while (parserState !== ParseMultipartState.Done) {
720
+ switch (parserState) {
721
+ case ParseMultipartState.Initializing: {
722
+ activeChunk = yield getNextChunk();
723
+ parserState = ParseMultipartState.FindingBoundary;
724
+ activeHeaderStart = -1;
725
+ activeHeaderEnd = -1;
726
+ activeBodyStart = -1;
727
+ activeBodyEnd = -1;
728
+ break;
699
729
  }
700
- else if (leftOverMatch) {
701
- if (initializationStepDone && onDataCompletion != null) {
702
- response = yield onDataCompletion(ctx, {
703
- headers: activeHeaders,
704
- id: activeId,
705
- name: activeName,
706
- filename: activeFilename,
707
- file: fileInfo,
708
- });
709
- if (response != null) {
710
- break away;
730
+ case ParseMultipartState.FindingBoundary: {
731
+ if (activeChunk == null) {
732
+ if (!streamIsDone) {
733
+ throw new types_ts_1.HttpError(400, "Invalid body");
711
734
  }
735
+ break away;
712
736
  }
713
- leftOverBoundary = undefined;
714
- }
715
- if (leftOverCompleteMatch) {
716
- activeBodyEnd = -1;
717
- activeHeaderStart = -1;
718
- }
719
- else {
720
- activeBodyEnd = boundaryStart;
721
- activeHeaderStart = boundaryEnd + 2;
722
- }
723
- // keep looking if not found
724
- if (boundaryStart < 0) {
725
- if (streamIsDone) {
726
- error = new types_ts_1.HttpError(400, "Invalid body");
737
+ // find start boundary
738
+ const [boundaryStart, boundaryEnd, leftOverMatch, leftOverCompleteMatch,] = findBoundary(activeChunk, initializationStepDone ? boundaryPre : boundary, activeHeaderEnd < 0 ? 0 : activeHeaderEnd + 2);
739
+ if (streamIsDone &&
740
+ ((boundaryEnd != -1 &&
741
+ activeChunk[boundaryEnd] === endSuffix[0] &&
742
+ activeChunk[boundaryEnd + 1] === endSuffix[1]) ||
743
+ boundaryStart + 2 >= boundaryEnd)) {
727
744
  break away;
728
745
  }
729
- if (initializationStepDone && activeBodyStart != -1) {
730
- const chunk = activeChunk.subarray(activeBodyStart, activeChunk.length - boundaryIdx);
731
- if (fileInfo != null) {
732
- fileInfo.size += chunk.length;
733
- }
734
- response = yield onData(ctx, {
735
- chunk,
746
+ if (!initializationStepDone && boundaryStart < 0) {
747
+ throw new types_ts_1.HttpError(400, "Invalid body");
748
+ // break away;
749
+ }
750
+ // check for leftOverBoundary
751
+ if (leftOverBoundary != null &&
752
+ !leftOverMatch &&
753
+ !leftOverCompleteMatch &&
754
+ boundaryIdx === 0) {
755
+ response = yield _onData(ctx, leftOverBoundary, {
736
756
  headers: activeHeaders,
737
757
  id: activeId,
738
758
  name: activeName,
@@ -742,245 +762,317 @@ const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataC
742
762
  if (response != null) {
743
763
  break away;
744
764
  }
765
+ leftOverBoundary = undefined;
745
766
  }
746
- activeChunk = yield getNextChunk();
747
- activeHeaderStart = -1;
748
- activeHeaderEnd = -1;
749
- activeBodyStart = 0;
750
- activeBodyEnd = -1;
751
- continue;
752
- }
753
- // keep looking for the boundaryEnd in the next chunk
754
- if (boundaryEnd < 0) {
755
- if (streamIsDone) {
756
- error = new types_ts_1.HttpError(400, "Invalid body");
757
- break away;
767
+ else if (leftOverMatch) {
768
+ if (initializationStepDone && onDataComplete != null) {
769
+ response = yield onDataComplete(ctx, {
770
+ headers: activeHeaders,
771
+ id: activeId,
772
+ name: activeName,
773
+ filename: activeFilename,
774
+ file: fileInfo,
775
+ });
776
+ activeFilename = undefined;
777
+ if (response != null) {
778
+ break away;
779
+ }
780
+ }
781
+ else if (initializationStepDone) {
782
+ activeFilename = undefined;
783
+ }
784
+ leftOverBoundary = undefined;
758
785
  }
759
- if (leftOverBoundary != null && boundaryStart !== -1) {
760
- const currentLeftOver = activeChunk.subarray(boundaryStart, activeChunk.length - boundaryStart);
761
- const newLeftOver = new Uint8Array(leftOverBoundary.length + currentLeftOver.length);
762
- newLeftOver.set(leftOverBoundary, 0);
763
- newLeftOver.set(currentLeftOver, leftOverBoundary.length);
764
- leftOverBoundary = newLeftOver;
786
+ if (leftOverCompleteMatch) {
787
+ activeBodyEnd = -1;
788
+ activeHeaderStart = -1;
765
789
  }
766
790
  else {
767
- leftOverBoundary = activeChunk.subarray(activeChunk.length - boundaryIdx);
791
+ activeBodyEnd = boundaryStart;
792
+ activeHeaderStart = boundaryEnd + 2;
768
793
  }
769
- if (!leftOverCompleteMatch && activeBodyEnd > 0) {
770
- const chunk = activeChunk.subarray(activeBodyStart, activeBodyEnd);
771
- if (fileInfo != null) {
772
- fileInfo.size += chunk.length;
794
+ // keep looking if not found
795
+ if (boundaryStart < 0) {
796
+ if (streamIsDone) {
797
+ throw new types_ts_1.HttpError(400, "Invalid body");
798
+ // break away;
773
799
  }
774
- response = yield onData(ctx, {
775
- chunk,
776
- headers: activeHeaders,
777
- id: activeId,
778
- name: activeName,
779
- filename: activeFilename,
780
- file: fileInfo,
781
- });
782
- if (response != null) {
783
- break away;
800
+ if (initializationStepDone && activeBodyStart != -1) {
801
+ const chunk = activeChunk.subarray(activeBodyStart, activeChunk.length - boundaryIdx);
802
+ response = yield _onData(ctx, chunk, {
803
+ headers: activeHeaders,
804
+ id: activeId,
805
+ name: activeName,
806
+ filename: activeFilename,
807
+ file: fileInfo,
808
+ });
809
+ if (response != null) {
810
+ break away;
811
+ }
784
812
  }
813
+ activeChunk = yield getNextChunk();
814
+ activeHeaderStart = -1;
815
+ activeHeaderEnd = -1;
816
+ activeBodyStart = 0;
817
+ activeBodyEnd = -1;
818
+ continue;
785
819
  }
786
- activeChunk = yield getNextChunk();
787
- activeHeaderStart = -1;
788
- activeHeaderEnd = -1;
789
- activeBodyStart = 0;
790
- activeBodyEnd = -1;
791
- continue;
792
- }
793
- if (!leftOverCompleteMatch &&
794
- boundaryEnd > activeChunk.length - crlf1.length) {
795
- expectBoundaryCRLF =
796
- crlf1.length - (activeChunk.length - boundaryEnd);
797
- }
798
- else {
799
- expectBoundaryCRLF = 0;
800
- }
801
- parserState = initializationStepDone
802
- ? ParseMultipartState.ParsingChunk
803
- : ParseMultipartState.FindingCRLF;
804
- if (!initializationStepDone) {
805
- initializationStepDone = true;
806
- }
807
- break;
808
- }
809
- case ParseMultipartState.FindingCRLF: {
810
- if (activeChunk == null) {
811
- if (!streamIsDone) {
812
- error = new types_ts_1.HttpError(400, "Invalid body");
820
+ // keep looking for the boundaryEnd in the next chunk
821
+ if (boundaryEnd < 0) {
822
+ if (streamIsDone) {
823
+ throw new types_ts_1.HttpError(400, "Invalid body");
824
+ // break away;
825
+ }
826
+ if (leftOverBoundary != null && boundaryStart !== -1) {
827
+ const currentLeftOver = activeChunk.subarray(boundaryStart, activeChunk.length - boundaryStart);
828
+ const newLeftOver = new Uint8Array(leftOverBoundary.length + currentLeftOver.length);
829
+ newLeftOver.set(leftOverBoundary, 0);
830
+ newLeftOver.set(currentLeftOver, leftOverBoundary.length);
831
+ leftOverBoundary = newLeftOver;
832
+ }
833
+ else {
834
+ leftOverBoundary = activeChunk.subarray(activeChunk.length - boundaryIdx);
835
+ }
836
+ if (!leftOverCompleteMatch && activeBodyEnd > 0) {
837
+ const chunk = activeChunk.subarray(activeBodyStart, activeBodyEnd);
838
+ response = yield _onData(ctx, chunk, {
839
+ headers: activeHeaders,
840
+ id: activeId,
841
+ name: activeName,
842
+ filename: activeFilename,
843
+ file: fileInfo,
844
+ });
845
+ if (response != null) {
846
+ break away;
847
+ }
848
+ }
849
+ activeChunk = yield getNextChunk();
850
+ activeHeaderStart = -1;
851
+ activeHeaderEnd = -1;
852
+ activeBodyStart = 0;
853
+ activeBodyEnd = -1;
854
+ continue;
813
855
  }
814
- break away;
815
- }
816
- if (activeHeaderStart < 0) {
817
- if (expectBoundaryCRLF > 0) {
818
- activeHeaderStart = expectBoundaryCRLF;
819
- expectBoundaryCRLF = 0;
856
+ if (!leftOverCompleteMatch &&
857
+ boundaryEnd > activeChunk.length - crlf1.length) {
858
+ expectBoundaryCRLF =
859
+ crlf1.length - (activeChunk.length - boundaryEnd);
820
860
  }
821
861
  else {
822
- activeHeaderStart = 0;
862
+ expectBoundaryCRLF = 0;
823
863
  }
864
+ parserState = initializationStepDone
865
+ ? ParseMultipartState.ParsingChunk
866
+ : ParseMultipartState.FindingCRLF;
867
+ if (!initializationStepDone) {
868
+ initializationStepDone = true;
869
+ }
870
+ break;
824
871
  }
825
- // find crlf2
826
- const [crlfStart, crlfEnd, leftOverHeaderMatch] = findCRLF(activeChunk, activeHeaderStart);
827
- // check for leftOverHeader
828
- if (leftOverHeader != null && !leftOverHeaderMatch) {
829
- headersChunks.push(leftOverHeader);
830
- leftOverHeader = undefined;
831
- }
832
- // keep looking if not found
833
- if (crlfStart < 0) {
834
- if (streamIsDone) {
835
- error = new types_ts_1.HttpError(400, "Invalid body");
872
+ case ParseMultipartState.FindingCRLF: {
873
+ if (activeChunk == null) {
874
+ if (!streamIsDone) {
875
+ throw new types_ts_1.HttpError(400, "Invalid body");
876
+ }
836
877
  break away;
837
878
  }
838
- const headerChunk = activeChunk.subarray(activeHeaderStart, activeChunk.length);
839
- headersChunks.push(headerChunk);
840
- activeChunk = yield getNextChunk();
841
- activeHeaderStart = -1;
842
- activeHeaderEnd = -1;
843
- activeBodyStart = -1;
844
- activeBodyEnd = -1;
845
- continue;
879
+ if (activeHeaderStart < 0) {
880
+ if (expectBoundaryCRLF > 0) {
881
+ activeHeaderStart = expectBoundaryCRLF;
882
+ expectBoundaryCRLF = 0;
883
+ }
884
+ else {
885
+ activeHeaderStart = 0;
886
+ }
887
+ }
888
+ // find crlf2
889
+ const [crlfStart, crlfEnd, leftOverHeaderMatch] = findCRLF(activeChunk, activeHeaderStart);
890
+ // check for leftOverHeader
891
+ if (leftOverHeader != null && !leftOverHeaderMatch) {
892
+ headersChunks.push(leftOverHeader);
893
+ leftOverHeader = undefined;
894
+ }
895
+ // keep looking if not found
896
+ if (crlfStart < 0) {
897
+ if (streamIsDone) {
898
+ throw new types_ts_1.HttpError(400, "Invalid body");
899
+ break away;
900
+ }
901
+ const headerChunk = activeChunk.subarray(activeHeaderStart, activeChunk.length);
902
+ headersChunks.push(headerChunk);
903
+ activeChunk = yield getNextChunk();
904
+ activeHeaderStart = -1;
905
+ activeHeaderEnd = -1;
906
+ activeBodyStart = -1;
907
+ activeBodyEnd = -1;
908
+ continue;
909
+ }
910
+ activeHeaderEnd = crlfStart;
911
+ // keep looking for the crlfEnd in the next chunk
912
+ if (crlfEnd < 0) {
913
+ if (streamIsDone) {
914
+ throw new types_ts_1.HttpError(400, "Invalid body");
915
+ // break away;
916
+ }
917
+ if (leftOverHeader != null) {
918
+ const currentLeftOver = activeChunk.subarray(activeHeaderEnd);
919
+ const newLeftOver = new Uint8Array(leftOverHeader.length + currentLeftOver.length);
920
+ newLeftOver.set(leftOverHeader, 0);
921
+ newLeftOver.set(currentLeftOver, leftOverHeader.length);
922
+ leftOverBoundary = newLeftOver;
923
+ }
924
+ else {
925
+ leftOverHeader = activeChunk.subarray(activeHeaderEnd);
926
+ }
927
+ const headerChunk = activeChunk.subarray(activeHeaderStart, activeHeaderEnd);
928
+ headersChunks.push(headerChunk);
929
+ activeChunk = yield getNextChunk();
930
+ activeHeaderStart = 0;
931
+ activeHeaderEnd = -1;
932
+ activeBodyStart = -1;
933
+ activeBodyEnd = -1;
934
+ continue;
935
+ }
936
+ activeBodyStart = crlfEnd;
937
+ if (activeHeaderStart != -1) {
938
+ const headerChunk = activeChunk.subarray(activeHeaderStart, activeHeaderEnd);
939
+ headersChunks.push(headerChunk);
940
+ }
941
+ parserState = ParseMultipartState.ParsingHeaders;
942
+ break;
846
943
  }
847
- activeHeaderEnd = crlfStart;
848
- // keep looking for the crlfEnd in the next chunk
849
- if (crlfEnd < 0) {
850
- if (streamIsDone) {
851
- error = new types_ts_1.HttpError(400, "Invalid body");
944
+ case ParseMultipartState.ParsingHeaders: {
945
+ if (activeChunk == null) {
946
+ if (!streamIsDone) {
947
+ throw new types_ts_1.HttpError(400, "Invalid body");
948
+ }
852
949
  break away;
853
950
  }
854
- if (leftOverHeader != null) {
855
- const currentLeftOver = activeChunk.subarray(activeHeaderEnd);
856
- const newLeftOver = new Uint8Array(leftOverHeader.length + currentLeftOver.length);
857
- newLeftOver.set(leftOverHeader, 0);
858
- newLeftOver.set(currentLeftOver, leftOverHeader.length);
859
- leftOverBoundary = newLeftOver;
951
+ let buffer = headersChunks.length === 1 ? headersChunks[0] : undefined;
952
+ if (headersChunks.length > 1) {
953
+ let requiredSize = 0;
954
+ let bufferOffset = 0;
955
+ for (const headerChunk of headersChunks) {
956
+ requiredSize += headerChunk.length;
957
+ }
958
+ buffer = new Uint8Array(requiredSize);
959
+ for (const headerChunk of headersChunks) {
960
+ if (headerChunk.length === 0) {
961
+ continue;
962
+ }
963
+ buffer.set(headerChunk, bufferOffset);
964
+ bufferOffset += headerChunk.length;
965
+ }
860
966
  }
861
- else {
862
- leftOverHeader = activeChunk.subarray(activeHeaderEnd);
967
+ headersChunks = [];
968
+ leftOverHeader = undefined;
969
+ const contentDisposition = {};
970
+ activeHeaders = (0, exports.parseHeaders)(new Uint8Array(buffer), contentDisposition);
971
+ if (contentDisposition["name"] == null) {
972
+ throw new types_ts_1.HttpError(400, "Invalid Content-Disposition header");
863
973
  }
864
- const headerChunk = activeChunk.subarray(activeHeaderStart, activeHeaderEnd);
865
- headersChunks.push(headerChunk);
866
- activeChunk = yield getNextChunk();
867
- activeHeaderStart = 0;
868
- activeHeaderEnd = -1;
869
- activeBodyStart = -1;
870
- activeBodyEnd = -1;
871
- continue;
872
- }
873
- activeBodyStart = crlfEnd;
874
- if (activeHeaderStart != -1) {
875
- const headerChunk = activeChunk.subarray(activeHeaderStart, activeHeaderEnd);
876
- headersChunks.push(headerChunk);
877
- }
878
- parserState = ParseMultipartState.ParsingHeaders;
879
- break;
880
- }
881
- case ParseMultipartState.ParsingHeaders: {
882
- if (activeChunk == null) {
883
- if (!streamIsDone) {
884
- error = new types_ts_1.HttpError(400, "Invalid body");
974
+ // intialize for formdata part
975
+ activeName = contentDisposition.name;
976
+ activeFilename = contentDisposition.filename;
977
+ activeId =
978
+ idGenerator != null
979
+ ? idGenerator({
980
+ headers: activeHeaders,
981
+ name: activeName,
982
+ filename: activeFilename,
983
+ })
984
+ : (0, utils_ts_1.toBase64UUID)(crypto.randomUUID());
985
+ if (activeFilename != null) {
986
+ const contentTypeHeader = activeHeaders.get("content-type");
987
+ const contentLengthHeader = activeHeaders.get("content-length");
988
+ const size = 0;
989
+ const totalSize = contentLengthHeader
990
+ ? parseInt(contentLengthHeader)
991
+ : null;
992
+ const type = (contentTypeHeader
993
+ ? contentTypeHeader
994
+ : "application/octet-stream");
995
+ fileInfo = {
996
+ name: activeFilename,
997
+ size,
998
+ totalSize,
999
+ type,
1000
+ };
1001
+ ctx.files.set(activeId, fileInfo);
885
1002
  }
886
- break away;
887
- }
888
- let buffer = headersChunks.length === 1 ? headersChunks[0] : undefined;
889
- if (headersChunks.length > 1) {
890
- let requiredSize = 0;
891
- let bufferOffset = 0;
892
- for (const headerChunk of headersChunks) {
893
- requiredSize += headerChunk.length;
1003
+ else {
1004
+ ctx.fields.set(activeName, null);
894
1005
  }
895
- buffer = new Uint8Array(requiredSize);
896
- for (const headerChunk of headersChunks) {
897
- if (headerChunk.length === 0) {
898
- continue;
1006
+ // reset states
1007
+ activeFieldSize = 0;
1008
+ activeFileSize = 0;
1009
+ // update states
1010
+ if (activeFilename != null) {
1011
+ totalFiles++;
1012
+ if (maxFiles != null && totalFiles > maxFiles) {
1013
+ if (onFileLimit != null) {
1014
+ response = yield onFileLimit(ctx, {
1015
+ headers: activeHeaders,
1016
+ id: activeId,
1017
+ name: activeName,
1018
+ filename: activeFilename,
1019
+ file: fileInfo,
1020
+ });
1021
+ if (response != null) {
1022
+ break away;
1023
+ }
1024
+ }
1025
+ else {
1026
+ throw new types_ts_1.HttpError(413, "Too many files");
1027
+ break away;
1028
+ }
899
1029
  }
900
- buffer.set(headerChunk, bufferOffset);
901
- bufferOffset += headerChunk.length;
902
1030
  }
903
- }
904
- headersChunks = [];
905
- leftOverHeader = undefined;
906
- const contentDisposition = {};
907
- activeHeaders = (0, exports.parseHeaders)(new Uint8Array(buffer), contentDisposition);
908
- if (contentDisposition["name"] == null) {
909
- throw new types_ts_1.HttpError(400, "Invalid Content-Disposition header");
910
- }
911
- // intialize for formdata part
912
- activeName = contentDisposition.name;
913
- activeFilename = contentDisposition.filename;
914
- activeId =
915
- idGenerator != null
916
- ? idGenerator({
1031
+ else {
1032
+ totalFields++;
1033
+ if (maxFields != null && totalFields > maxFields) {
1034
+ if (onFieldLimit != null) {
1035
+ response = yield onFieldLimit(ctx, {
1036
+ headers: activeHeaders,
1037
+ id: activeId,
1038
+ name: activeName,
1039
+ });
1040
+ if (response != null) {
1041
+ break away;
1042
+ }
1043
+ }
1044
+ else {
1045
+ throw new types_ts_1.HttpError(413, "Too many fields");
1046
+ break away;
1047
+ }
1048
+ }
1049
+ }
1050
+ // invoke callback
1051
+ if (onHeader != null) {
1052
+ response = yield onHeader(ctx, {
917
1053
  headers: activeHeaders,
1054
+ id: activeId,
918
1055
  name: activeName,
919
1056
  filename: activeFilename,
920
- })
921
- : (0, utils_ts_1.toBase64UUID)(crypto.randomUUID());
922
- if (activeFilename != null) {
923
- const contentTypeHeader = activeHeaders.get("content-type");
924
- const contentLengthHeader = activeHeaders.get("content-length");
925
- const size = 0;
926
- const totalSize = contentLengthHeader
927
- ? parseInt(contentLengthHeader)
928
- : null;
929
- const type = (contentTypeHeader
930
- ? contentTypeHeader
931
- : "application/octet-stream");
932
- fileInfo = {
933
- name: activeFilename,
934
- size,
935
- totalSize,
936
- type,
937
- };
938
- ctx.files.set(activeId, fileInfo);
939
- }
940
- else {
941
- ctx.fields.set(activeName, null);
942
- }
943
- // invoke callback
944
- if (onHeader != null) {
945
- response = yield onHeader(ctx, {
946
- headers: activeHeaders,
947
- id: activeId,
948
- name: activeName,
949
- filename: activeFilename,
950
- file: fileInfo,
951
- });
952
- if (response != null) {
953
- break away;
954
- }
955
- }
956
- parserState = ParseMultipartState.FindingBoundary;
957
- break;
958
- }
959
- case ParseMultipartState.ParsingChunk: {
960
- if (activeChunk == null) {
961
- if (!streamIsDone) {
962
- error = new types_ts_1.HttpError(400, "Invalid body");
1057
+ file: fileInfo,
1058
+ });
1059
+ if (response != null) {
1060
+ break away;
1061
+ }
963
1062
  }
964
- break away;
1063
+ parserState = ParseMultipartState.FindingBoundary;
1064
+ break;
965
1065
  }
966
- if (activeBodyStart != -1 && activeBodyStart < activeBodyEnd) {
967
- const chunk = activeChunk.subarray(activeBodyStart, activeBodyEnd);
968
- if (fileInfo != null) {
969
- fileInfo.size += chunk.length;
970
- }
971
- response = yield onData(ctx, {
972
- chunk,
973
- headers: activeHeaders,
974
- id: activeId,
975
- name: activeName,
976
- filename: activeFilename,
977
- file: fileInfo,
978
- });
979
- if (response != null) {
1066
+ case ParseMultipartState.ParsingChunk: {
1067
+ if (activeChunk == null) {
1068
+ if (!streamIsDone) {
1069
+ throw new types_ts_1.HttpError(400, "Invalid body");
1070
+ }
980
1071
  break away;
981
1072
  }
982
- if (onDataCompletion != null) {
983
- response = yield onDataCompletion(ctx, {
1073
+ if (activeBodyStart != -1 && activeBodyStart < activeBodyEnd) {
1074
+ const chunk = activeChunk.subarray(activeBodyStart, activeBodyEnd);
1075
+ response = yield _onData(ctx, chunk, {
984
1076
  headers: activeHeaders,
985
1077
  id: activeId,
986
1078
  name: activeName,
@@ -990,19 +1082,53 @@ const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataC
990
1082
  if (response != null) {
991
1083
  break away;
992
1084
  }
1085
+ if (onDataComplete != null) {
1086
+ response = yield onDataComplete(ctx, {
1087
+ headers: activeHeaders,
1088
+ id: activeId,
1089
+ name: activeName,
1090
+ filename: activeFilename,
1091
+ file: fileInfo,
1092
+ });
1093
+ activeFilename = undefined;
1094
+ if (response != null) {
1095
+ break away;
1096
+ }
1097
+ }
1098
+ else {
1099
+ activeFilename = undefined;
1100
+ }
993
1101
  }
1102
+ parserState = ParseMultipartState.FindingCRLF;
1103
+ break;
994
1104
  }
995
- parserState = ParseMultipartState.FindingCRLF;
996
- break;
997
1105
  }
998
1106
  }
999
1107
  }
1000
1108
  }
1001
- // handle completion and return a response
1109
+ catch (_error) {
1110
+ if (dontCatch) {
1111
+ throw _error;
1112
+ }
1113
+ else {
1114
+ const error = _error instanceof Error ? _error : new Error(String(_error));
1115
+ // handle error and return a response
1116
+ if (onEnd != null) {
1117
+ response = yield onEnd(ctx, {
1118
+ success: false,
1119
+ error,
1120
+ });
1121
+ }
1122
+ return response instanceof Response
1123
+ ? response
1124
+ : (0, helpers_ts_1.status)(error.status || 500, error.message);
1125
+ }
1126
+ }
1127
+ // handle complete and return a response
1002
1128
  if (onEnd != null) {
1129
+ const status = response instanceof Response ? response.status : 200;
1003
1130
  response = yield onEnd(ctx, {
1004
- success: error == null,
1005
- error,
1131
+ success: status >= 200 && status < 400,
1006
1132
  });
1007
1133
  }
1008
1134
  if (response instanceof Response) {
@@ -1014,8 +1140,157 @@ const parseMultipart = ({ idGenerator, onStart, onEnd, onHeader, onData, onDataC
1014
1140
  else if (response === types_ts_1.Break_Pipeline) {
1015
1141
  return types_ts_1.Break_Pipeline;
1016
1142
  }
1017
- return error == null ? (0, helpers_ts_1.status)(200) : (0, helpers_ts_1.status)(error.status, error.message);
1143
+ return (0, helpers_ts_1.status)(200);
1018
1144
  });
1019
1145
  };
1020
1146
  exports.parseMultipart = parseMultipart;
1147
+ const parseUpload = ({ path, fileHandle, write, end, parseField = exports.defaultFieldParser, dontCatch, maxFields, maxFiles, maxFieldSize, maxFileSize, maxTotalSize, progressIncrement = 10, idGenerator, onStart, onEnd, onHeader, onFieldHeader, onFileHeader, onFileData, onFileDataSpy, onFieldData, onFieldDataSpy, onFileProgress, onFieldComplete, onFileComplete, onComplete, onFileLimit, onFieldLimit, onFileSizeLimit, onFieldSizeLimit, onTotalSizeLimit, }) => {
1148
+ const getUploadPath = (id, file) => __awaiter(void 0, void 0, void 0, function* () {
1149
+ return typeof path === "function"
1150
+ ? yield path(id, file)
1151
+ : path + "/" + id + file.name.substring(file.name.lastIndexOf("."));
1152
+ });
1153
+ return (0, exports.parseMultipart)({
1154
+ maxFields,
1155
+ maxFiles,
1156
+ maxFieldSize,
1157
+ maxFileSize,
1158
+ maxTotalSize,
1159
+ idGenerator,
1160
+ onHeader: (ctx, info) => __awaiter(void 0, void 0, void 0, function* () {
1161
+ let response = undefined;
1162
+ if (info.file) {
1163
+ const { id, file } = info;
1164
+ const uploadPath = yield getUploadPath(id, file);
1165
+ file.fullpath = uploadPath;
1166
+ file.handle = yield fileHandle(uploadPath);
1167
+ file.totalChunks = 0;
1168
+ file._prevProgress = 0;
1169
+ file.progress = 0;
1170
+ if (onFileHeader != null) {
1171
+ response = yield onFileHeader(ctx, info);
1172
+ }
1173
+ }
1174
+ else {
1175
+ const { name } = info;
1176
+ ctx.fields.set(name, "");
1177
+ if (onFieldHeader != null) {
1178
+ response = yield onFieldHeader(ctx, info);
1179
+ }
1180
+ }
1181
+ if (onHeader != null) {
1182
+ response = yield onHeader(ctx, info);
1183
+ }
1184
+ return response;
1185
+ }),
1186
+ onData: (ctx, chunk, info) => __awaiter(void 0, void 0, void 0, function* () {
1187
+ if (info.file != null) {
1188
+ const { file } = info;
1189
+ file.totalChunks++;
1190
+ if (onFileProgress != null &&
1191
+ progressIncrement != null &&
1192
+ progressIncrement > 0) {
1193
+ if (file.totalSize) {
1194
+ const progress = (file.size / file.totalSize) * 100;
1195
+ const truncProgress = Math.trunc(progress / progressIncrement);
1196
+ if (truncProgress > file._prevProgress) {
1197
+ file.progress = progress;
1198
+ yield onFileProgress(ctx, info);
1199
+ file._prevProgress = truncProgress;
1200
+ }
1201
+ }
1202
+ }
1203
+ if (onFileDataSpy != null) {
1204
+ const response = yield onFileDataSpy(ctx, chunk, info);
1205
+ if (response != null) {
1206
+ return response;
1207
+ }
1208
+ }
1209
+ if (onFileData != null) {
1210
+ return yield onFileData(ctx, chunk, info);
1211
+ }
1212
+ else {
1213
+ yield write(info.file, chunk, info);
1214
+ }
1215
+ }
1216
+ else {
1217
+ const { name } = info;
1218
+ if (onFieldDataSpy != null) {
1219
+ const response = yield onFieldDataSpy(ctx, chunk, info);
1220
+ if (response != null) {
1221
+ return response;
1222
+ }
1223
+ }
1224
+ if (onFieldData != null) {
1225
+ return yield onFieldData(ctx, chunk, info);
1226
+ }
1227
+ else {
1228
+ ctx.fields.set(name, ctx.fields.get(name) + new TextDecoder().decode(chunk));
1229
+ }
1230
+ }
1231
+ }),
1232
+ onDataComplete: (ctx, info) => __awaiter(void 0, void 0, void 0, function* () {
1233
+ let response = undefined;
1234
+ if (info.file) {
1235
+ if (end != null) {
1236
+ yield end(info.file, true, info);
1237
+ }
1238
+ if (onFileComplete != null) {
1239
+ response = yield onFileComplete(ctx, info);
1240
+ }
1241
+ }
1242
+ else {
1243
+ const { name, headers } = info;
1244
+ // parse field
1245
+ if (parseField != null) {
1246
+ const contentTypeHeader = headers.get("content-type");
1247
+ const field = ctx.fields.get(name);
1248
+ const contentType = contentTypeHeader
1249
+ ? contentTypeHeader.split(";", 2)[0]
1250
+ : undefined;
1251
+ const parsed = yield parseField(field, contentType);
1252
+ ctx.fields.set(name, parsed);
1253
+ }
1254
+ if (onFieldComplete != null) {
1255
+ const field = ctx.fields.get(name);
1256
+ response = yield onFieldComplete(ctx, Object.assign(Object.assign({}, info), { field }));
1257
+ }
1258
+ }
1259
+ if (onComplete != null) {
1260
+ response = yield onComplete(ctx, info);
1261
+ }
1262
+ return response;
1263
+ }),
1264
+ onStart: (ctx) => {
1265
+ if (onStart != null) {
1266
+ return onStart(ctx);
1267
+ }
1268
+ },
1269
+ onEnd: (ctx, info) => __awaiter(void 0, void 0, void 0, function* () {
1270
+ var _a;
1271
+ if (onEnd != null) {
1272
+ return yield onEnd(ctx, info);
1273
+ }
1274
+ if (!info.success) {
1275
+ // console.error("[Upload](onEnd)", info.error);
1276
+ return (0, helpers_ts_1.status)(500, ((_a = info.error) === null || _a === void 0 ? void 0 : _a.message) || "Error while parsing upload");
1277
+ }
1278
+ return (0, helpers_ts_1.status)(200);
1279
+ }),
1280
+ onFileSizeLimit: (ctx, info) => __awaiter(void 0, void 0, void 0, function* () {
1281
+ if (end != null) {
1282
+ yield end(info.file, false, info);
1283
+ }
1284
+ if (onFileSizeLimit != null) {
1285
+ return yield onFileSizeLimit(ctx, info);
1286
+ }
1287
+ }),
1288
+ dontCatch,
1289
+ onFileLimit,
1290
+ onFieldLimit,
1291
+ onFieldSizeLimit,
1292
+ onTotalSizeLimit,
1293
+ });
1294
+ };
1295
+ exports.parseUpload = parseUpload;
1021
1296
  //# sourceMappingURL=parsers.js.map