@arcis/node 1.0.0 → 1.1.0
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/README.md +7 -18
- package/dist/{index-BpT7flAQ.d.ts → index-BvcFpoR3.d.ts} +184 -1
- package/dist/{index-JaFOUKyK.d.mts → index-CCcPuTBo.d.mts} +184 -1
- package/dist/index-CslcoZUN.d.mts +340 -0
- package/dist/index-iCOw8Fcg.d.ts +340 -0
- package/dist/index.d.mts +142 -106
- package/dist/index.d.ts +142 -106
- package/dist/index.js +896 -114
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +885 -115
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +378 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +375 -1
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/validation/index.d.mts +1 -1
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +400 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/index.mjs +394 -1
- package/dist/validation/index.mjs.map +1 -1
- package/package.json +6 -1
- package/dist/index-BgHPM7LC.d.ts +0 -129
- package/dist/index-nAgXexwD.d.mts +0 -129
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { promises } from 'dns';
|
|
2
|
+
|
|
1
3
|
// src/core/constants.ts
|
|
2
4
|
var INPUT = {
|
|
3
5
|
/** Default maximum input size (1MB) */
|
|
@@ -694,6 +696,397 @@ function isDangerousExtension(filename) {
|
|
|
694
696
|
return ext !== "" && DANGEROUS_EXTENSIONS.has(ext);
|
|
695
697
|
}
|
|
696
698
|
|
|
697
|
-
|
|
699
|
+
// src/validation/url.ts
|
|
700
|
+
function validateUrl(url, options = {}) {
|
|
701
|
+
const {
|
|
702
|
+
allowedProtocols = ["http:", "https:"],
|
|
703
|
+
blockedHosts = [],
|
|
704
|
+
allowedHosts = [],
|
|
705
|
+
allowLocalhost = false,
|
|
706
|
+
allowPrivate = false
|
|
707
|
+
} = options;
|
|
708
|
+
if (typeof url !== "string" || url.trim() === "") {
|
|
709
|
+
return { safe: false, reason: "invalid URL: empty or not a string" };
|
|
710
|
+
}
|
|
711
|
+
let parsed;
|
|
712
|
+
try {
|
|
713
|
+
parsed = new URL(url);
|
|
714
|
+
} catch {
|
|
715
|
+
return { safe: false, reason: "invalid URL: failed to parse" };
|
|
716
|
+
}
|
|
717
|
+
if (!allowedProtocols.includes(parsed.protocol)) {
|
|
718
|
+
return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };
|
|
719
|
+
}
|
|
720
|
+
if (parsed.username || parsed.password) {
|
|
721
|
+
return { safe: false, reason: "URL contains credentials" };
|
|
722
|
+
}
|
|
723
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
724
|
+
if (allowedHosts.some((h) => hostname === h.toLowerCase())) {
|
|
725
|
+
return { safe: true };
|
|
726
|
+
}
|
|
727
|
+
if (blockedHosts.some((h) => hostname === h.toLowerCase())) {
|
|
728
|
+
return { safe: false, reason: `blocked host: ${hostname}` };
|
|
729
|
+
}
|
|
730
|
+
if (!allowLocalhost) {
|
|
731
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1" || hostname === "0.0.0.0" || hostname.endsWith(".localhost")) {
|
|
732
|
+
return { safe: false, reason: "loopback address" };
|
|
733
|
+
}
|
|
734
|
+
if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
|
|
735
|
+
return { safe: false, reason: "loopback address" };
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
if (!allowPrivate) {
|
|
739
|
+
const privateCheck = checkPrivateIp(hostname);
|
|
740
|
+
if (privateCheck) {
|
|
741
|
+
return { safe: false, reason: privateCheck };
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
return { safe: true };
|
|
745
|
+
}
|
|
746
|
+
function isUrlSafe(url, options = {}) {
|
|
747
|
+
return validateUrl(url, options).safe;
|
|
748
|
+
}
|
|
749
|
+
function checkPrivateIp(hostname) {
|
|
750
|
+
if (/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
|
|
751
|
+
return "private address (10.0.0.0/8)";
|
|
752
|
+
}
|
|
753
|
+
const match172 = hostname.match(/^172\.(\d{1,3})\.\d{1,3}\.\d{1,3}$/);
|
|
754
|
+
if (match172) {
|
|
755
|
+
const second = parseInt(match172[1], 10);
|
|
756
|
+
if (second >= 16 && second <= 31) {
|
|
757
|
+
return "private address (172.16.0.0/12)";
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (/^192\.168\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
|
|
761
|
+
return "private address (192.168.0.0/16)";
|
|
762
|
+
}
|
|
763
|
+
if (/^169\.254\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
|
|
764
|
+
return "link-local address (169.254.0.0/16)";
|
|
765
|
+
}
|
|
766
|
+
if (/^0\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
|
|
767
|
+
return "current network address (0.0.0.0/8)";
|
|
768
|
+
}
|
|
769
|
+
if (hostname === "metadata.google.internal" || hostname === "metadata.internal") {
|
|
770
|
+
return "cloud metadata endpoint";
|
|
771
|
+
}
|
|
772
|
+
const ipv6 = hostname.replace(/^\[|\]$/g, "");
|
|
773
|
+
if (ipv6 === "::1" || ipv6 === "::" || ipv6.startsWith("fc") || ipv6.startsWith("fd") || ipv6.startsWith("fe80")) {
|
|
774
|
+
return "private IPv6 address";
|
|
775
|
+
}
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// src/validation/redirect.ts
|
|
780
|
+
var DANGEROUS_PROTOCOLS = /^(javascript|data|vbscript|blob):/i;
|
|
781
|
+
var CONTROL_CHARS = /[\t\n\r]/g;
|
|
782
|
+
function validateRedirect(url, options = {}) {
|
|
783
|
+
const {
|
|
784
|
+
allowedHosts = [],
|
|
785
|
+
allowProtocolRelative = false,
|
|
786
|
+
allowedProtocols = ["http:", "https:"]
|
|
787
|
+
} = options;
|
|
788
|
+
if (typeof url !== "string" || url.trim() === "") {
|
|
789
|
+
return { safe: false, reason: "invalid redirect: empty or not a string" };
|
|
790
|
+
}
|
|
791
|
+
const cleaned = url.replace(CONTROL_CHARS, "");
|
|
792
|
+
if (DANGEROUS_PROTOCOLS.test(cleaned)) {
|
|
793
|
+
const proto = cleaned.match(DANGEROUS_PROTOCOLS);
|
|
794
|
+
return { safe: false, reason: `dangerous protocol: ${proto[0]}` };
|
|
795
|
+
}
|
|
796
|
+
if (cleaned.startsWith("\\")) {
|
|
797
|
+
return { safe: false, reason: "backslash-prefixed URL (browser treats as protocol-relative)" };
|
|
798
|
+
}
|
|
799
|
+
if (cleaned.startsWith("//")) {
|
|
800
|
+
if (!allowProtocolRelative) {
|
|
801
|
+
const host2 = extractHost(cleaned);
|
|
802
|
+
if (host2 && allowedHosts.some((h) => host2 === h.toLowerCase())) {
|
|
803
|
+
return { safe: true };
|
|
804
|
+
}
|
|
805
|
+
return { safe: false, reason: "protocol-relative URL not in allowed hosts" };
|
|
806
|
+
}
|
|
807
|
+
const host = extractHost(cleaned);
|
|
808
|
+
if (host && allowedHosts.length > 0 && !allowedHosts.some((h) => host === h.toLowerCase())) {
|
|
809
|
+
return { safe: false, reason: "protocol-relative URL not in allowed hosts" };
|
|
810
|
+
}
|
|
811
|
+
return { safe: true };
|
|
812
|
+
}
|
|
813
|
+
let parsed;
|
|
814
|
+
try {
|
|
815
|
+
parsed = new URL(cleaned);
|
|
816
|
+
} catch {
|
|
817
|
+
return { safe: true };
|
|
818
|
+
}
|
|
819
|
+
if (!allowedProtocols.includes(parsed.protocol)) {
|
|
820
|
+
return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };
|
|
821
|
+
}
|
|
822
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
823
|
+
if (allowedHosts.length === 0) {
|
|
824
|
+
return { safe: false, reason: "absolute URL not in allowed hosts" };
|
|
825
|
+
}
|
|
826
|
+
if (!allowedHosts.some((h) => hostname === h.toLowerCase())) {
|
|
827
|
+
return { safe: false, reason: `host not allowed: ${hostname}` };
|
|
828
|
+
}
|
|
829
|
+
return { safe: true };
|
|
830
|
+
}
|
|
831
|
+
function isRedirectSafe(url, options = {}) {
|
|
832
|
+
return validateRedirect(url, options).safe;
|
|
833
|
+
}
|
|
834
|
+
function extractHost(url) {
|
|
835
|
+
const match = url.match(/^\/\/([^/:?#]+)/);
|
|
836
|
+
return match ? match[1].toLowerCase() : null;
|
|
837
|
+
}
|
|
838
|
+
var MAX_EMAIL_LENGTH = 254;
|
|
839
|
+
var MAX_LOCAL_LENGTH = 64;
|
|
840
|
+
var MAX_DOMAIN_LENGTH = 255;
|
|
841
|
+
var EMAIL_SYNTAX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$/;
|
|
842
|
+
var FREE_PROVIDERS = /* @__PURE__ */ new Set([
|
|
843
|
+
"gmail.com",
|
|
844
|
+
"yahoo.com",
|
|
845
|
+
"hotmail.com",
|
|
846
|
+
"outlook.com",
|
|
847
|
+
"aol.com",
|
|
848
|
+
"protonmail.com",
|
|
849
|
+
"proton.me",
|
|
850
|
+
"icloud.com",
|
|
851
|
+
"mail.com",
|
|
852
|
+
"zoho.com",
|
|
853
|
+
"yandex.com",
|
|
854
|
+
"gmx.com",
|
|
855
|
+
"gmx.net",
|
|
856
|
+
"live.com",
|
|
857
|
+
"msn.com",
|
|
858
|
+
"me.com",
|
|
859
|
+
"mac.com",
|
|
860
|
+
"fastmail.com",
|
|
861
|
+
"tutanota.com",
|
|
862
|
+
"hey.com"
|
|
863
|
+
]);
|
|
864
|
+
var DISPOSABLE_DOMAINS = /* @__PURE__ */ new Set([
|
|
865
|
+
// Popular disposable services
|
|
866
|
+
"guerrillamail.com",
|
|
867
|
+
"guerrillamail.net",
|
|
868
|
+
"guerrillamail.org",
|
|
869
|
+
"tempmail.com",
|
|
870
|
+
"temp-mail.org",
|
|
871
|
+
"temp-mail.io",
|
|
872
|
+
"throwaway.email",
|
|
873
|
+
"throwaway.com",
|
|
874
|
+
"mailinator.com",
|
|
875
|
+
"mailinator.net",
|
|
876
|
+
"yopmail.com",
|
|
877
|
+
"yopmail.fr",
|
|
878
|
+
"yopmail.net",
|
|
879
|
+
"sharklasers.com",
|
|
880
|
+
"grr.la",
|
|
881
|
+
"guerrillamail.info",
|
|
882
|
+
"guerrillamail.biz",
|
|
883
|
+
"guerrillamail.de",
|
|
884
|
+
"trashmail.com",
|
|
885
|
+
"trashmail.me",
|
|
886
|
+
"trashmail.net",
|
|
887
|
+
"dispostable.com",
|
|
888
|
+
"maildrop.cc",
|
|
889
|
+
"mailnesia.com",
|
|
890
|
+
"tempail.com",
|
|
891
|
+
"mohmal.com",
|
|
892
|
+
"getnada.com",
|
|
893
|
+
"emailondeck.com",
|
|
894
|
+
"discard.email",
|
|
895
|
+
"fakeinbox.com",
|
|
896
|
+
"mailcatch.com",
|
|
897
|
+
"mintemail.com",
|
|
898
|
+
"tempr.email",
|
|
899
|
+
"tempinbox.com",
|
|
900
|
+
"burnermail.io",
|
|
901
|
+
"mailsac.com",
|
|
902
|
+
"harakirimail.com",
|
|
903
|
+
"tempmailo.com",
|
|
904
|
+
"emailfake.com",
|
|
905
|
+
"crazymailing.com",
|
|
906
|
+
"armyspy.com",
|
|
907
|
+
"dayrep.com",
|
|
908
|
+
"einrot.com",
|
|
909
|
+
"fleckens.hu",
|
|
910
|
+
"gustr.com",
|
|
911
|
+
"jourrapide.com",
|
|
912
|
+
"rhyta.com",
|
|
913
|
+
"superrito.com",
|
|
914
|
+
"teleworm.us",
|
|
915
|
+
"10minutemail.com",
|
|
916
|
+
"10minutemail.net",
|
|
917
|
+
"minutemail.com",
|
|
918
|
+
"tempsky.com",
|
|
919
|
+
"spamgourmet.com",
|
|
920
|
+
"mytrashmail.com",
|
|
921
|
+
"mailexpire.com",
|
|
922
|
+
"safetymail.info",
|
|
923
|
+
"filzmail.com",
|
|
924
|
+
"trashymail.com",
|
|
925
|
+
"sharkmail.com",
|
|
926
|
+
"jetable.org",
|
|
927
|
+
"nospam.ze.tc",
|
|
928
|
+
"trash-me.com",
|
|
929
|
+
"dodgit.com",
|
|
930
|
+
"mailmoat.com",
|
|
931
|
+
"spamfree24.org",
|
|
932
|
+
"incognitomail.org",
|
|
933
|
+
"tempomail.fr",
|
|
934
|
+
"ephemail.net",
|
|
935
|
+
"hidemail.de",
|
|
936
|
+
"spaml.de",
|
|
937
|
+
"uggsrock.com",
|
|
938
|
+
"binkmail.com",
|
|
939
|
+
"suremail.info",
|
|
940
|
+
"bugmenot.com"
|
|
941
|
+
]);
|
|
942
|
+
var DOMAIN_TYPOS = {
|
|
943
|
+
"gmial.com": "gmail.com",
|
|
944
|
+
"gmaill.com": "gmail.com",
|
|
945
|
+
"gmai.com": "gmail.com",
|
|
946
|
+
"gamil.com": "gmail.com",
|
|
947
|
+
"gnail.com": "gmail.com",
|
|
948
|
+
"gmal.com": "gmail.com",
|
|
949
|
+
"gmil.com": "gmail.com",
|
|
950
|
+
"gmail.co": "gmail.com",
|
|
951
|
+
"gmail.cm": "gmail.com",
|
|
952
|
+
"gmail.om": "gmail.com",
|
|
953
|
+
"gmail.con": "gmail.com",
|
|
954
|
+
"gmail.cim": "gmail.com",
|
|
955
|
+
"gmail.comm": "gmail.com",
|
|
956
|
+
"yahooo.com": "yahoo.com",
|
|
957
|
+
"yaho.com": "yahoo.com",
|
|
958
|
+
"yahoo.co": "yahoo.com",
|
|
959
|
+
"yahoo.cm": "yahoo.com",
|
|
960
|
+
"yahoo.con": "yahoo.com",
|
|
961
|
+
"yahho.com": "yahoo.com",
|
|
962
|
+
"hotmial.com": "hotmail.com",
|
|
963
|
+
"hotmal.com": "hotmail.com",
|
|
964
|
+
"hotmai.com": "hotmail.com",
|
|
965
|
+
"hotmil.com": "hotmail.com",
|
|
966
|
+
"hotmail.co": "hotmail.com",
|
|
967
|
+
"hotmail.cm": "hotmail.com",
|
|
968
|
+
"hotmail.con": "hotmail.com",
|
|
969
|
+
"outlok.com": "outlook.com",
|
|
970
|
+
"outloo.com": "outlook.com",
|
|
971
|
+
"outlook.co": "outlook.com",
|
|
972
|
+
"outlook.cm": "outlook.com",
|
|
973
|
+
"protonmal.com": "protonmail.com",
|
|
974
|
+
"protonmail.co": "protonmail.com",
|
|
975
|
+
"icloud.co": "icloud.com",
|
|
976
|
+
"icloud.cm": "icloud.com",
|
|
977
|
+
"icoud.com": "icloud.com"
|
|
978
|
+
};
|
|
979
|
+
function invalidResult(reason, email) {
|
|
980
|
+
return {
|
|
981
|
+
valid: false,
|
|
982
|
+
reason,
|
|
983
|
+
suggestion: null,
|
|
984
|
+
isFree: false,
|
|
985
|
+
isDisposable: false,
|
|
986
|
+
normalized: email
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
function validateEmail(email, options = {}) {
|
|
990
|
+
const {
|
|
991
|
+
checkDisposable = true,
|
|
992
|
+
suggestTypoFix = true,
|
|
993
|
+
blockedDomains = [],
|
|
994
|
+
allowedDomains = []
|
|
995
|
+
} = options;
|
|
996
|
+
const normalized = email.trim().toLowerCase();
|
|
997
|
+
if (!normalized || normalized.length > MAX_EMAIL_LENGTH) {
|
|
998
|
+
return invalidResult("invalid_syntax", normalized);
|
|
999
|
+
}
|
|
1000
|
+
const atIndex = normalized.lastIndexOf("@");
|
|
1001
|
+
if (atIndex === -1) {
|
|
1002
|
+
return invalidResult("invalid_syntax", normalized);
|
|
1003
|
+
}
|
|
1004
|
+
const localPart = normalized.slice(0, atIndex);
|
|
1005
|
+
const domain = normalized.slice(atIndex + 1);
|
|
1006
|
+
if (localPart.length === 0 || localPart.length > MAX_LOCAL_LENGTH) {
|
|
1007
|
+
return invalidResult("invalid_syntax", normalized);
|
|
1008
|
+
}
|
|
1009
|
+
if (domain.length === 0 || domain.length > MAX_DOMAIN_LENGTH) {
|
|
1010
|
+
return invalidResult("invalid_syntax", normalized);
|
|
1011
|
+
}
|
|
1012
|
+
if (localPart.includes("..")) {
|
|
1013
|
+
return invalidResult("invalid_syntax", normalized);
|
|
1014
|
+
}
|
|
1015
|
+
if (localPart.startsWith(".") || localPart.endsWith(".")) {
|
|
1016
|
+
return invalidResult("invalid_syntax", normalized);
|
|
1017
|
+
}
|
|
1018
|
+
if (!EMAIL_SYNTAX.test(normalized)) {
|
|
1019
|
+
return invalidResult("invalid_syntax", normalized);
|
|
1020
|
+
}
|
|
1021
|
+
const allowedSet = new Set(allowedDomains.map((d) => d.toLowerCase()));
|
|
1022
|
+
if (allowedSet.has(domain)) {
|
|
1023
|
+
return {
|
|
1024
|
+
valid: true,
|
|
1025
|
+
reason: "valid",
|
|
1026
|
+
suggestion: null,
|
|
1027
|
+
isFree: FREE_PROVIDERS.has(domain),
|
|
1028
|
+
isDisposable: false,
|
|
1029
|
+
normalized
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
const blockedSet = new Set(blockedDomains.map((d) => d.toLowerCase()));
|
|
1033
|
+
if (blockedSet.has(domain)) {
|
|
1034
|
+
return invalidResult("blocked", normalized);
|
|
1035
|
+
}
|
|
1036
|
+
const isDisposable = DISPOSABLE_DOMAINS.has(domain);
|
|
1037
|
+
if (checkDisposable && isDisposable) {
|
|
1038
|
+
return {
|
|
1039
|
+
valid: false,
|
|
1040
|
+
reason: "disposable",
|
|
1041
|
+
suggestion: null,
|
|
1042
|
+
isFree: false,
|
|
1043
|
+
isDisposable: true,
|
|
1044
|
+
normalized
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
const isFree = FREE_PROVIDERS.has(domain);
|
|
1048
|
+
if (suggestTypoFix && DOMAIN_TYPOS[domain]) {
|
|
1049
|
+
const corrected = `${localPart}@${DOMAIN_TYPOS[domain]}`;
|
|
1050
|
+
return {
|
|
1051
|
+
valid: true,
|
|
1052
|
+
reason: "typo",
|
|
1053
|
+
suggestion: corrected,
|
|
1054
|
+
isFree: FREE_PROVIDERS.has(DOMAIN_TYPOS[domain]),
|
|
1055
|
+
isDisposable: false,
|
|
1056
|
+
normalized
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
return {
|
|
1060
|
+
valid: true,
|
|
1061
|
+
reason: "valid",
|
|
1062
|
+
suggestion: null,
|
|
1063
|
+
isFree,
|
|
1064
|
+
isDisposable,
|
|
1065
|
+
normalized
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
async function verifyEmailMx(email) {
|
|
1069
|
+
if (!isValidEmailSyntax(email)) return false;
|
|
1070
|
+
const atIndex = email.lastIndexOf("@");
|
|
1071
|
+
const domain = email.slice(atIndex + 1).trim().toLowerCase();
|
|
1072
|
+
if (!domain) return false;
|
|
1073
|
+
try {
|
|
1074
|
+
const records = await promises.resolveMx(domain);
|
|
1075
|
+
return records.length > 0;
|
|
1076
|
+
} catch {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
function isValidEmailSyntax(email) {
|
|
1081
|
+
const normalized = email.trim().toLowerCase();
|
|
1082
|
+
if (!normalized || normalized.length > MAX_EMAIL_LENGTH) return false;
|
|
1083
|
+
const atIndex = normalized.lastIndexOf("@");
|
|
1084
|
+
if (atIndex === -1) return false;
|
|
1085
|
+
const localPart = normalized.slice(0, atIndex);
|
|
1086
|
+
if (localPart.includes("..") || localPart.startsWith(".") || localPart.endsWith(".")) return false;
|
|
1087
|
+
return EMAIL_SYNTAX.test(normalized);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
export { createValidator, isDangerousExtension, isRedirectSafe, isUrlSafe, isValidEmailSyntax, sanitizeFilename, validate, validateEmail, validateFile, validateRedirect, validateUrl, verifyEmailMx };
|
|
698
1091
|
//# sourceMappingURL=index.mjs.map
|
|
699
1092
|
//# sourceMappingURL=index.mjs.map
|