@bcts/uniform-resources 1.0.0-alpha.21 → 1.0.0-alpha.23
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 +1 -1
- package/dist/index.cjs +136 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +49 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +194 -102
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +131 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/index.ts +5 -0
- package/src/utils.ts +135 -17
package/README.md
CHANGED
|
@@ -14,4 +14,4 @@ The primary specification for URs is [BCR-2020-005: Uniform Resources](https://g
|
|
|
14
14
|
|
|
15
15
|
## Rust Reference Implementation
|
|
16
16
|
|
|
17
|
-
This TypeScript implementation is based on [bc-ur-rust](https://github.com/BlockchainCommons/bc-ur-rust) **v0.19.
|
|
17
|
+
This TypeScript implementation is based on [bc-ur-rust](https://github.com/BlockchainCommons/bc-ur-rust) **v0.19.2** ([commit](https://github.com/BlockchainCommons/bc-ur-rust/tree/2f8b4e728945f9dc248eba71911b89371f076924)).
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value:
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _bcts_dcbor = require("@bcts/dcbor");
|
|
3
3
|
let _bcts_crypto = require("@bcts/crypto");
|
|
4
|
-
|
|
5
4
|
//#region src/error.ts
|
|
6
5
|
/**
|
|
7
6
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
@@ -95,7 +94,6 @@ var URDecodeError = class extends URError {
|
|
|
95
94
|
function isError(result) {
|
|
96
95
|
return result instanceof Error;
|
|
97
96
|
}
|
|
98
|
-
|
|
99
97
|
//#endregion
|
|
100
98
|
//#region src/utils.ts
|
|
101
99
|
/**
|
|
@@ -653,36 +651,102 @@ const BYTEMOJIS = [
|
|
|
653
651
|
"🐳"
|
|
654
652
|
];
|
|
655
653
|
/**
|
|
656
|
-
* Encodes
|
|
654
|
+
* Encodes an arbitrary byte slice as a string of space-separated bytewords.
|
|
655
|
+
*
|
|
656
|
+
* Mirrors `bytewords::encode_to_words` in `bc-ur-rust` (≥ v0.19.1). Does not
|
|
657
|
+
* add a CRC32 checksum — use {@link encodeBytewords} for UR-style encoding.
|
|
657
658
|
*/
|
|
658
|
-
function
|
|
659
|
-
if (data.length !== 4) throw new Error("Identifier data must be exactly 4 bytes");
|
|
659
|
+
function encodeToWords(data) {
|
|
660
660
|
const words = [];
|
|
661
|
-
for (
|
|
662
|
-
const byte = data[i];
|
|
663
|
-
if (byte === void 0) throw new Error("Invalid byte");
|
|
661
|
+
for (const byte of data) {
|
|
664
662
|
const word = BYTEWORDS[byte];
|
|
665
|
-
if (word ===
|
|
663
|
+
if (word === void 0) throw new Error(`Invalid byte value: ${byte}`);
|
|
666
664
|
words.push(word);
|
|
667
665
|
}
|
|
668
666
|
return words.join(" ");
|
|
669
667
|
}
|
|
670
668
|
/**
|
|
671
|
-
* Encodes
|
|
669
|
+
* Encodes an arbitrary byte slice as a string of space-separated bytemojis.
|
|
670
|
+
*
|
|
671
|
+
* Mirrors `bytewords::encode_to_bytemojis` in `bc-ur-rust` (≥ v0.19.1).
|
|
672
672
|
*/
|
|
673
|
-
function
|
|
674
|
-
if (data.length !== 4) throw new Error("Identifier data must be exactly 4 bytes");
|
|
673
|
+
function encodeToBytemojis(data) {
|
|
675
674
|
const emojis = [];
|
|
676
|
-
for (
|
|
677
|
-
const byte = data[i];
|
|
678
|
-
if (byte === void 0) throw new Error("Invalid byte");
|
|
675
|
+
for (const byte of data) {
|
|
679
676
|
const emoji = BYTEMOJIS[byte];
|
|
680
|
-
if (emoji ===
|
|
677
|
+
if (emoji === void 0) throw new Error(`Invalid byte value: ${byte}`);
|
|
681
678
|
emojis.push(emoji);
|
|
682
679
|
}
|
|
683
680
|
return emojis.join(" ");
|
|
684
681
|
}
|
|
685
682
|
/**
|
|
683
|
+
* Encodes an arbitrary byte slice as minimal bytewords (first + last letter of
|
|
684
|
+
* each word, concatenated with no separator).
|
|
685
|
+
*
|
|
686
|
+
* Mirrors `bytewords::encode_to_minimal_bytewords` in `bc-ur-rust`
|
|
687
|
+
* (≥ v0.19.1). Does not add a CRC32 checksum.
|
|
688
|
+
*/
|
|
689
|
+
function encodeToMinimalBytewords(data) {
|
|
690
|
+
let out = "";
|
|
691
|
+
for (const byte of data) {
|
|
692
|
+
const word = BYTEWORDS[byte];
|
|
693
|
+
if (word === void 0) throw new Error(`Invalid byte value: ${byte}`);
|
|
694
|
+
out += word[0] + word[word.length - 1];
|
|
695
|
+
}
|
|
696
|
+
return out;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Encodes a 4-byte slice as a string of bytewords for identification.
|
|
700
|
+
*
|
|
701
|
+
* Thin wrapper over {@link encodeToWords} that enforces the 4-byte length
|
|
702
|
+
* contract historically used by `bc-ur-rust`'s `bytewords::identifier`.
|
|
703
|
+
*/
|
|
704
|
+
function encodeBytewordsIdentifier(data) {
|
|
705
|
+
if (data.length !== 4) throw new Error("Identifier data must be exactly 4 bytes");
|
|
706
|
+
return encodeToWords(data);
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Encodes a 4-byte slice as a string of bytemojis for identification.
|
|
710
|
+
*
|
|
711
|
+
* Thin wrapper over {@link encodeToBytemojis} that enforces the 4-byte length
|
|
712
|
+
* contract historically used by `bc-ur-rust`'s `bytewords::bytemoji_identifier`.
|
|
713
|
+
*/
|
|
714
|
+
function encodeBytemojisIdentifier(data) {
|
|
715
|
+
if (data.length !== 4) throw new Error("Identifier data must be exactly 4 bytes");
|
|
716
|
+
return encodeToBytemojis(data);
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Returns `true` if `emoji` is one of the 256 bytemojis.
|
|
720
|
+
*
|
|
721
|
+
* Mirrors `bytewords::is_valid_bytemoji` in `bc-ur-rust` (≥ v0.19.1).
|
|
722
|
+
*/
|
|
723
|
+
function isValidBytemoji(emoji) {
|
|
724
|
+
return BYTEMOJI_SET.has(emoji);
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Canonicalises a byteword token (2–4 ASCII letters, case-insensitive) to its
|
|
728
|
+
* full 4-letter lowercase form. Returns `undefined` if the token is not a
|
|
729
|
+
* valid byteword or any of its short forms.
|
|
730
|
+
*
|
|
731
|
+
* Mirrors `bytewords::canonicalize_byteword` in `bc-ur-rust` (≥ v0.19.1).
|
|
732
|
+
*
|
|
733
|
+
* - 2-letter tokens are matched against the first + last letter of each
|
|
734
|
+
* byteword (identical to the minimal bytewords encoding).
|
|
735
|
+
* - 3-letter tokens are matched against the first 3 and the last 3 letters of
|
|
736
|
+
* each byteword; if both match different entries, the first-3 match wins
|
|
737
|
+
* (matching rust's `or_else` priority).
|
|
738
|
+
* - 4-letter tokens must exactly match a full byteword (after lower-casing).
|
|
739
|
+
*/
|
|
740
|
+
function canonicalizeByteword(token) {
|
|
741
|
+
const lower = token.toLowerCase();
|
|
742
|
+
switch (lower.length) {
|
|
743
|
+
case 4: return BYTEWORDS_MAP.has(lower) ? lower : void 0;
|
|
744
|
+
case 2: return BYTEWORD_FIRST_LAST_MAP.get(lower);
|
|
745
|
+
case 3: return BYTEWORD_FIRST_THREE_MAP.get(lower) ?? BYTEWORD_LAST_THREE_MAP.get(lower);
|
|
746
|
+
default: return;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
686
750
|
* Bytewords encoding style.
|
|
687
751
|
*/
|
|
688
752
|
let BytewordsStyle = /* @__PURE__ */ function(BytewordsStyle) {
|
|
@@ -707,6 +771,38 @@ function createMinimalBytewordsMap() {
|
|
|
707
771
|
}
|
|
708
772
|
const MINIMAL_BYTEWORDS_MAP = createMinimalBytewordsMap();
|
|
709
773
|
/**
|
|
774
|
+
* Set of all 256 bytemojis for fast membership testing. Backs
|
|
775
|
+
* {@link isValidBytemoji}.
|
|
776
|
+
*/
|
|
777
|
+
const BYTEMOJI_SET = new Set(BYTEMOJIS);
|
|
778
|
+
/**
|
|
779
|
+
* Lookup from a 2-letter (first+last) byteword short-form to its full
|
|
780
|
+
* lowercase 4-letter form. Backs {@link canonicalizeByteword}.
|
|
781
|
+
*/
|
|
782
|
+
const BYTEWORD_FIRST_LAST_MAP = (() => {
|
|
783
|
+
const map = /* @__PURE__ */ new Map();
|
|
784
|
+
for (const word of BYTEWORDS) map.set(word[0] + word[word.length - 1], word);
|
|
785
|
+
return map;
|
|
786
|
+
})();
|
|
787
|
+
/**
|
|
788
|
+
* Lookup from the first 3 letters of a byteword to its full lowercase 4-letter
|
|
789
|
+
* form. Backs {@link canonicalizeByteword}.
|
|
790
|
+
*/
|
|
791
|
+
const BYTEWORD_FIRST_THREE_MAP = (() => {
|
|
792
|
+
const map = /* @__PURE__ */ new Map();
|
|
793
|
+
for (const word of BYTEWORDS) map.set(word.slice(0, 3), word);
|
|
794
|
+
return map;
|
|
795
|
+
})();
|
|
796
|
+
/**
|
|
797
|
+
* Lookup from the last 3 letters of a byteword to its full lowercase 4-letter
|
|
798
|
+
* form. Backs {@link canonicalizeByteword}.
|
|
799
|
+
*/
|
|
800
|
+
const BYTEWORD_LAST_THREE_MAP = (() => {
|
|
801
|
+
const map = /* @__PURE__ */ new Map();
|
|
802
|
+
for (const word of BYTEWORDS) map.set(word.slice(1), word);
|
|
803
|
+
return map;
|
|
804
|
+
})();
|
|
805
|
+
/**
|
|
710
806
|
* CRC32 lookup table (IEEE polynomial).
|
|
711
807
|
*/
|
|
712
808
|
const CRC32_TABLE = (() => {
|
|
@@ -741,7 +837,7 @@ function uint32ToBytes(value) {
|
|
|
741
837
|
* Encode data as bytewords with the specified style.
|
|
742
838
|
* Includes CRC32 checksum.
|
|
743
839
|
*/
|
|
744
|
-
function encodeBytewords(data, style =
|
|
840
|
+
function encodeBytewords(data, style = "minimal") {
|
|
745
841
|
const checksumBytes = uint32ToBytes(crc32(data));
|
|
746
842
|
const dataWithChecksum = new Uint8Array(data.length + 4);
|
|
747
843
|
dataWithChecksum.set(data);
|
|
@@ -751,46 +847,46 @@ function encodeBytewords(data, style = BytewordsStyle.Minimal) {
|
|
|
751
847
|
const word = BYTEWORDS[byte];
|
|
752
848
|
if (word === void 0) throw new Error(`Invalid byte value: ${byte}`);
|
|
753
849
|
switch (style) {
|
|
754
|
-
case
|
|
850
|
+
case "standard":
|
|
755
851
|
words.push(word);
|
|
756
852
|
break;
|
|
757
|
-
case
|
|
853
|
+
case "uri":
|
|
758
854
|
words.push(word);
|
|
759
855
|
break;
|
|
760
|
-
case
|
|
856
|
+
case "minimal":
|
|
761
857
|
words.push(word[0] + word[3]);
|
|
762
858
|
break;
|
|
763
859
|
}
|
|
764
860
|
}
|
|
765
861
|
switch (style) {
|
|
766
|
-
case
|
|
767
|
-
case
|
|
768
|
-
case
|
|
862
|
+
case "standard": return words.join(" ");
|
|
863
|
+
case "uri": return words.join("-");
|
|
864
|
+
case "minimal": return words.join("");
|
|
769
865
|
}
|
|
770
866
|
}
|
|
771
867
|
/**
|
|
772
868
|
* Decode bytewords string back to data.
|
|
773
869
|
* Validates and removes CRC32 checksum.
|
|
774
870
|
*/
|
|
775
|
-
function decodeBytewords(encoded, style =
|
|
871
|
+
function decodeBytewords(encoded, style = "minimal") {
|
|
776
872
|
const lowercased = encoded.toLowerCase();
|
|
777
873
|
let bytes;
|
|
778
874
|
switch (style) {
|
|
779
|
-
case
|
|
875
|
+
case "standard":
|
|
780
876
|
bytes = lowercased.split(" ").map((word) => {
|
|
781
877
|
const index = BYTEWORDS_MAP.get(word);
|
|
782
878
|
if (index === void 0) throw new Error(`Invalid byteword: ${word}`);
|
|
783
879
|
return index;
|
|
784
880
|
});
|
|
785
881
|
break;
|
|
786
|
-
case
|
|
882
|
+
case "uri":
|
|
787
883
|
bytes = lowercased.split("-").map((word) => {
|
|
788
884
|
const index = BYTEWORDS_MAP.get(word);
|
|
789
885
|
if (index === void 0) throw new Error(`Invalid byteword: ${word}`);
|
|
790
886
|
return index;
|
|
791
887
|
});
|
|
792
888
|
break;
|
|
793
|
-
case
|
|
889
|
+
case "minimal":
|
|
794
890
|
if (lowercased.length % 2 !== 0) throw new Error("Invalid minimal bytewords length");
|
|
795
891
|
bytes = [];
|
|
796
892
|
for (let i = 0; i < lowercased.length; i += 2) {
|
|
@@ -810,7 +906,6 @@ function decodeBytewords(encoded, style = BytewordsStyle.Minimal) {
|
|
|
810
906
|
if (expectedChecksum !== actualChecksum) throw new Error(`Bytewords checksum mismatch: expected ${expectedChecksum.toString(16)}, got ${actualChecksum.toString(16)}`);
|
|
811
907
|
return data;
|
|
812
908
|
}
|
|
813
|
-
|
|
814
909
|
//#endregion
|
|
815
910
|
//#region src/ur-type.ts
|
|
816
911
|
/**
|
|
@@ -894,7 +989,6 @@ var URType = class URType {
|
|
|
894
989
|
}
|
|
895
990
|
}
|
|
896
991
|
};
|
|
897
|
-
|
|
898
992
|
//#endregion
|
|
899
993
|
//#region src/ur.ts
|
|
900
994
|
/**
|
|
@@ -1037,7 +1131,7 @@ var UR = class UR {
|
|
|
1037
1131
|
*/
|
|
1038
1132
|
var URStringEncoder = class {
|
|
1039
1133
|
static encode(urType, cborData) {
|
|
1040
|
-
return `ur:${urType}/${encodeBytewords(cborData,
|
|
1134
|
+
return `ur:${urType}/${encodeBytewords(cborData, "minimal")}`;
|
|
1041
1135
|
}
|
|
1042
1136
|
};
|
|
1043
1137
|
/**
|
|
@@ -1054,14 +1148,13 @@ var URStringDecoder = class {
|
|
|
1054
1148
|
try {
|
|
1055
1149
|
return {
|
|
1056
1150
|
urType,
|
|
1057
|
-
cbor: (0, _bcts_dcbor.decodeCbor)(decodeBytewords(data,
|
|
1151
|
+
cbor: (0, _bcts_dcbor.decodeCbor)(decodeBytewords(data, "minimal"))
|
|
1058
1152
|
};
|
|
1059
1153
|
} catch (error) {
|
|
1060
1154
|
throw new URError(`Failed to decode UR: ${error instanceof Error ? error.message : String(error)}`);
|
|
1061
1155
|
}
|
|
1062
1156
|
}
|
|
1063
1157
|
};
|
|
1064
|
-
|
|
1065
1158
|
//#endregion
|
|
1066
1159
|
//#region src/ur-encodable.ts
|
|
1067
1160
|
/**
|
|
@@ -1070,7 +1163,6 @@ var URStringDecoder = class {
|
|
|
1070
1163
|
function isUREncodable(obj) {
|
|
1071
1164
|
return typeof obj === "object" && obj !== null && "ur" in obj && "urString" in obj && typeof obj["ur"] === "function" && typeof obj["urString"] === "function";
|
|
1072
1165
|
}
|
|
1073
|
-
|
|
1074
1166
|
//#endregion
|
|
1075
1167
|
//#region src/ur-decodable.ts
|
|
1076
1168
|
/**
|
|
@@ -1079,7 +1171,6 @@ function isUREncodable(obj) {
|
|
|
1079
1171
|
function isURDecodable(obj) {
|
|
1080
1172
|
return typeof obj === "object" && obj !== null && "fromUR" in obj && typeof obj["fromUR"] === "function";
|
|
1081
1173
|
}
|
|
1082
|
-
|
|
1083
1174
|
//#endregion
|
|
1084
1175
|
//#region src/ur-codable.ts
|
|
1085
1176
|
/**
|
|
@@ -1088,7 +1179,6 @@ function isURDecodable(obj) {
|
|
|
1088
1179
|
function isURCodable(obj) {
|
|
1089
1180
|
return typeof obj === "object" && obj !== null && "ur" in obj && "urString" in obj && "fromUR" in obj && typeof obj["ur"] === "function" && typeof obj["urString"] === "function" && typeof obj["fromUR"] === "function";
|
|
1090
1181
|
}
|
|
1091
|
-
|
|
1092
1182
|
//#endregion
|
|
1093
1183
|
//#region src/xoshiro.ts
|
|
1094
1184
|
/**
|
|
@@ -1300,7 +1390,6 @@ function createSeed(checksum, seqNum) {
|
|
|
1300
1390
|
seed8[7] = checksum & 255;
|
|
1301
1391
|
return (0, _bcts_crypto.sha256)(seed8);
|
|
1302
1392
|
}
|
|
1303
|
-
|
|
1304
1393
|
//#endregion
|
|
1305
1394
|
//#region src/fountain.ts
|
|
1306
1395
|
/**
|
|
@@ -1553,7 +1642,6 @@ var FountainDecoder = class {
|
|
|
1553
1642
|
this.mixedParts.clear();
|
|
1554
1643
|
}
|
|
1555
1644
|
};
|
|
1556
|
-
|
|
1557
1645
|
//#endregion
|
|
1558
1646
|
//#region src/multipart-encoder.ts
|
|
1559
1647
|
/**
|
|
@@ -1602,7 +1690,8 @@ var MultipartEncoder = class {
|
|
|
1602
1690
|
constructor(ur, maxFragmentLen) {
|
|
1603
1691
|
if (maxFragmentLen < 1) throw new URError("Max fragment length must be at least 1");
|
|
1604
1692
|
this._ur = ur;
|
|
1605
|
-
|
|
1693
|
+
const cborData = ur.cbor().toData();
|
|
1694
|
+
this._fountainEncoder = new FountainEncoder(cborData, maxFragmentLen);
|
|
1606
1695
|
}
|
|
1607
1696
|
/**
|
|
1608
1697
|
* Gets the next part of the encoding.
|
|
@@ -1628,7 +1717,7 @@ var MultipartEncoder = class {
|
|
|
1628
1717
|
*/
|
|
1629
1718
|
_encodePart(part) {
|
|
1630
1719
|
if (part.seqLen === 1) return this._ur.string();
|
|
1631
|
-
const encoded = encodeBytewords(this._encodePartData(part),
|
|
1720
|
+
const encoded = encodeBytewords(this._encodePartData(part), "minimal");
|
|
1632
1721
|
return `ur:${this._ur.urTypeStr()}/${part.seqNum}-${part.seqLen}/${encoded}`;
|
|
1633
1722
|
}
|
|
1634
1723
|
/**
|
|
@@ -1660,7 +1749,6 @@ var MultipartEncoder = class {
|
|
|
1660
1749
|
return this._fountainEncoder.seqLen;
|
|
1661
1750
|
}
|
|
1662
1751
|
};
|
|
1663
|
-
|
|
1664
1752
|
//#endregion
|
|
1665
1753
|
//#region src/multipart-decoder.ts
|
|
1666
1754
|
/**
|
|
@@ -1749,7 +1837,7 @@ var MultipartDecoder = class {
|
|
|
1749
1837
|
* The multipart body is a CBOR array: [seqNum, seqLen, messageLen, checksum, data]
|
|
1750
1838
|
*/
|
|
1751
1839
|
_decodeFountainPart(partInfo) {
|
|
1752
|
-
const decoded = (0, _bcts_dcbor.decodeCbor)(decodeBytewords(partInfo.encodedData,
|
|
1840
|
+
const decoded = (0, _bcts_dcbor.decodeCbor)(decodeBytewords(partInfo.encodedData, "minimal"));
|
|
1753
1841
|
if (decoded.type !== _bcts_dcbor.MajorType.Array) throw new URError("Invalid multipart data: expected CBOR array");
|
|
1754
1842
|
const items = decoded.value;
|
|
1755
1843
|
if (items.length !== 5) throw new URError(`Invalid multipart data: expected 5 elements, got ${items.length}`);
|
|
@@ -1782,7 +1870,6 @@ var MultipartDecoder = class {
|
|
|
1782
1870
|
return this._decodedMessage;
|
|
1783
1871
|
}
|
|
1784
1872
|
};
|
|
1785
|
-
|
|
1786
1873
|
//#endregion
|
|
1787
1874
|
exports.BYTEMOJIS = BYTEMOJIS;
|
|
1788
1875
|
exports.BYTEWORDS = BYTEWORDS;
|
|
@@ -1800,12 +1887,18 @@ exports.URDecodeError = URDecodeError;
|
|
|
1800
1887
|
exports.URError = URError;
|
|
1801
1888
|
exports.URType = URType;
|
|
1802
1889
|
exports.UnexpectedTypeError = UnexpectedTypeError;
|
|
1890
|
+
exports.canonicalizeByteword = canonicalizeByteword;
|
|
1803
1891
|
exports.decodeBytewords = decodeBytewords;
|
|
1804
1892
|
exports.encodeBytemojisIdentifier = encodeBytemojisIdentifier;
|
|
1805
1893
|
exports.encodeBytewords = encodeBytewords;
|
|
1806
1894
|
exports.encodeBytewordsIdentifier = encodeBytewordsIdentifier;
|
|
1895
|
+
exports.encodeToBytemojis = encodeToBytemojis;
|
|
1896
|
+
exports.encodeToMinimalBytewords = encodeToMinimalBytewords;
|
|
1897
|
+
exports.encodeToWords = encodeToWords;
|
|
1807
1898
|
exports.isError = isError;
|
|
1808
1899
|
exports.isURCodable = isURCodable;
|
|
1809
1900
|
exports.isURDecodable = isURDecodable;
|
|
1810
1901
|
exports.isUREncodable = isUREncodable;
|
|
1902
|
+
exports.isValidBytemoji = isValidBytemoji;
|
|
1903
|
+
|
|
1811
1904
|
//# sourceMappingURL=index.cjs.map
|