@atproto/lex-data 0.0.5 → 0.0.6
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/CHANGELOG.md +10 -0
- package/dist/blob.d.ts +28 -2
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +41 -1
- package/dist/blob.js.map +1 -1
- package/dist/uint8array-from-base64.d.ts.map +1 -1
- package/dist/uint8array-from-base64.js +1 -1
- package/dist/uint8array-from-base64.js.map +1 -1
- package/dist/uint8array-to-base64.d.ts.map +1 -1
- package/dist/uint8array-to-base64.js +2 -2
- package/dist/uint8array-to-base64.js.map +1 -1
- package/dist/utf8-from-base64.d.ts +4 -0
- package/dist/utf8-from-base64.d.ts.map +1 -0
- package/dist/utf8-from-base64.js +18 -0
- package/dist/utf8-from-base64.js.map +1 -0
- package/dist/utf8-to-base64.d.ts +4 -0
- package/dist/utf8-to-base64.d.ts.map +1 -0
- package/dist/utf8-to-base64.js +20 -0
- package/dist/utf8-to-base64.js.map +1 -0
- package/dist/utf8.d.ts +3 -0
- package/dist/utf8.d.ts.map +1 -1
- package/dist/utf8.js +16 -3
- package/dist/utf8.js.map +1 -1
- package/package.json +1 -1
- package/src/blob.test.ts +146 -24
- package/src/blob.ts +80 -3
- package/src/uint8array-from-base64.ts +1 -1
- package/src/uint8array-to-base64.test.ts +2 -2
- package/src/uint8array-to-base64.ts +2 -2
- package/src/utf8-from-base64.test.ts +39 -0
- package/src/utf8-from-base64.ts +23 -0
- package/src/utf8-grapheme-len.test.ts +2 -2
- package/src/utf8-len.test.ts +2 -2
- package/src/utf8-to-base64.test.ts +35 -0
- package/src/utf8-to-base64.ts +22 -0
- package/src/utf8.ts +23 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @atproto/lex-data
|
|
2
2
|
|
|
3
|
+
## 0.0.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#4501](https://github.com/bluesky-social/atproto/pull/4501) [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `enumBlobRefs` utility function
|
|
8
|
+
|
|
9
|
+
- [#4501](https://github.com/bluesky-social/atproto/pull/4501) [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Perform strict `BlobRef` validation by default
|
|
10
|
+
|
|
11
|
+
- [#4501](https://github.com/bluesky-social/atproto/pull/4501) [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `base64ToUtf8` and `utf8ToBase64` utilities
|
|
12
|
+
|
|
3
13
|
## 0.0.5
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/blob.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Cid } from './cid.js';
|
|
2
|
+
import { LexValue } from './lex.js';
|
|
2
3
|
/**
|
|
3
4
|
* @note {@link BlobRef} is just a {@link LexMap} with a specific shape.
|
|
4
5
|
*/
|
|
@@ -8,9 +9,17 @@ export type BlobRef = {
|
|
|
8
9
|
ref: Cid;
|
|
9
10
|
size: number;
|
|
10
11
|
};
|
|
11
|
-
export
|
|
12
|
+
export type BlobRefValidationOptions = {
|
|
13
|
+
/**
|
|
14
|
+
* If `false`, skips strict CID validation of {@link BlobRef.ref}, allowing
|
|
15
|
+
* any valid CID. Otherwise, validates that the CID is v1, uses the raw
|
|
16
|
+
* multicodec, and has a sha256 multihash.
|
|
17
|
+
*
|
|
18
|
+
* @defaults to `true`
|
|
19
|
+
*/
|
|
12
20
|
strict?: boolean;
|
|
13
|
-
}
|
|
21
|
+
};
|
|
22
|
+
export declare function isBlobRef(input: unknown, options?: BlobRefValidationOptions): input is BlobRef;
|
|
14
23
|
/**
|
|
15
24
|
* @note {@link LegacyBlobRef} is just a {@link LexMap} with a specific shape.
|
|
16
25
|
*/
|
|
@@ -19,4 +28,21 @@ export type LegacyBlobRef = {
|
|
|
19
28
|
mimeType: string;
|
|
20
29
|
};
|
|
21
30
|
export declare function isLegacyBlobRef(input: unknown): input is LegacyBlobRef;
|
|
31
|
+
export type EnumBlobRefsOptions = BlobRefValidationOptions & {
|
|
32
|
+
/**
|
|
33
|
+
* @defaults to `false`
|
|
34
|
+
*/
|
|
35
|
+
allowLegacy?: boolean;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Enumerates all {@link BlobRef}s (and, optionally, {@link LegacyBlobRef}s)
|
|
39
|
+
* found within a {@link LexValue}.
|
|
40
|
+
*/
|
|
41
|
+
export declare function enumBlobRefs(input: LexValue, options: EnumBlobRefsOptions & {
|
|
42
|
+
allowLegacy: true;
|
|
43
|
+
}): Generator<BlobRef | LegacyBlobRef, void, unknown>;
|
|
44
|
+
export declare function enumBlobRefs(input: LexValue, options?: EnumBlobRefsOptions & {
|
|
45
|
+
allowLegacy?: false;
|
|
46
|
+
}): Generator<BlobRef, void, unknown>;
|
|
47
|
+
export declare function enumBlobRefs(input: LexValue, options?: EnumBlobRefsOptions): Generator<BlobRef | LegacyBlobRef, void, unknown>;
|
|
22
48
|
//# sourceMappingURL=blob.d.ts.map
|
package/dist/blob.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EAKJ,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EAKJ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGnC;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,wBAAwB,GACjC,KAAK,IAAI,OAAO,CAoDlB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CA2BtE;AAED,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,GAAG;IAC3D;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,mBAAmB,GAAG;IAAE,WAAW,EAAE,IAAI,CAAA;CAAE,GACnD,SAAS,CAAC,OAAO,GAAG,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AACpD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EACf,OAAO,CAAC,EAAE,mBAAmB,GAAG;IAAE,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,GACtD,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AACpC,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EACf,OAAO,CAAC,EAAE,mBAAmB,GAC5B,SAAS,CAAC,OAAO,GAAG,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA"}
|
package/dist/blob.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isBlobRef = isBlobRef;
|
|
4
4
|
exports.isLegacyBlobRef = isLegacyBlobRef;
|
|
5
|
+
exports.enumBlobRefs = enumBlobRefs;
|
|
5
6
|
const cid_js_1 = require("./cid.js");
|
|
6
7
|
const object_js_1 = require("./object.js");
|
|
7
8
|
function isBlobRef(input, options) {
|
|
@@ -34,7 +35,7 @@ function isBlobRef(input, options) {
|
|
|
34
35
|
if (!cid) {
|
|
35
36
|
return false;
|
|
36
37
|
}
|
|
37
|
-
if (options?.strict) {
|
|
38
|
+
if (options?.strict !== false) {
|
|
38
39
|
if (cid.version !== 1) {
|
|
39
40
|
return false;
|
|
40
41
|
}
|
|
@@ -71,4 +72,43 @@ function isLegacyBlobRef(input) {
|
|
|
71
72
|
}
|
|
72
73
|
return true;
|
|
73
74
|
}
|
|
75
|
+
function* enumBlobRefs(input, options) {
|
|
76
|
+
const includeLegacy = options?.allowLegacy === true;
|
|
77
|
+
// Using a stack to avoid recursion depth issues.
|
|
78
|
+
const stack = [input];
|
|
79
|
+
// Since we are using a stack, we could end-up in an infinite loop with cyclic
|
|
80
|
+
// structures. Cyclic structures are not valid LexValues and should, thus,
|
|
81
|
+
// never occur, but let's be safe.
|
|
82
|
+
const visited = new Set();
|
|
83
|
+
do {
|
|
84
|
+
const value = stack.pop();
|
|
85
|
+
if (value != null && typeof value === 'object') {
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
if (visited.has(value))
|
|
88
|
+
continue;
|
|
89
|
+
visited.add(value);
|
|
90
|
+
stack.push(...value);
|
|
91
|
+
}
|
|
92
|
+
else if ((0, object_js_1.isPlainProto)(value)) {
|
|
93
|
+
if (visited.has(value))
|
|
94
|
+
continue;
|
|
95
|
+
visited.add(value);
|
|
96
|
+
if (isBlobRef(value, options)) {
|
|
97
|
+
yield value;
|
|
98
|
+
}
|
|
99
|
+
else if (includeLegacy && isLegacyBlobRef(value)) {
|
|
100
|
+
yield value;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
for (const v of Object.values(value)) {
|
|
104
|
+
if (v != null)
|
|
105
|
+
stack.push(v);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} while (stack.length > 0);
|
|
111
|
+
// Optimization: ease GC's work
|
|
112
|
+
visited.clear();
|
|
113
|
+
}
|
|
74
114
|
//# sourceMappingURL=blob.js.map
|
package/dist/blob.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blob.js","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"blob.js","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Cid,\n RAW_BIN_MULTICODEC,\n SHA2_256_MULTIHASH_CODE,\n asCid,\n parseCid,\n} from './cid.js'\nimport { LexValue } from './lex.js'\nimport { isPlainObject, isPlainProto } from './object.js'\n\n/**\n * @note {@link BlobRef} is just a {@link LexMap} with a specific shape.\n */\nexport type BlobRef = {\n $type: 'blob'\n mimeType: string\n ref: Cid\n size: number\n}\n\nexport type BlobRefValidationOptions = {\n /**\n * If `false`, skips strict CID validation of {@link BlobRef.ref}, allowing\n * any valid CID. Otherwise, validates that the CID is v1, uses the raw\n * multicodec, and has a sha256 multihash.\n *\n * @defaults to `true`\n */\n strict?: boolean\n}\n\nexport function isBlobRef(\n input: unknown,\n options?: BlobRefValidationOptions,\n): input is BlobRef {\n if (!isPlainObject(input)) {\n return false\n }\n\n if (input?.$type !== 'blob') {\n return false\n }\n\n const { mimeType, size, ref } = input\n // @NOTE Very basic mime validation\n if (typeof mimeType !== 'string' || !mimeType.includes('/')) {\n return false\n }\n\n if (typeof size !== 'number' || size < 0 || !Number.isSafeInteger(size)) {\n return false\n }\n\n if (typeof ref !== 'object' || ref === null) {\n return false\n }\n\n for (const key in input) {\n if (\n key !== '$type' &&\n key !== 'mimeType' &&\n key !== 'ref' &&\n key !== 'size'\n ) {\n return false\n }\n }\n\n const cid = asCid(ref)\n if (!cid) {\n return false\n }\n\n if (options?.strict !== false) {\n if (cid.version !== 1) {\n return false\n }\n if (cid.code !== RAW_BIN_MULTICODEC) {\n return false\n }\n if (cid.multihash.code !== SHA2_256_MULTIHASH_CODE) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * @note {@link LegacyBlobRef} is just a {@link LexMap} with a specific shape.\n */\nexport type LegacyBlobRef = {\n cid: string\n mimeType: string\n}\n\nexport function isLegacyBlobRef(input: unknown): input is LegacyBlobRef {\n if (!isPlainObject(input)) {\n return false\n }\n\n const { cid, mimeType } = input\n if (typeof cid !== 'string') {\n return false\n }\n\n if (typeof mimeType !== 'string' || mimeType.length === 0) {\n return false\n }\n\n for (const key in input) {\n if (key !== 'cid' && key !== 'mimeType') {\n return false\n }\n }\n\n try {\n parseCid(cid)\n } catch {\n return false\n }\n\n return true\n}\n\nexport type EnumBlobRefsOptions = BlobRefValidationOptions & {\n /**\n * @defaults to `false`\n */\n allowLegacy?: boolean\n}\n\n/**\n * Enumerates all {@link BlobRef}s (and, optionally, {@link LegacyBlobRef}s)\n * found within a {@link LexValue}.\n */\nexport function enumBlobRefs(\n input: LexValue,\n options: EnumBlobRefsOptions & { allowLegacy: true },\n): Generator<BlobRef | LegacyBlobRef, void, unknown>\nexport function enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions & { allowLegacy?: false },\n): Generator<BlobRef, void, unknown>\nexport function enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions,\n): Generator<BlobRef | LegacyBlobRef, void, unknown>\nexport function* enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions,\n): Generator<BlobRef | LegacyBlobRef, void, unknown> {\n const includeLegacy = options?.allowLegacy === true\n\n // Using a stack to avoid recursion depth issues.\n const stack: LexValue[] = [input]\n\n // Since we are using a stack, we could end-up in an infinite loop with cyclic\n // structures. Cyclic structures are not valid LexValues and should, thus,\n // never occur, but let's be safe.\n const visited = new Set<object>()\n\n do {\n const value = stack.pop()!\n\n if (value != null && typeof value === 'object') {\n if (Array.isArray(value)) {\n if (visited.has(value)) continue\n visited.add(value)\n stack.push(...value)\n } else if (isPlainProto(value)) {\n if (visited.has(value)) continue\n visited.add(value)\n if (isBlobRef(value, options)) {\n yield value\n } else if (includeLegacy && isLegacyBlobRef(value)) {\n yield value\n } else {\n for (const v of Object.values(value)) {\n if (v != null) stack.push(v)\n }\n }\n }\n }\n } while (stack.length > 0)\n\n // Optimization: ease GC's work\n visited.clear()\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uint8array-from-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-from-base64.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B;;WAEG;QACH,UAAU,CAAC,EAAE,CACX,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;YACR,wBAAwB;YACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;YACjC,iBAAiB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,qBAAqB,CAAA;SAC/D,KACE,UAAU,CAAA;KAChB;CACF;AAED,eAAO,MAAM,gBAAgB,SAGhB,MAAM,aACD,cAAc,KACvB,UAAU,
|
|
1
|
+
{"version":3,"file":"uint8array-from-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-from-base64.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B;;WAEG;QACH,UAAU,CAAC,EAAE,CACX,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;YACR,wBAAwB;YACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;YACjC,iBAAiB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,qBAAqB,CAAA;SAC/D,KACE,UAAU,CAAA;KAChB;CACF;AAED,eAAO,MAAM,gBAAgB,SAGhB,MAAM,aACD,cAAc,KACvB,UAAU,QAMyB,CAAA;AAE5C,eAAO,MAAM,cAAc,SAEhB,MAAM,aACD,cAAc,KACvB,UAAU,QAQyB,CAAA;AAE1C,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,cAAyB,GAClC,UAAU,CAIZ"}
|
|
@@ -12,7 +12,7 @@ exports.fromBase64Native = typeof Uint8Array.fromBase64 === 'function'
|
|
|
12
12
|
lastChunkHandling: 'loose',
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
-
: null;
|
|
15
|
+
: /* v8 ignore next -- @preserve */ null;
|
|
16
16
|
exports.fromBase64Node = Buffer
|
|
17
17
|
? function fromBase64Node(b64, alphabet = 'base64') {
|
|
18
18
|
const bytes = Buffer.from(b64, alphabet);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uint8array-from-base64.js","sourceRoot":"","sources":["../src/uint8array-from-base64.ts"],"names":[],"mappings":";;;AAiDA,gDAOC;AAxDD,yDAAoD;AACpD,6DAAqD;AAGrD,MAAM,MAAM,GAAG,+BAAY,CAAA;AAkBd,QAAA,gBAAgB,GAC3B,OAAO,UAAU,CAAC,UAAU,KAAK,UAAU;IACzC,CAAC,CAAC,SAAS,gBAAgB,CACvB,GAAW,EACX,WAA2B,QAAQ;QAEnC,OAAO,UAAU,CAAC,UAAW,CAAC,GAAG,EAAE;YACjC,QAAQ;YACR,iBAAiB,EAAE,OAAO;SAC3B,CAAC,CAAA;IACJ,CAAC;IACH,CAAC,CAAC,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"uint8array-from-base64.js","sourceRoot":"","sources":["../src/uint8array-from-base64.ts"],"names":[],"mappings":"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","sourcesContent":["import { fromString } from 'uint8arrays/from-string'\nimport { NodeJSBuffer } from './lib/nodejs-buffer.js'\nimport { Base64Alphabet } from './uint8array-base64.js'\n\nconst Buffer = NodeJSBuffer\n\ndeclare global {\n interface Uint8ArrayConstructor {\n /**\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/fromBase64 Uint8Array.fromBase64()}\n */\n fromBase64?: (\n b64: string,\n options?: {\n /** @default 'base64' */\n alphabet?: 'base64' | 'base64url'\n lastChunkHandling?: 'loose' | 'strict' | 'stop-before-partial'\n },\n ) => Uint8Array\n }\n}\n\nexport const fromBase64Native =\n typeof Uint8Array.fromBase64 === 'function'\n ? function fromBase64Native(\n b64: string,\n alphabet: Base64Alphabet = 'base64',\n ): Uint8Array {\n return Uint8Array.fromBase64!(b64, {\n alphabet,\n lastChunkHandling: 'loose',\n })\n }\n : /* v8 ignore next -- @preserve */ null\n\nexport const fromBase64Node = Buffer\n ? function fromBase64Node(\n b64: string,\n alphabet: Base64Alphabet = 'base64',\n ): Uint8Array {\n const bytes = Buffer.from(b64, alphabet)\n verifyBase64ForBytes(b64, bytes)\n // Convert to Uint8Array because even though Buffer is a sub class of\n // Uint8Array, it serializes differently to Uint8Array (e.g. in JSON) and\n // results in unexpected behavior downstream (e.g. in tests)\n return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n }\n : /* v8 ignore next -- @preserve */ null\n\nexport function fromBase64Ponyfill(\n b64: string,\n alphabet: Base64Alphabet = 'base64',\n): Uint8Array {\n const bytes = fromString(b64, b64.endsWith('=') ? `${alphabet}pad` : alphabet)\n verifyBase64ForBytes(b64, bytes)\n return bytes\n}\n\n// @NOTE NodeJS will silently stop decoding at the first invalid character,\n// while \"uint8arrays/from-string\" will not validate that the padding is\n// correct. The following function performs basic validation to ensure that the\n// input was a valid base64 string. The availability of the \"bytes\" allows\n// to perform checks with O[1] complexity.\nfunction verifyBase64ForBytes(b64: string, bytes: Uint8Array): void {\n const paddingCount = b64.endsWith('==') ? 2 : b64.endsWith('=') ? 1 : 0\n const trimmedLength = b64.length - paddingCount\n const expectedByteLength = Math.floor((trimmedLength * 3) / 4)\n if (bytes.length !== expectedByteLength) {\n throw new Error('Invalid base64 string')\n }\n\n const expectedB64Length = (bytes.length / 3) * 4\n const expectedPaddingCount =\n expectedB64Length % 4 === 0 ? 0 : 4 - (expectedB64Length % 4)\n const expectedFullB64Length = expectedB64Length + expectedPaddingCount\n if (b64.length > expectedFullB64Length) {\n throw new Error('Invalid base64 string')\n }\n\n // The previous might still allow false positive if only the last few\n // chars are invalid.\n for (\n let i = Math.ceil(expectedB64Length);\n i < b64.length - paddingCount;\n i++\n ) {\n const code = b64.charCodeAt(i)\n if (\n !(code >= 65 && code <= 90) && // A-Z\n !(code >= 97 && code <= 122) && // a-z\n !(code >= 48 && code <= 57) && // 0-9\n code !== 43 && // +\n code !== 47 // /\n ) {\n throw new Error('Invalid base64 string')\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uint8array-to-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-to-base64.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;WAEG;QACH,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE;YACpB,wBAAwB;YACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;YACjC,WAAW,CAAC,EAAE,OAAO,CAAA;SACtB,KAAK,MAAM,CAAA;KACb;CACF;AAED,eAAO,MAAM,cAAc,WAGZ,UAAU,aACP,cAAc,KACvB,MAAM,
|
|
1
|
+
{"version":3,"file":"uint8array-to-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-to-base64.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;WAEG;QACH,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE;YACpB,wBAAwB;YACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;YACjC,WAAW,CAAC,EAAE,OAAO,CAAA;SACtB,KAAK,MAAM,CAAA;KACb;CACF;AAED,eAAO,MAAM,cAAc,WAGZ,UAAU,aACP,cAAc,KACvB,MAAM,QAG6B,CAAA;AAE5C,eAAO,MAAM,YAAY,WAEZ,UAAU,aACP,cAAc,KACvB,MAAM,QAc6B,CAAA;AAE1C,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,QAAQ,GAAE,cAAyB,GAClC,MAAM,CAER"}
|
|
@@ -9,7 +9,7 @@ exports.toBase64Native = typeof Uint8Array.prototype.toBase64 === 'function'
|
|
|
9
9
|
? function toBase64Native(bytes, alphabet = 'base64') {
|
|
10
10
|
return bytes.toBase64({ alphabet, omitPadding: true });
|
|
11
11
|
}
|
|
12
|
-
: null;
|
|
12
|
+
: /* v8 ignore next -- @preserve */ null;
|
|
13
13
|
exports.toBase64Node = Buffer
|
|
14
14
|
? function toBase64Node(bytes, alphabet = 'base64') {
|
|
15
15
|
const buffer = bytes instanceof Buffer ? bytes : Buffer.from(bytes);
|
|
@@ -24,7 +24,7 @@ exports.toBase64Node = Buffer
|
|
|
24
24
|
: b64.slice(0, -1) // '='
|
|
25
25
|
: b64;
|
|
26
26
|
}
|
|
27
|
-
: null;
|
|
27
|
+
: /* v8 ignore next -- @preserve */ null;
|
|
28
28
|
function toBase64Ponyfill(bytes, alphabet = 'base64') {
|
|
29
29
|
return (0, to_string_1.toString)(bytes, alphabet);
|
|
30
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uint8array-to-base64.js","sourceRoot":"","sources":["../src/uint8array-to-base64.ts"],"names":[],"mappings":";;;AAiDA,4CAKC;AAtDD,qDAAgD;AAChD,6DAAqD;AAGrD,MAAM,MAAM,GAAG,+BAAY,CAAA;AAed,QAAA,cAAc,GACzB,OAAO,UAAU,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU;IACjD,CAAC,CAAC,SAAS,cAAc,CACrB,KAAiB,EACjB,WAA2B,QAAQ;QAEnC,OAAO,KAAK,CAAC,QAAS,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC;IACH,CAAC,CAAC,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"uint8array-to-base64.js","sourceRoot":"","sources":["../src/uint8array-to-base64.ts"],"names":[],"mappings":";;;AAiDA,4CAKC;AAtDD,qDAAgD;AAChD,6DAAqD;AAGrD,MAAM,MAAM,GAAG,+BAAY,CAAA;AAed,QAAA,cAAc,GACzB,OAAO,UAAU,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU;IACjD,CAAC,CAAC,SAAS,cAAc,CACrB,KAAiB,EACjB,WAA2B,QAAQ;QAEnC,OAAO,KAAK,CAAC,QAAS,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC;IACH,CAAC,CAAC,iCAAiC,CAAC,IAAI,CAAA;AAE/B,QAAA,YAAY,GAAG,MAAM;IAChC,CAAC,CAAC,SAAS,YAAY,CACnB,KAAiB,EACjB,WAA2B,QAAQ;QAEnC,MAAM,MAAM,GAAG,KAAK,YAAY,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnE,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAErC,uDAAuD;QACvD,0EAA0E;QAC1E,sEAAsE;QACtE,6DAA6D;QAC7D,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,SAAS,CAAC,IAAI;YACtD,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,SAAS,CAAC,IAAI;gBACjD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO;gBAC1B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM;YAC3B,CAAC,CAAC,GAAG,CAAA;IACT,CAAC;IACH,CAAC,CAAC,iCAAiC,CAAC,IAAI,CAAA;AAE1C,SAAgB,gBAAgB,CAC9B,KAAiB,EACjB,WAA2B,QAAQ;IAEnC,OAAO,IAAA,oBAAQ,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAClC,CAAC","sourcesContent":["import { toString } from 'uint8arrays/to-string'\nimport { NodeJSBuffer } from './lib/nodejs-buffer.js'\nimport { Base64Alphabet } from './uint8array-base64.js'\n\nconst Buffer = NodeJSBuffer\n\ndeclare global {\n interface Uint8Array {\n /**\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toBase64 Uint8Array.prototype.toBase64()}\n */\n toBase64?: (options?: {\n /** @default 'base64' */\n alphabet?: 'base64' | 'base64url'\n omitPadding?: boolean\n }) => string\n }\n}\n\nexport const toBase64Native =\n typeof Uint8Array.prototype.toBase64 === 'function'\n ? function toBase64Native(\n bytes: Uint8Array,\n alphabet: Base64Alphabet = 'base64',\n ): string {\n return bytes.toBase64!({ alphabet, omitPadding: true })\n }\n : /* v8 ignore next -- @preserve */ null\n\nexport const toBase64Node = Buffer\n ? function toBase64Node(\n bytes: Uint8Array,\n alphabet: Base64Alphabet = 'base64',\n ): string {\n const buffer = bytes instanceof Buffer ? bytes : Buffer.from(bytes)\n const b64 = buffer.toString(alphabet)\n\n // @NOTE We strip padding for strict compatibility with\n // uint8arrays.toString behavior. Tests failing because of the presence of\n // padding are not really synonymous with an actual error and we might\n // (should?) actually want to keep the padding at some point.\n return b64.charCodeAt(b64.length - 1) === /* '=' */ 0x3d\n ? b64.charCodeAt(b64.length - 2) === /* '=' */ 0x3d\n ? b64.slice(0, -2) // '=='\n : b64.slice(0, -1) // '='\n : b64\n }\n : /* v8 ignore next -- @preserve */ null\n\nexport function toBase64Ponyfill(\n bytes: Uint8Array,\n alphabet: Base64Alphabet = 'base64',\n): string {\n return toString(bytes, alphabet)\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Base64Alphabet } from './uint8array-base64.js';
|
|
2
|
+
export declare const utf8FromBase64Node: ((b64: string, alphabet?: Base64Alphabet) => string) | null;
|
|
3
|
+
export declare function utf8FromBase64Ponyfill(b64: string, alphabet?: Base64Alphabet): string;
|
|
4
|
+
//# sourceMappingURL=utf8-from-base64.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utf8-from-base64.d.ts","sourceRoot":"","sources":["../src/utf8-from-base64.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAIvD,eAAO,MAAM,kBAAkB,SAEpB,MAAM,aACD,cAAc,KACvB,MAAM,QAG6B,CAAA;AAG1C,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,GACxB,MAAM,CAGR"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.utf8FromBase64Node = void 0;
|
|
4
|
+
exports.utf8FromBase64Ponyfill = utf8FromBase64Ponyfill;
|
|
5
|
+
const from_string_1 = require("uint8arrays/from-string");
|
|
6
|
+
const nodejs_buffer_js_1 = require("./lib/nodejs-buffer.js");
|
|
7
|
+
const Buffer = nodejs_buffer_js_1.NodeJSBuffer;
|
|
8
|
+
exports.utf8FromBase64Node = Buffer
|
|
9
|
+
? function utf8FromBase64Node(b64, alphabet = 'base64') {
|
|
10
|
+
return Buffer.from(b64, alphabet).toString('utf8');
|
|
11
|
+
}
|
|
12
|
+
: /* v8 ignore next -- @preserve */ null;
|
|
13
|
+
const textDecoder = /*#__PURE__*/ new TextDecoder();
|
|
14
|
+
function utf8FromBase64Ponyfill(b64, alphabet) {
|
|
15
|
+
const bytes = (0, from_string_1.fromString)(b64, alphabet);
|
|
16
|
+
return textDecoder.decode(bytes);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=utf8-from-base64.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utf8-from-base64.js","sourceRoot":"","sources":["../src/utf8-from-base64.ts"],"names":[],"mappings":";;;AAgBA,wDAMC;AAtBD,yDAAoD;AACpD,6DAAqD;AAGrD,MAAM,MAAM,GAAG,+BAAY,CAAA;AAEd,QAAA,kBAAkB,GAAG,MAAM;IACtC,CAAC,CAAC,SAAS,kBAAkB,CACzB,GAAW,EACX,WAA2B,QAAQ;QAEnC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACpD,CAAC;IACH,CAAC,CAAC,iCAAiC,CAAC,IAAI,CAAA;AAE1C,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,WAAW,EAAE,CAAA;AACnD,SAAgB,sBAAsB,CACpC,GAAW,EACX,QAAyB;IAEzB,MAAM,KAAK,GAAG,IAAA,wBAAU,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACvC,OAAO,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAClC,CAAC","sourcesContent":["import { fromString } from 'uint8arrays/from-string'\nimport { NodeJSBuffer } from './lib/nodejs-buffer.js'\nimport { Base64Alphabet } from './uint8array-base64.js'\n\nconst Buffer = NodeJSBuffer\n\nexport const utf8FromBase64Node = Buffer\n ? function utf8FromBase64Node(\n b64: string,\n alphabet: Base64Alphabet = 'base64',\n ): string {\n return Buffer.from(b64, alphabet).toString('utf8')\n }\n : /* v8 ignore next -- @preserve */ null\n\nconst textDecoder = /*#__PURE__*/ new TextDecoder()\nexport function utf8FromBase64Ponyfill(\n b64: string,\n alphabet?: Base64Alphabet,\n): string {\n const bytes = fromString(b64, alphabet)\n return textDecoder.decode(bytes)\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Base64Alphabet } from './uint8array-base64.js';
|
|
2
|
+
export declare const utf8ToBase64Node: ((text: string, alphabet?: Base64Alphabet) => string) | null;
|
|
3
|
+
export declare function utf8ToBase64Ponyfill(text: string, alphabet?: Base64Alphabet): string;
|
|
4
|
+
//# sourceMappingURL=utf8-to-base64.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utf8-to-base64.d.ts","sourceRoot":"","sources":["../src/utf8-to-base64.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAKvD,eAAO,MAAM,gBAAgB,UACO,MAAM,aAAa,cAAc,KAAG,MAAM,QAIpC,CAAA;AAG1C,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,cAAc,GACxB,MAAM,CAGR"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.utf8ToBase64Node = void 0;
|
|
4
|
+
exports.utf8ToBase64Ponyfill = utf8ToBase64Ponyfill;
|
|
5
|
+
const to_string_1 = require("uint8arrays/to-string");
|
|
6
|
+
const nodejs_buffer_js_1 = require("./lib/nodejs-buffer.js");
|
|
7
|
+
const uint8array_to_base64_js_1 = require("./uint8array-to-base64.js");
|
|
8
|
+
const Buffer = nodejs_buffer_js_1.NodeJSBuffer;
|
|
9
|
+
exports.utf8ToBase64Node = Buffer
|
|
10
|
+
? function utf8ToBase64Node(text, alphabet) {
|
|
11
|
+
const buffer = Buffer.from(text, 'utf8');
|
|
12
|
+
return uint8array_to_base64_js_1.toBase64Node(buffer, alphabet);
|
|
13
|
+
}
|
|
14
|
+
: /* v8 ignore next -- @preserve */ null;
|
|
15
|
+
const textEncoder = /*#__PURE__*/ new TextEncoder();
|
|
16
|
+
function utf8ToBase64Ponyfill(text, alphabet) {
|
|
17
|
+
const bytes = textEncoder.encode(text);
|
|
18
|
+
return (0, to_string_1.toString)(bytes, alphabet);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=utf8-to-base64.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utf8-to-base64.js","sourceRoot":"","sources":["../src/utf8-to-base64.ts"],"names":[],"mappings":";;;AAeA,oDAMC;AArBD,qDAAgD;AAChD,6DAAqD;AAErD,uEAAwD;AAExD,MAAM,MAAM,GAAG,+BAAY,CAAA;AAEd,QAAA,gBAAgB,GAAG,MAAM;IACpC,CAAC,CAAC,SAAS,gBAAgB,CAAC,IAAY,EAAE,QAAyB;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACxC,OAAO,sCAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IACxC,CAAC;IACH,CAAC,CAAC,iCAAiC,CAAC,IAAI,CAAA;AAE1C,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,WAAW,EAAE,CAAA;AACnD,SAAgB,oBAAoB,CAClC,IAAY,EACZ,QAAyB;IAEzB,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtC,OAAO,IAAA,oBAAQ,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAClC,CAAC","sourcesContent":["import { toString } from 'uint8arrays/to-string'\nimport { NodeJSBuffer } from './lib/nodejs-buffer.js'\nimport { Base64Alphabet } from './uint8array-base64.js'\nimport { toBase64Node } from './uint8array-to-base64.js'\n\nconst Buffer = NodeJSBuffer\n\nexport const utf8ToBase64Node = Buffer\n ? function utf8ToBase64Node(text: string, alphabet?: Base64Alphabet): string {\n const buffer = Buffer.from(text, 'utf8')\n return toBase64Node!(buffer, alphabet)\n }\n : /* v8 ignore next -- @preserve */ null\n\nconst textEncoder = /*#__PURE__*/ new TextEncoder()\nexport function utf8ToBase64Ponyfill(\n text: string,\n alphabet?: Base64Alphabet,\n): string {\n const bytes = textEncoder.encode(text)\n return toString(bytes, alphabet)\n}\n"]}
|
package/dist/utf8.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Base64Alphabet } from './uint8array.js';
|
|
1
2
|
export declare const graphemeLen: (str: string) => number;
|
|
2
3
|
export declare const utf8Len: (string: string) => number;
|
|
4
|
+
export declare const utf8ToBase64: (str: string, alphabet?: Base64Alphabet) => string;
|
|
5
|
+
export declare const utf8FromBase64: (b64: string, alphabet?: Base64Alphabet) => string;
|
|
3
6
|
//# sourceMappingURL=utf8.d.ts.map
|
package/dist/utf8.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAShD,eAAO,MAAM,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAEY,CAAA;AAUvD,eAAO,MAAM,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAEQ,CAAA;AAElD,eAAO,MAAM,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,KAAK,MAEf,CAAA;AAExD,eAAO,MAAM,cAAc,EAAE,CAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,KACtB,MAEqD,CAAA"}
|
package/dist/utf8.js
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.utf8Len = exports.graphemeLen = void 0;
|
|
3
|
+
exports.utf8FromBase64 = exports.utf8ToBase64 = exports.utf8Len = exports.graphemeLen = void 0;
|
|
4
|
+
const utf8_from_base64_js_1 = require("./utf8-from-base64.js");
|
|
4
5
|
const utf8_grapheme_len_js_1 = require("./utf8-grapheme-len.js");
|
|
5
6
|
const utf8_len_js_1 = require("./utf8-len.js");
|
|
6
|
-
|
|
7
|
+
const utf8_to_base64_js_1 = require("./utf8-to-base64.js");
|
|
8
|
+
exports.graphemeLen =
|
|
9
|
+
/* v8 ignore next -- @preserve */ utf8_grapheme_len_js_1.graphemeLenNative ??
|
|
10
|
+
/* v8 ignore next -- @preserve */ utf8_grapheme_len_js_1.graphemeLenPonyfill;
|
|
11
|
+
/* v8 ignore next -- @preserve */
|
|
7
12
|
if (exports.graphemeLen === utf8_grapheme_len_js_1.graphemeLenPonyfill) {
|
|
8
13
|
/*#__PURE__*/
|
|
9
14
|
console.warn('[@atproto/lex-data]: Intl.Segmenter is not available in this environment. Falling back to ponyfill implementation.');
|
|
10
15
|
}
|
|
11
|
-
exports.utf8Len =
|
|
16
|
+
exports.utf8Len =
|
|
17
|
+
/* v8 ignore next -- @preserve */ utf8_len_js_1.utf8LenNode ??
|
|
18
|
+
/* v8 ignore next -- @preserve */ utf8_len_js_1.utf8LenCompute;
|
|
19
|
+
exports.utf8ToBase64 =
|
|
20
|
+
/* v8 ignore next -- @preserve */ utf8_to_base64_js_1.utf8ToBase64Node ??
|
|
21
|
+
/* v8 ignore next -- @preserve */ utf8_to_base64_js_1.utf8ToBase64Ponyfill;
|
|
22
|
+
exports.utf8FromBase64 =
|
|
23
|
+
/* v8 ignore next -- @preserve */ utf8_from_base64_js_1.utf8FromBase64Node ??
|
|
24
|
+
/* v8 ignore next -- @preserve */ utf8_from_base64_js_1.utf8FromBase64Ponyfill;
|
|
12
25
|
//# sourceMappingURL=utf8.js.map
|
package/dist/utf8.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utf8.js","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"utf8.js","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":";;;AACA,+DAG8B;AAC9B,iEAA+E;AAC/E,+CAA2D;AAC3D,2DAA4E;AAE/D,QAAA,WAAW;AACtB,iCAAiC,CAAC,wCAAiB;IACnD,iCAAiC,CAAC,0CAAmB,CAAA;AAEvD,iCAAiC;AACjC,IAAI,mBAAW,KAAK,0CAAmB,EAAE,CAAC;IACxC,aAAa;IACb,OAAO,CAAC,IAAI,CACV,oHAAoH,CACrH,CAAA;AACH,CAAC;AAEY,QAAA,OAAO;AAClB,iCAAiC,CAAC,yBAAW;IAC7C,iCAAiC,CAAC,4BAAc,CAAA;AAErC,QAAA,YAAY;AACvB,iCAAiC,CAAC,oCAAgB;IAClD,iCAAiC,CAAC,wCAAoB,CAAA;AAE3C,QAAA,cAAc;AAIzB,iCAAiC,CAAC,wCAAkB;IACpD,iCAAiC,CAAC,4CAAsB,CAAA","sourcesContent":["import { Base64Alphabet } from './uint8array.js'\nimport {\n utf8FromBase64Node,\n utf8FromBase64Ponyfill,\n} from './utf8-from-base64.js'\nimport { graphemeLenNative, graphemeLenPonyfill } from './utf8-grapheme-len.js'\nimport { utf8LenCompute, utf8LenNode } from './utf8-len.js'\nimport { utf8ToBase64Node, utf8ToBase64Ponyfill } from './utf8-to-base64.js'\n\nexport const graphemeLen: (str: string) => number =\n /* v8 ignore next -- @preserve */ graphemeLenNative ??\n /* v8 ignore next -- @preserve */ graphemeLenPonyfill\n\n/* v8 ignore next -- @preserve */\nif (graphemeLen === graphemeLenPonyfill) {\n /*#__PURE__*/\n console.warn(\n '[@atproto/lex-data]: Intl.Segmenter is not available in this environment. Falling back to ponyfill implementation.',\n )\n}\n\nexport const utf8Len: (string: string) => number =\n /* v8 ignore next -- @preserve */ utf8LenNode ??\n /* v8 ignore next -- @preserve */ utf8LenCompute\n\nexport const utf8ToBase64: (str: string, alphabet?: Base64Alphabet) => string =\n /* v8 ignore next -- @preserve */ utf8ToBase64Node ??\n /* v8 ignore next -- @preserve */ utf8ToBase64Ponyfill\n\nexport const utf8FromBase64: (\n b64: string,\n alphabet?: Base64Alphabet,\n) => string =\n /* v8 ignore next -- @preserve */ utf8FromBase64Node ??\n /* v8 ignore next -- @preserve */ utf8FromBase64Ponyfill\n"]}
|
package/package.json
CHANGED
package/src/blob.test.ts
CHANGED
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
BlobRef,
|
|
4
|
+
LegacyBlobRef,
|
|
5
|
+
enumBlobRefs,
|
|
6
|
+
isBlobRef,
|
|
7
|
+
isLegacyBlobRef,
|
|
8
|
+
} from './blob.js'
|
|
3
9
|
import { parseCid } from './cid.js'
|
|
10
|
+
import { LexArray, LexMap, LexValue } from './lex.js'
|
|
4
11
|
|
|
5
12
|
// await cidForRawBytes(Buffer.from('Hello, World!'))
|
|
6
|
-
const
|
|
13
|
+
const validBlobCid = parseCid(
|
|
7
14
|
'bafkreig77vqcdozl2wyk6z3cscaj5q5fggi53aoh64fewkdiri3cdauyn4',
|
|
8
15
|
)
|
|
9
16
|
// await cidForLex(Buffer.from('Hello, World!'))
|
|
10
|
-
const
|
|
17
|
+
const invalidBlobCid = parseCid(
|
|
11
18
|
'bafyreic52vzks7wdklat4evp3vimohl55i2unzqpshz2ytka5omzr7exdy',
|
|
12
19
|
)
|
|
13
20
|
|
|
14
21
|
describe(isBlobRef, () => {
|
|
15
22
|
it('tests valid blobCid and lexCid', () => {
|
|
16
|
-
expect(
|
|
17
|
-
expect(
|
|
18
|
-
expect(
|
|
19
|
-
expect(
|
|
23
|
+
expect(validBlobCid.code).toBe(0x55) // raw
|
|
24
|
+
expect(validBlobCid.multihash.code).toBe(0x12) // sha2-256
|
|
25
|
+
expect(invalidBlobCid.code).toBe(0x71) // dag-cbor
|
|
26
|
+
expect(invalidBlobCid.multihash.code).toBe(0x12) // sha2-256
|
|
20
27
|
})
|
|
21
28
|
|
|
22
29
|
it('parses valid blob', () => {
|
|
23
30
|
expect(
|
|
24
31
|
isBlobRef({
|
|
25
32
|
$type: 'blob',
|
|
26
|
-
ref:
|
|
33
|
+
ref: validBlobCid,
|
|
27
34
|
mimeType: 'image/jpeg',
|
|
28
35
|
size: 10000,
|
|
29
36
|
}),
|
|
@@ -33,7 +40,7 @@ describe(isBlobRef, () => {
|
|
|
33
40
|
isBlobRef(
|
|
34
41
|
{
|
|
35
42
|
$type: 'blob',
|
|
36
|
-
ref:
|
|
43
|
+
ref: invalidBlobCid,
|
|
37
44
|
mimeType: 'image/jpeg',
|
|
38
45
|
size: 10000,
|
|
39
46
|
},
|
|
@@ -43,11 +50,22 @@ describe(isBlobRef, () => {
|
|
|
43
50
|
).toBe(true)
|
|
44
51
|
})
|
|
45
52
|
|
|
53
|
+
it('performs strict validation by default', () => {
|
|
54
|
+
expect(
|
|
55
|
+
isBlobRef({
|
|
56
|
+
$type: 'blob',
|
|
57
|
+
ref: invalidBlobCid,
|
|
58
|
+
mimeType: 'image/jpeg',
|
|
59
|
+
size: 10000,
|
|
60
|
+
}),
|
|
61
|
+
).toBe(false)
|
|
62
|
+
})
|
|
63
|
+
|
|
46
64
|
it('rejects invalid inputs', () => {
|
|
47
65
|
expect(
|
|
48
66
|
isBlobRef({
|
|
49
67
|
$type: 'blob',
|
|
50
|
-
ref: { $link:
|
|
68
|
+
ref: { $link: validBlobCid.toString() },
|
|
51
69
|
mimeType: 'image/jpeg',
|
|
52
70
|
size: '10000',
|
|
53
71
|
}),
|
|
@@ -56,7 +74,7 @@ describe(isBlobRef, () => {
|
|
|
56
74
|
expect(
|
|
57
75
|
isBlobRef({
|
|
58
76
|
// $type: 'blob',
|
|
59
|
-
ref:
|
|
77
|
+
ref: validBlobCid,
|
|
60
78
|
mimeType: 'image/jpeg',
|
|
61
79
|
size: 10000,
|
|
62
80
|
}),
|
|
@@ -65,7 +83,7 @@ describe(isBlobRef, () => {
|
|
|
65
83
|
expect(
|
|
66
84
|
isBlobRef({
|
|
67
85
|
$type: 'blob',
|
|
68
|
-
ref:
|
|
86
|
+
ref: validBlobCid,
|
|
69
87
|
mimeType: { toString: () => 'image/jpeg' },
|
|
70
88
|
size: 10000,
|
|
71
89
|
}),
|
|
@@ -75,7 +93,7 @@ describe(isBlobRef, () => {
|
|
|
75
93
|
isBlobRef(
|
|
76
94
|
{
|
|
77
95
|
$type: 'blob',
|
|
78
|
-
ref: { $link:
|
|
96
|
+
ref: { $link: validBlobCid.toString() },
|
|
79
97
|
mimeType: 'image/jpeg',
|
|
80
98
|
size: '10000',
|
|
81
99
|
},
|
|
@@ -112,7 +130,7 @@ describe(isBlobRef, () => {
|
|
|
112
130
|
expect(
|
|
113
131
|
isBlobRef({
|
|
114
132
|
$type: 'blob',
|
|
115
|
-
ref:
|
|
133
|
+
ref: validBlobCid,
|
|
116
134
|
mimeType: 'image/jpeg',
|
|
117
135
|
size: 10000.5,
|
|
118
136
|
}),
|
|
@@ -124,7 +142,7 @@ describe(isBlobRef, () => {
|
|
|
124
142
|
isBlobRef(
|
|
125
143
|
{
|
|
126
144
|
$type: 'blob',
|
|
127
|
-
ref:
|
|
145
|
+
ref: validBlobCid,
|
|
128
146
|
mimeType: 'image/jpeg',
|
|
129
147
|
size: 10000,
|
|
130
148
|
},
|
|
@@ -136,7 +154,7 @@ describe(isBlobRef, () => {
|
|
|
136
154
|
isBlobRef(
|
|
137
155
|
{
|
|
138
156
|
$type: 'blob',
|
|
139
|
-
ref:
|
|
157
|
+
ref: invalidBlobCid,
|
|
140
158
|
mimeType: 'image/jpeg',
|
|
141
159
|
size: 10000,
|
|
142
160
|
},
|
|
@@ -149,7 +167,7 @@ describe(isBlobRef, () => {
|
|
|
149
167
|
expect(
|
|
150
168
|
isBlobRef({
|
|
151
169
|
$type: 'blob',
|
|
152
|
-
ref:
|
|
170
|
+
ref: validBlobCid,
|
|
153
171
|
mimeType: 'image/jpeg',
|
|
154
172
|
size: 10000,
|
|
155
173
|
extra: 'not allowed',
|
|
@@ -160,7 +178,7 @@ describe(isBlobRef, () => {
|
|
|
160
178
|
isBlobRef(
|
|
161
179
|
{
|
|
162
180
|
$type: 'blob',
|
|
163
|
-
ref:
|
|
181
|
+
ref: validBlobCid,
|
|
164
182
|
mimeType: 'image/jpeg',
|
|
165
183
|
size: 10000,
|
|
166
184
|
extra: 'not allowed',
|
|
@@ -194,14 +212,14 @@ describe(isLegacyBlobRef, () => {
|
|
|
194
212
|
it('parses valid legacy blob', () => {
|
|
195
213
|
expect(
|
|
196
214
|
isLegacyBlobRef({
|
|
197
|
-
cid:
|
|
215
|
+
cid: validBlobCid.toString(),
|
|
198
216
|
mimeType: 'image/jpeg',
|
|
199
217
|
}),
|
|
200
218
|
).toBe(true)
|
|
201
219
|
|
|
202
220
|
expect(
|
|
203
221
|
isLegacyBlobRef({
|
|
204
|
-
cid:
|
|
222
|
+
cid: invalidBlobCid.toString(),
|
|
205
223
|
mimeType: 'image/jpeg',
|
|
206
224
|
}),
|
|
207
225
|
).toBe(true)
|
|
@@ -230,21 +248,21 @@ describe(isLegacyBlobRef, () => {
|
|
|
230
248
|
|
|
231
249
|
expect(
|
|
232
250
|
isLegacyBlobRef({
|
|
233
|
-
cid:
|
|
251
|
+
cid: invalidBlobCid.toString(),
|
|
234
252
|
mimeType: { toString: () => 'image/jpeg' },
|
|
235
253
|
}),
|
|
236
254
|
).toBe(false)
|
|
237
255
|
|
|
238
256
|
expect(
|
|
239
257
|
isLegacyBlobRef({
|
|
240
|
-
cid:
|
|
258
|
+
cid: invalidBlobCid.toString(),
|
|
241
259
|
mimeType: 3,
|
|
242
260
|
}),
|
|
243
261
|
).toBe(false)
|
|
244
262
|
|
|
245
263
|
expect(
|
|
246
264
|
isLegacyBlobRef({
|
|
247
|
-
cid:
|
|
265
|
+
cid: invalidBlobCid.toString(),
|
|
248
266
|
mimeType: '',
|
|
249
267
|
}),
|
|
250
268
|
).toBe(false)
|
|
@@ -258,10 +276,114 @@ describe(isLegacyBlobRef, () => {
|
|
|
258
276
|
it('rejects extra keys', () => {
|
|
259
277
|
expect(
|
|
260
278
|
isLegacyBlobRef({
|
|
261
|
-
cid:
|
|
279
|
+
cid: validBlobCid.toString(),
|
|
262
280
|
mimeType: 'image/jpeg',
|
|
263
281
|
extra: 'not allowed',
|
|
264
282
|
}),
|
|
265
283
|
).toBe(false)
|
|
266
284
|
})
|
|
267
285
|
})
|
|
286
|
+
|
|
287
|
+
describe(enumBlobRefs, () => {
|
|
288
|
+
const valid1: BlobRef = {
|
|
289
|
+
$type: 'blob',
|
|
290
|
+
ref: validBlobCid,
|
|
291
|
+
mimeType: 'image/png',
|
|
292
|
+
size: 2048,
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const valid2: BlobRef = {
|
|
296
|
+
$type: 'blob',
|
|
297
|
+
ref: validBlobCid,
|
|
298
|
+
mimeType: 'image/jpeg',
|
|
299
|
+
size: 1024,
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const invalid: BlobRef = {
|
|
303
|
+
$type: 'blob',
|
|
304
|
+
ref: invalidBlobCid,
|
|
305
|
+
mimeType: 'image/jpeg',
|
|
306
|
+
size: 1024,
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const legacy: LegacyBlobRef = {
|
|
310
|
+
cid: validBlobCid.toString(),
|
|
311
|
+
mimeType: 'image/gif',
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const data: LexValue = {
|
|
315
|
+
name: 'example',
|
|
316
|
+
file: { deeply: { nested: { in: { object: { valid1 } } } } },
|
|
317
|
+
attachments: [valid2, invalid, legacy, { description: 'not a blob' }],
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
it('enumerates valid BlobRefs by default', () => {
|
|
321
|
+
const refs = Array.from(enumBlobRefs(data))
|
|
322
|
+
expect(refs).toHaveLength(2)
|
|
323
|
+
expect(refs.includes(valid1)).toBe(true)
|
|
324
|
+
expect(refs.includes(valid2)).toBe(true)
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
describe('strict support', () => {
|
|
328
|
+
it('enumerates valid BlobRefs in strict mode', () => {
|
|
329
|
+
const refs = Array.from(enumBlobRefs(data, { strict: true }))
|
|
330
|
+
expect(refs).toHaveLength(2)
|
|
331
|
+
expect(refs.includes(valid1)).toBe(true)
|
|
332
|
+
expect(refs.includes(valid2)).toBe(true)
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
it('enumerates all BlobRefs in non-strict mode', () => {
|
|
336
|
+
const refs = Array.from(enumBlobRefs(data, { strict: false }))
|
|
337
|
+
expect(refs).toHaveLength(3)
|
|
338
|
+
expect(refs.includes(valid1)).toBe(true)
|
|
339
|
+
expect(refs.includes(valid2)).toBe(true)
|
|
340
|
+
expect(refs.includes(invalid)).toBe(true)
|
|
341
|
+
})
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
describe('legacy support', () => {
|
|
345
|
+
it('returns LegacyBlobRefs when legacy option is enabled', () => {
|
|
346
|
+
const refs = Array.from(enumBlobRefs(data, { allowLegacy: true }))
|
|
347
|
+
expect(refs).toHaveLength(3)
|
|
348
|
+
expect(refs.includes(valid1)).toBe(true)
|
|
349
|
+
expect(refs.includes(valid2)).toBe(true)
|
|
350
|
+
expect(refs.includes(legacy)).toBe(true)
|
|
351
|
+
})
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
describe('safety', () => {
|
|
355
|
+
it('handles cyclic structures without infinite loops', () => {
|
|
356
|
+
const cyclicArray: LexArray = [valid2]
|
|
357
|
+
const cyclicObject: LexMap = {
|
|
358
|
+
name: 'cyclic',
|
|
359
|
+
blob: valid1,
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Creating a cycle
|
|
363
|
+
cyclicArray.push(cyclicArray)
|
|
364
|
+
cyclicObject.self = cyclicObject
|
|
365
|
+
|
|
366
|
+
const refs = Array.from(
|
|
367
|
+
enumBlobRefs({
|
|
368
|
+
cyclicObject,
|
|
369
|
+
cyclicArray,
|
|
370
|
+
}),
|
|
371
|
+
)
|
|
372
|
+
expect(refs).toHaveLength(2)
|
|
373
|
+
expect(refs.includes(valid1)).toBe(true)
|
|
374
|
+
expect(refs.includes(valid2)).toBe(true)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('handles deep structures without exceeding call stack', () => {
|
|
378
|
+
// Creating a deep nested structure
|
|
379
|
+
let deepData: LexMap = { blob: valid1 }
|
|
380
|
+
for (let i = 0; i < 100_000; i++) {
|
|
381
|
+
deepData = { nested: deepData }
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const refs = Array.from(enumBlobRefs(deepData))
|
|
385
|
+
expect(refs).toHaveLength(1)
|
|
386
|
+
expect(refs[0]).toBe(valid1)
|
|
387
|
+
})
|
|
388
|
+
})
|
|
389
|
+
})
|
package/src/blob.ts
CHANGED
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
asCid,
|
|
6
6
|
parseCid,
|
|
7
7
|
} from './cid.js'
|
|
8
|
-
import {
|
|
8
|
+
import { LexValue } from './lex.js'
|
|
9
|
+
import { isPlainObject, isPlainProto } from './object.js'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @note {@link BlobRef} is just a {@link LexMap} with a specific shape.
|
|
@@ -17,9 +18,20 @@ export type BlobRef = {
|
|
|
17
18
|
size: number
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
export type BlobRefValidationOptions = {
|
|
22
|
+
/**
|
|
23
|
+
* If `false`, skips strict CID validation of {@link BlobRef.ref}, allowing
|
|
24
|
+
* any valid CID. Otherwise, validates that the CID is v1, uses the raw
|
|
25
|
+
* multicodec, and has a sha256 multihash.
|
|
26
|
+
*
|
|
27
|
+
* @defaults to `true`
|
|
28
|
+
*/
|
|
29
|
+
strict?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
export function isBlobRef(
|
|
21
33
|
input: unknown,
|
|
22
|
-
options?:
|
|
34
|
+
options?: BlobRefValidationOptions,
|
|
23
35
|
): input is BlobRef {
|
|
24
36
|
if (!isPlainObject(input)) {
|
|
25
37
|
return false
|
|
@@ -59,7 +71,7 @@ export function isBlobRef(
|
|
|
59
71
|
return false
|
|
60
72
|
}
|
|
61
73
|
|
|
62
|
-
if (options?.strict) {
|
|
74
|
+
if (options?.strict !== false) {
|
|
63
75
|
if (cid.version !== 1) {
|
|
64
76
|
return false
|
|
65
77
|
}
|
|
@@ -110,3 +122,68 @@ export function isLegacyBlobRef(input: unknown): input is LegacyBlobRef {
|
|
|
110
122
|
|
|
111
123
|
return true
|
|
112
124
|
}
|
|
125
|
+
|
|
126
|
+
export type EnumBlobRefsOptions = BlobRefValidationOptions & {
|
|
127
|
+
/**
|
|
128
|
+
* @defaults to `false`
|
|
129
|
+
*/
|
|
130
|
+
allowLegacy?: boolean
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Enumerates all {@link BlobRef}s (and, optionally, {@link LegacyBlobRef}s)
|
|
135
|
+
* found within a {@link LexValue}.
|
|
136
|
+
*/
|
|
137
|
+
export function enumBlobRefs(
|
|
138
|
+
input: LexValue,
|
|
139
|
+
options: EnumBlobRefsOptions & { allowLegacy: true },
|
|
140
|
+
): Generator<BlobRef | LegacyBlobRef, void, unknown>
|
|
141
|
+
export function enumBlobRefs(
|
|
142
|
+
input: LexValue,
|
|
143
|
+
options?: EnumBlobRefsOptions & { allowLegacy?: false },
|
|
144
|
+
): Generator<BlobRef, void, unknown>
|
|
145
|
+
export function enumBlobRefs(
|
|
146
|
+
input: LexValue,
|
|
147
|
+
options?: EnumBlobRefsOptions,
|
|
148
|
+
): Generator<BlobRef | LegacyBlobRef, void, unknown>
|
|
149
|
+
export function* enumBlobRefs(
|
|
150
|
+
input: LexValue,
|
|
151
|
+
options?: EnumBlobRefsOptions,
|
|
152
|
+
): Generator<BlobRef | LegacyBlobRef, void, unknown> {
|
|
153
|
+
const includeLegacy = options?.allowLegacy === true
|
|
154
|
+
|
|
155
|
+
// Using a stack to avoid recursion depth issues.
|
|
156
|
+
const stack: LexValue[] = [input]
|
|
157
|
+
|
|
158
|
+
// Since we are using a stack, we could end-up in an infinite loop with cyclic
|
|
159
|
+
// structures. Cyclic structures are not valid LexValues and should, thus,
|
|
160
|
+
// never occur, but let's be safe.
|
|
161
|
+
const visited = new Set<object>()
|
|
162
|
+
|
|
163
|
+
do {
|
|
164
|
+
const value = stack.pop()!
|
|
165
|
+
|
|
166
|
+
if (value != null && typeof value === 'object') {
|
|
167
|
+
if (Array.isArray(value)) {
|
|
168
|
+
if (visited.has(value)) continue
|
|
169
|
+
visited.add(value)
|
|
170
|
+
stack.push(...value)
|
|
171
|
+
} else if (isPlainProto(value)) {
|
|
172
|
+
if (visited.has(value)) continue
|
|
173
|
+
visited.add(value)
|
|
174
|
+
if (isBlobRef(value, options)) {
|
|
175
|
+
yield value
|
|
176
|
+
} else if (includeLegacy && isLegacyBlobRef(value)) {
|
|
177
|
+
yield value
|
|
178
|
+
} else {
|
|
179
|
+
for (const v of Object.values(value)) {
|
|
180
|
+
if (v != null) stack.push(v)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} while (stack.length > 0)
|
|
186
|
+
|
|
187
|
+
// Optimization: ease GC's work
|
|
188
|
+
visited.clear()
|
|
189
|
+
}
|
|
@@ -14,9 +14,9 @@ for (const toBase64 of [
|
|
|
14
14
|
] as const) {
|
|
15
15
|
// Tests should run in NodeJS where implementations are either available or
|
|
16
16
|
// polyfilled (see core-js imports above).
|
|
17
|
-
assert(toBase64
|
|
17
|
+
assert(toBase64, 'toBase64 implementation should not be null')
|
|
18
18
|
|
|
19
|
-
describe(toBase64
|
|
19
|
+
describe(toBase64, () => {
|
|
20
20
|
describe('basic encoding', () => {
|
|
21
21
|
it('encodes empty Uint8Array', () => {
|
|
22
22
|
const encoded = toBase64(new Uint8Array(0))
|
|
@@ -25,7 +25,7 @@ export const toBase64Native =
|
|
|
25
25
|
): string {
|
|
26
26
|
return bytes.toBase64!({ alphabet, omitPadding: true })
|
|
27
27
|
}
|
|
28
|
-
: null
|
|
28
|
+
: /* v8 ignore next -- @preserve */ null
|
|
29
29
|
|
|
30
30
|
export const toBase64Node = Buffer
|
|
31
31
|
? function toBase64Node(
|
|
@@ -45,7 +45,7 @@ export const toBase64Node = Buffer
|
|
|
45
45
|
: b64.slice(0, -1) // '='
|
|
46
46
|
: b64
|
|
47
47
|
}
|
|
48
|
-
: null
|
|
48
|
+
: /* v8 ignore next -- @preserve */ null
|
|
49
49
|
|
|
50
50
|
export function toBase64Ponyfill(
|
|
51
51
|
bytes: Uint8Array,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { assert, describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
utf8FromBase64Node,
|
|
4
|
+
utf8FromBase64Ponyfill,
|
|
5
|
+
} from './utf8-from-base64.js'
|
|
6
|
+
|
|
7
|
+
const strings = [
|
|
8
|
+
'Hello, World!',
|
|
9
|
+
'¡Hola, Mundo!',
|
|
10
|
+
'こんにちは世界',
|
|
11
|
+
'😀👩💻🌍',
|
|
12
|
+
'',
|
|
13
|
+
'𓀀𓁐𓂀𓃰𓄿𓅱𓆑𓇋𓈖𓉔𓊃𓋴𓌳𓍿𓎛𓏏',
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
for (const utf8FromBase64 of [
|
|
17
|
+
utf8FromBase64Node,
|
|
18
|
+
utf8FromBase64Ponyfill,
|
|
19
|
+
] as const) {
|
|
20
|
+
assert(utf8FromBase64, 'implementation should not be null')
|
|
21
|
+
|
|
22
|
+
describe(utf8FromBase64, () => {
|
|
23
|
+
it('decodes base64 to utf8 string', () => {
|
|
24
|
+
for (const text of strings) {
|
|
25
|
+
const b64 = Buffer.from(text, 'utf8').toString('base64')
|
|
26
|
+
const decoded = utf8FromBase64(b64, 'base64')
|
|
27
|
+
expect(decoded).toBe(text)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('decodes base64url to utf8 string', () => {
|
|
32
|
+
for (const text of strings) {
|
|
33
|
+
const b64u = Buffer.from(text, 'utf8').toString('base64url')
|
|
34
|
+
const decoded = utf8FromBase64(b64u, 'base64url')
|
|
35
|
+
expect(decoded).toBe(text)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { fromString } from 'uint8arrays/from-string'
|
|
2
|
+
import { NodeJSBuffer } from './lib/nodejs-buffer.js'
|
|
3
|
+
import { Base64Alphabet } from './uint8array-base64.js'
|
|
4
|
+
|
|
5
|
+
const Buffer = NodeJSBuffer
|
|
6
|
+
|
|
7
|
+
export const utf8FromBase64Node = Buffer
|
|
8
|
+
? function utf8FromBase64Node(
|
|
9
|
+
b64: string,
|
|
10
|
+
alphabet: Base64Alphabet = 'base64',
|
|
11
|
+
): string {
|
|
12
|
+
return Buffer.from(b64, alphabet).toString('utf8')
|
|
13
|
+
}
|
|
14
|
+
: /* v8 ignore next -- @preserve */ null
|
|
15
|
+
|
|
16
|
+
const textDecoder = /*#__PURE__*/ new TextDecoder()
|
|
17
|
+
export function utf8FromBase64Ponyfill(
|
|
18
|
+
b64: string,
|
|
19
|
+
alphabet?: Base64Alphabet,
|
|
20
|
+
): string {
|
|
21
|
+
const bytes = fromString(b64, alphabet)
|
|
22
|
+
return textDecoder.decode(bytes)
|
|
23
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
import { graphemeLenNative, graphemeLenPonyfill } from './utf8-grapheme-len.js'
|
|
3
3
|
|
|
4
|
-
describe(
|
|
4
|
+
describe(graphemeLenNative!, () => {
|
|
5
5
|
it('computes grapheme length', () => {
|
|
6
6
|
expect(graphemeLenNative!('a')).toBe(1)
|
|
7
7
|
expect(graphemeLenNative!('~')).toBe(1)
|
|
@@ -19,7 +19,7 @@ describe('graphemeLenSegmenter', () => {
|
|
|
19
19
|
})
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
describe(
|
|
22
|
+
describe(graphemeLenPonyfill, () => {
|
|
23
23
|
it('computes grapheme length', () => {
|
|
24
24
|
expect(graphemeLenPonyfill('a')).toBe(1)
|
|
25
25
|
expect(graphemeLenPonyfill('~')).toBe(1)
|
package/src/utf8-len.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
import { utf8LenCompute, utf8LenNode } from './utf8-len.js'
|
|
3
3
|
|
|
4
|
-
describe(
|
|
4
|
+
describe(utf8LenNode!, () => {
|
|
5
5
|
it('computes utf8 string length', () => {
|
|
6
6
|
expect(utf8LenNode!('a')).toBe(1)
|
|
7
7
|
expect(utf8LenNode!('~')).toBe(1)
|
|
@@ -16,7 +16,7 @@ describe('utf8LenNode', () => {
|
|
|
16
16
|
})
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
describe(
|
|
19
|
+
describe(utf8LenCompute, () => {
|
|
20
20
|
it('computes utf8 string length', () => {
|
|
21
21
|
expect(utf8LenCompute('a')).toBe(1)
|
|
22
22
|
expect(utf8LenCompute('~')).toBe(1)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { assert, describe, expect, it } from 'vitest'
|
|
2
|
+
import { utf8ToBase64Node, utf8ToBase64Ponyfill } from './utf8-to-base64.js'
|
|
3
|
+
|
|
4
|
+
const strings = [
|
|
5
|
+
'Hello, World!',
|
|
6
|
+
'¡Hola, Mundo!',
|
|
7
|
+
'こんにちは世界',
|
|
8
|
+
'😀👩💻🌍',
|
|
9
|
+
'',
|
|
10
|
+
'𓀀𓁐𓂀𓃰𓄿𓅱𓆑𓇋𓈖𓉔𓊃𓋴𓌳𓍿𓎛𓏏',
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
for (const utf8ToBase64 of [utf8ToBase64Node, utf8ToBase64Ponyfill] as const) {
|
|
14
|
+
assert(utf8ToBase64, 'implementation should not be null')
|
|
15
|
+
|
|
16
|
+
describe(utf8ToBase64, () => {
|
|
17
|
+
it('encodes utf8 string to base64', () => {
|
|
18
|
+
for (const text of strings) {
|
|
19
|
+
const b64 = Buffer.from(text, 'utf8')
|
|
20
|
+
.toString('base64')
|
|
21
|
+
.replaceAll('=', '') // utf8ToBase64 omits padding
|
|
22
|
+
const encoded = utf8ToBase64(text, 'base64')
|
|
23
|
+
expect(encoded).toBe(b64)
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('encodes utf8 string to base64url', () => {
|
|
28
|
+
for (const text of strings) {
|
|
29
|
+
const b64u = Buffer.from(text, 'utf8').toString('base64url')
|
|
30
|
+
const encoded = utf8ToBase64(text, 'base64url')
|
|
31
|
+
expect(encoded).toBe(b64u)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { toString } from 'uint8arrays/to-string'
|
|
2
|
+
import { NodeJSBuffer } from './lib/nodejs-buffer.js'
|
|
3
|
+
import { Base64Alphabet } from './uint8array-base64.js'
|
|
4
|
+
import { toBase64Node } from './uint8array-to-base64.js'
|
|
5
|
+
|
|
6
|
+
const Buffer = NodeJSBuffer
|
|
7
|
+
|
|
8
|
+
export const utf8ToBase64Node = Buffer
|
|
9
|
+
? function utf8ToBase64Node(text: string, alphabet?: Base64Alphabet): string {
|
|
10
|
+
const buffer = Buffer.from(text, 'utf8')
|
|
11
|
+
return toBase64Node!(buffer, alphabet)
|
|
12
|
+
}
|
|
13
|
+
: /* v8 ignore next -- @preserve */ null
|
|
14
|
+
|
|
15
|
+
const textEncoder = /*#__PURE__*/ new TextEncoder()
|
|
16
|
+
export function utf8ToBase64Ponyfill(
|
|
17
|
+
text: string,
|
|
18
|
+
alphabet?: Base64Alphabet,
|
|
19
|
+
): string {
|
|
20
|
+
const bytes = textEncoder.encode(text)
|
|
21
|
+
return toString(bytes, alphabet)
|
|
22
|
+
}
|
package/src/utf8.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import { Base64Alphabet } from './uint8array.js'
|
|
2
|
+
import {
|
|
3
|
+
utf8FromBase64Node,
|
|
4
|
+
utf8FromBase64Ponyfill,
|
|
5
|
+
} from './utf8-from-base64.js'
|
|
1
6
|
import { graphemeLenNative, graphemeLenPonyfill } from './utf8-grapheme-len.js'
|
|
2
7
|
import { utf8LenCompute, utf8LenNode } from './utf8-len.js'
|
|
8
|
+
import { utf8ToBase64Node, utf8ToBase64Ponyfill } from './utf8-to-base64.js'
|
|
3
9
|
|
|
4
10
|
export const graphemeLen: (str: string) => number =
|
|
5
|
-
graphemeLenNative ??
|
|
11
|
+
/* v8 ignore next -- @preserve */ graphemeLenNative ??
|
|
12
|
+
/* v8 ignore next -- @preserve */ graphemeLenPonyfill
|
|
6
13
|
|
|
14
|
+
/* v8 ignore next -- @preserve */
|
|
7
15
|
if (graphemeLen === graphemeLenPonyfill) {
|
|
8
16
|
/*#__PURE__*/
|
|
9
17
|
console.warn(
|
|
@@ -11,4 +19,17 @@ if (graphemeLen === graphemeLenPonyfill) {
|
|
|
11
19
|
)
|
|
12
20
|
}
|
|
13
21
|
|
|
14
|
-
export const utf8Len: (string: string) => number =
|
|
22
|
+
export const utf8Len: (string: string) => number =
|
|
23
|
+
/* v8 ignore next -- @preserve */ utf8LenNode ??
|
|
24
|
+
/* v8 ignore next -- @preserve */ utf8LenCompute
|
|
25
|
+
|
|
26
|
+
export const utf8ToBase64: (str: string, alphabet?: Base64Alphabet) => string =
|
|
27
|
+
/* v8 ignore next -- @preserve */ utf8ToBase64Node ??
|
|
28
|
+
/* v8 ignore next -- @preserve */ utf8ToBase64Ponyfill
|
|
29
|
+
|
|
30
|
+
export const utf8FromBase64: (
|
|
31
|
+
b64: string,
|
|
32
|
+
alphabet?: Base64Alphabet,
|
|
33
|
+
) => string =
|
|
34
|
+
/* v8 ignore next -- @preserve */ utf8FromBase64Node ??
|
|
35
|
+
/* v8 ignore next -- @preserve */ utf8FromBase64Ponyfill
|