@atproto/lex-data 0.0.9 → 0.0.11
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 +14 -0
- package/dist/blob.d.ts +143 -6
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +23 -0
- package/dist/blob.js.map +1 -1
- package/dist/cid.d.ts +211 -27
- package/dist/cid.d.ts.map +1 -1
- package/dist/cid.js +115 -19
- package/dist/cid.js.map +1 -1
- package/dist/lex-equals.d.ts +38 -0
- package/dist/lex-equals.d.ts.map +1 -1
- package/dist/lex-equals.js +38 -0
- package/dist/lex-equals.js.map +1 -1
- package/dist/lex-error.d.ts +83 -3
- package/dist/lex-error.d.ts.map +1 -1
- package/dist/lex-error.js +52 -3
- package/dist/lex-error.js.map +1 -1
- package/dist/lex.d.ts +184 -2
- package/dist/lex.d.ts.map +1 -1
- package/dist/lex.js +99 -0
- package/dist/lex.js.map +1 -1
- package/dist/object.d.ts +54 -4
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +54 -4
- package/dist/object.js.map +1 -1
- package/dist/uint8array.d.ts +96 -4
- package/dist/uint8array.d.ts.map +1 -1
- package/dist/uint8array.js +96 -4
- package/dist/uint8array.js.map +1 -1
- package/dist/utf8.d.ts +77 -0
- package/dist/utf8.d.ts.map +1 -1
- package/dist/utf8.js +77 -0
- package/dist/utf8.js.map +1 -1
- package/package.json +2 -2
- package/src/blob.ts +143 -6
- package/src/cid-implementation.test.ts +7 -15
- package/src/cid.test.ts +14 -16
- package/src/cid.ts +228 -52
- package/src/lex-equals.ts +38 -0
- package/src/lex-error.ts +83 -4
- package/src/lex.ts +187 -1
- package/src/object.ts +54 -4
- package/src/uint8array.ts +96 -4
- package/src/utf8.ts +77 -0
package/dist/uint8array.js
CHANGED
|
@@ -14,18 +14,45 @@ const uint8array_to_base64_js_1 = require("./uint8array-to-base64.js");
|
|
|
14
14
|
/**
|
|
15
15
|
* Encodes a Uint8Array into a base64 string.
|
|
16
16
|
*
|
|
17
|
+
* Uses native Uint8Array.prototype.toBase64 when available (Node.js 24+, modern browsers),
|
|
18
|
+
* falling back to Node.js Buffer or a ponyfill implementation.
|
|
19
|
+
*
|
|
20
|
+
* @param bytes - The binary data to encode
|
|
21
|
+
* @param alphabet - The base64 alphabet to use ('base64' or 'base64url'), defaults to 'base64'
|
|
17
22
|
* @returns The base64 encoded string
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { toBase64 } from '@atproto/lex-data'
|
|
27
|
+
*
|
|
28
|
+
* const bytes = new Uint8Array([72, 101, 108, 108, 111])
|
|
29
|
+
* toBase64(bytes) // 'SGVsbG8='
|
|
30
|
+
* toBase64(bytes, 'base64url') // 'SGVsbG8' (URL-safe, no padding)
|
|
31
|
+
* ```
|
|
18
32
|
*/
|
|
19
33
|
exports.toBase64 =
|
|
20
34
|
/* v8 ignore next -- @preserve */ uint8array_to_base64_js_1.toBase64Native ??
|
|
21
35
|
uint8array_to_base64_js_1.toBase64Node ??
|
|
22
36
|
uint8array_to_base64_js_1.toBase64Ponyfill;
|
|
23
37
|
/**
|
|
24
|
-
* Decodes a base64 string into a Uint8Array.
|
|
25
|
-
*
|
|
38
|
+
* Decodes a base64 string into a Uint8Array.
|
|
39
|
+
*
|
|
40
|
+
* Supports both padded and unpadded base64 strings. Uses native
|
|
41
|
+
* Uint8Array.fromBase64 when available, falling back to Node.js Buffer
|
|
42
|
+
* or a ponyfill implementation.
|
|
26
43
|
*
|
|
27
|
-
* @
|
|
44
|
+
* @param b64 - The base64 string to decode
|
|
45
|
+
* @param alphabet - The base64 alphabet to use ('base64' or 'base64url'), defaults to 'base64'
|
|
46
|
+
* @returns The decoded binary data
|
|
28
47
|
* @throws If the input is not a valid base64 string
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* import { fromBase64 } from '@atproto/lex-data'
|
|
52
|
+
*
|
|
53
|
+
* fromBase64('SGVsbG8=') // Uint8Array([72, 101, 108, 108, 111])
|
|
54
|
+
* fromBase64('SGVsbG8', 'base64url') // Same, URL-safe alphabet
|
|
55
|
+
* ```
|
|
29
56
|
*/
|
|
30
57
|
exports.fromBase64 =
|
|
31
58
|
/* v8 ignore next -- @preserve */ uint8array_from_base64_js_1.fromBase64Native ??
|
|
@@ -36,6 +63,21 @@ if (exports.toBase64 === uint8array_to_base64_js_1.toBase64Ponyfill || exports.f
|
|
|
36
63
|
/*#__PURE__*/
|
|
37
64
|
console.warn('[@atproto/lex-data]: Uint8Array.fromBase64 / Uint8Array.prototype.toBase64 not available in this environment. Falling back to ponyfill implementation.');
|
|
38
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns the input if it is a Uint8Array, otherwise returns undefined.
|
|
68
|
+
*
|
|
69
|
+
* @param input - The value to check
|
|
70
|
+
* @returns The input if it's a Uint8Array, otherwise undefined
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { ifUint8Array } from '@atproto/lex-data'
|
|
75
|
+
*
|
|
76
|
+
* ifUint8Array(new Uint8Array([1, 2])) // Uint8Array([1, 2])
|
|
77
|
+
* ifUint8Array('not binary') // undefined
|
|
78
|
+
* ifUint8Array(new ArrayBuffer(4)) // undefined
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
39
81
|
function ifUint8Array(input) {
|
|
40
82
|
if (input instanceof Uint8Array) {
|
|
41
83
|
return input;
|
|
@@ -45,7 +87,23 @@ function ifUint8Array(input) {
|
|
|
45
87
|
/**
|
|
46
88
|
* Coerces various binary data representations into a Uint8Array.
|
|
47
89
|
*
|
|
48
|
-
*
|
|
90
|
+
* Handles the following input types:
|
|
91
|
+
* - `Uint8Array` - Returned as-is
|
|
92
|
+
* - `ArrayBufferView` (e.g., DataView, other TypedArrays) - Converted to Uint8Array
|
|
93
|
+
* - `ArrayBuffer` - Wrapped in a Uint8Array
|
|
94
|
+
*
|
|
95
|
+
* @param input - The value to convert
|
|
96
|
+
* @returns A Uint8Array, or `undefined` if the input could not be converted
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import { asUint8Array } from '@atproto/lex-data'
|
|
101
|
+
*
|
|
102
|
+
* asUint8Array(new Uint8Array([1, 2])) // Uint8Array([1, 2])
|
|
103
|
+
* asUint8Array(new ArrayBuffer(4)) // Uint8Array of length 4
|
|
104
|
+
* asUint8Array(new Int16Array([1, 2])) // Uint8Array view of the buffer
|
|
105
|
+
* asUint8Array('string') // undefined
|
|
106
|
+
* ```
|
|
49
107
|
*/
|
|
50
108
|
function asUint8Array(input) {
|
|
51
109
|
if (input instanceof Uint8Array) {
|
|
@@ -59,6 +117,22 @@ function asUint8Array(input) {
|
|
|
59
117
|
}
|
|
60
118
|
return undefined;
|
|
61
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Compares two Uint8Arrays for byte-by-byte equality.
|
|
122
|
+
*
|
|
123
|
+
* @param a - First Uint8Array to compare
|
|
124
|
+
* @param b - Second Uint8Array to compare
|
|
125
|
+
* @returns `true` if both arrays have the same length and identical bytes
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* import { ui8Equals } from '@atproto/lex-data'
|
|
130
|
+
*
|
|
131
|
+
* ui8Equals(new Uint8Array([1, 2]), new Uint8Array([1, 2])) // true
|
|
132
|
+
* ui8Equals(new Uint8Array([1, 2]), new Uint8Array([1, 3])) // false
|
|
133
|
+
* ui8Equals(new Uint8Array([1]), new Uint8Array([1, 2])) // false
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
62
136
|
function ui8Equals(a, b) {
|
|
63
137
|
if (a.byteLength !== b.byteLength) {
|
|
64
138
|
return false;
|
|
@@ -70,6 +144,24 @@ function ui8Equals(a, b) {
|
|
|
70
144
|
}
|
|
71
145
|
return true;
|
|
72
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Concatenates multiple Uint8Arrays into a single Uint8Array.
|
|
149
|
+
*
|
|
150
|
+
* Uses Node.js Buffer.concat when available for performance,
|
|
151
|
+
* falling back to a ponyfill implementation.
|
|
152
|
+
*
|
|
153
|
+
* @param arrays - The Uint8Arrays to concatenate
|
|
154
|
+
* @returns A new Uint8Array containing all input bytes in order
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { ui8Concat } from '@atproto/lex-data'
|
|
159
|
+
*
|
|
160
|
+
* const a = new Uint8Array([1, 2])
|
|
161
|
+
* const b = new Uint8Array([3, 4])
|
|
162
|
+
* ui8Concat([a, b]) // Uint8Array([1, 2, 3, 4])
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
73
165
|
exports.ui8Concat =
|
|
74
166
|
/* v8 ignore next -- @preserve */ uint8array_concat_js_1.ui8ConcatNode ?? uint8array_concat_js_1.ui8ConcatPonyfill;
|
|
75
167
|
//# sourceMappingURL=uint8array.js.map
|
package/dist/uint8array.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uint8array.js","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"uint8array.js","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":";;;AAkGA,oCAMC;AAuBD,oCAkBC;AAkBD,8BAYC;AA9KD,iEAAyE;AACzE,2EAIoC;AACpC,uEAIkC;AAIlC,4EAA4E;AAC5E,2EAA2E;AAC3E,2EAA2E;AAC3E,0CAA0C;AAE1C;;;;;;;;;;;;;;;;;;GAkBG;AACU,QAAA,QAAQ;AAInB,iCAAiC,CAAC,wCAAc;IAChD,sCAAY;IACZ,0CAAgB,CAAA;AAElB;;;;;;;;;;;;;;;;;;;GAmBG;AACU,QAAA,UAAU;AAIrB,iCAAiC,CAAC,4CAAgB;IAClD,0CAAc;IACd,8CAAkB,CAAA;AAEpB,iCAAiC;AACjC,IAAI,gBAAQ,KAAK,0CAAgB,IAAI,kBAAU,KAAK,8CAAkB,EAAE,CAAC;IACvE,aAAa;IACb,OAAO,CAAC,IAAI,CACV,wJAAwJ,CACzJ,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,UAAU,CACnB,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC,iBAAiB,CAChD,CAAA;IACH,CAAC;IAED,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,SAAS,CAAC,CAAa,EAAE,CAAa;IACpD,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACU,QAAA,SAAS;AACpB,iCAAiC,CAAC,oCAAa,IAAI,wCAAiB,CAAA","sourcesContent":["import { Base64Alphabet } from './uint8array-base64.js'\nimport { ui8ConcatNode, ui8ConcatPonyfill } from './uint8array-concat.js'\nimport {\n fromBase64Native,\n fromBase64Node,\n fromBase64Ponyfill,\n} from './uint8array-from-base64.js'\nimport {\n toBase64Native,\n toBase64Node,\n toBase64Ponyfill,\n} from './uint8array-to-base64.js'\n\nexport type { Base64Alphabet }\n\n// @TODO drop dependency on uint8arrays package once Uint8Array.fromBase64 /\n// Uint8Array.prototype.toBase64 is widely supported, and mark fromBase64 /\n// toBase64 as deprecated. We can also drop NodeJS specific implementations\n// once NodeJS <24 is no longer supported.\n\n/**\n * Encodes a Uint8Array into a base64 string.\n *\n * Uses native Uint8Array.prototype.toBase64 when available (Node.js 24+, modern browsers),\n * falling back to Node.js Buffer or a ponyfill implementation.\n *\n * @param bytes - The binary data to encode\n * @param alphabet - The base64 alphabet to use ('base64' or 'base64url'), defaults to 'base64'\n * @returns The base64 encoded string\n *\n * @example\n * ```typescript\n * import { toBase64 } from '@atproto/lex-data'\n *\n * const bytes = new Uint8Array([72, 101, 108, 108, 111])\n * toBase64(bytes) // 'SGVsbG8='\n * toBase64(bytes, 'base64url') // 'SGVsbG8' (URL-safe, no padding)\n * ```\n */\nexport const toBase64: (\n bytes: Uint8Array,\n alphabet?: Base64Alphabet,\n) => string =\n /* v8 ignore next -- @preserve */ toBase64Native ??\n toBase64Node ??\n toBase64Ponyfill\n\n/**\n * Decodes a base64 string into a Uint8Array.\n *\n * Supports both padded and unpadded base64 strings. Uses native\n * Uint8Array.fromBase64 when available, falling back to Node.js Buffer\n * or a ponyfill implementation.\n *\n * @param b64 - The base64 string to decode\n * @param alphabet - The base64 alphabet to use ('base64' or 'base64url'), defaults to 'base64'\n * @returns The decoded binary data\n * @throws If the input is not a valid base64 string\n *\n * @example\n * ```typescript\n * import { fromBase64 } from '@atproto/lex-data'\n *\n * fromBase64('SGVsbG8=') // Uint8Array([72, 101, 108, 108, 111])\n * fromBase64('SGVsbG8', 'base64url') // Same, URL-safe alphabet\n * ```\n */\nexport const fromBase64: (\n b64: string,\n alphabet?: Base64Alphabet,\n) => Uint8Array =\n /* v8 ignore next -- @preserve */ fromBase64Native ??\n fromBase64Node ??\n fromBase64Ponyfill\n\n/* v8 ignore next -- @preserve */\nif (toBase64 === toBase64Ponyfill || fromBase64 === fromBase64Ponyfill) {\n /*#__PURE__*/\n console.warn(\n '[@atproto/lex-data]: Uint8Array.fromBase64 / Uint8Array.prototype.toBase64 not available in this environment. Falling back to ponyfill implementation.',\n )\n}\n\n/**\n * Returns the input if it is a Uint8Array, otherwise returns undefined.\n *\n * @param input - The value to check\n * @returns The input if it's a Uint8Array, otherwise undefined\n *\n * @example\n * ```typescript\n * import { ifUint8Array } from '@atproto/lex-data'\n *\n * ifUint8Array(new Uint8Array([1, 2])) // Uint8Array([1, 2])\n * ifUint8Array('not binary') // undefined\n * ifUint8Array(new ArrayBuffer(4)) // undefined\n * ```\n */\nexport function ifUint8Array(input: unknown): Uint8Array | undefined {\n if (input instanceof Uint8Array) {\n return input\n }\n\n return undefined\n}\n\n/**\n * Coerces various binary data representations into a Uint8Array.\n *\n * Handles the following input types:\n * - `Uint8Array` - Returned as-is\n * - `ArrayBufferView` (e.g., DataView, other TypedArrays) - Converted to Uint8Array\n * - `ArrayBuffer` - Wrapped in a Uint8Array\n *\n * @param input - The value to convert\n * @returns A Uint8Array, or `undefined` if the input could not be converted\n *\n * @example\n * ```typescript\n * import { asUint8Array } from '@atproto/lex-data'\n *\n * asUint8Array(new Uint8Array([1, 2])) // Uint8Array([1, 2])\n * asUint8Array(new ArrayBuffer(4)) // Uint8Array of length 4\n * asUint8Array(new Int16Array([1, 2])) // Uint8Array view of the buffer\n * asUint8Array('string') // undefined\n * ```\n */\nexport function asUint8Array(input: unknown): Uint8Array | undefined {\n if (input instanceof Uint8Array) {\n return input\n }\n\n if (ArrayBuffer.isView(input)) {\n return new Uint8Array(\n input.buffer,\n input.byteOffset,\n input.byteLength / Uint8Array.BYTES_PER_ELEMENT,\n )\n }\n\n if (input instanceof ArrayBuffer) {\n return new Uint8Array(input)\n }\n\n return undefined\n}\n\n/**\n * Compares two Uint8Arrays for byte-by-byte equality.\n *\n * @param a - First Uint8Array to compare\n * @param b - Second Uint8Array to compare\n * @returns `true` if both arrays have the same length and identical bytes\n *\n * @example\n * ```typescript\n * import { ui8Equals } from '@atproto/lex-data'\n *\n * ui8Equals(new Uint8Array([1, 2]), new Uint8Array([1, 2])) // true\n * ui8Equals(new Uint8Array([1, 2]), new Uint8Array([1, 3])) // false\n * ui8Equals(new Uint8Array([1]), new Uint8Array([1, 2])) // false\n * ```\n */\nexport function ui8Equals(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) {\n return false\n }\n\n for (let i = 0; i < a.byteLength; i++) {\n if (a[i] !== b[i]) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Concatenates multiple Uint8Arrays into a single Uint8Array.\n *\n * Uses Node.js Buffer.concat when available for performance,\n * falling back to a ponyfill implementation.\n *\n * @param arrays - The Uint8Arrays to concatenate\n * @returns A new Uint8Array containing all input bytes in order\n *\n * @example\n * ```typescript\n * import { ui8Concat } from '@atproto/lex-data'\n *\n * const a = new Uint8Array([1, 2])\n * const b = new Uint8Array([3, 4])\n * ui8Concat([a, b]) // Uint8Array([1, 2, 3, 4])\n * ```\n */\nexport const ui8Concat =\n /* v8 ignore next -- @preserve */ ui8ConcatNode ?? ui8ConcatPonyfill\n"]}
|
package/dist/utf8.d.ts
CHANGED
|
@@ -1,6 +1,83 @@
|
|
|
1
1
|
import { Base64Alphabet } from './uint8array.js';
|
|
2
|
+
/**
|
|
3
|
+
* Counts the number of grapheme clusters (user-perceived characters) in a string.
|
|
4
|
+
*
|
|
5
|
+
* Grapheme clusters represent what users typically think of as "characters",
|
|
6
|
+
* handling complex cases like:
|
|
7
|
+
* - Emoji with skin tones and ZWJ sequences (e.g., family emoji)
|
|
8
|
+
* - Combined characters (e.g., 'e' + combining accent)
|
|
9
|
+
* - Regional indicator pairs (flag emoji)
|
|
10
|
+
*
|
|
11
|
+
* Uses native {@link Intl.Segmenter} when available, falling back to a ponyfill.
|
|
12
|
+
*
|
|
13
|
+
* @param str - The string to measure
|
|
14
|
+
* @returns The number of grapheme clusters
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { graphemeLen } from '@atproto/lex-data'
|
|
19
|
+
*
|
|
20
|
+
* graphemeLen('hello') // 5
|
|
21
|
+
* graphemeLen('cafe\u0301') // 4 (cafe with combining accent)
|
|
22
|
+
* graphemeLen('\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}') // 1 (family emoji)
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
2
25
|
export declare const graphemeLen: (str: string) => number;
|
|
26
|
+
/**
|
|
27
|
+
* Calculates the UTF-8 byte length of a string.
|
|
28
|
+
*
|
|
29
|
+
* Returns the number of bytes the string would occupy when encoded as UTF-8.
|
|
30
|
+
* This is important for Lexicon validation where schemas specify byte limits.
|
|
31
|
+
*
|
|
32
|
+
* Uses Node.js Buffer.byteLength when available for performance,
|
|
33
|
+
* falling back to a computed implementation.
|
|
34
|
+
*
|
|
35
|
+
* @param str - The string to measure
|
|
36
|
+
* @returns The UTF-8 byte length
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { utf8Len } from '@atproto/lex-data'
|
|
41
|
+
*
|
|
42
|
+
* utf8Len('hello') // 5 (ASCII: 1 byte per char)
|
|
43
|
+
* utf8Len('\u00e9') // 2 (e with accent: 2 bytes)
|
|
44
|
+
* utf8Len('\u{1F600}') // 4 (emoji: 4 bytes)
|
|
45
|
+
* utf8Len('\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}') // 25 (family emoji)
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
3
48
|
export declare const utf8Len: (string: string) => number;
|
|
49
|
+
/**
|
|
50
|
+
* Encodes a UTF-8 string to base64.
|
|
51
|
+
*
|
|
52
|
+
* First encodes the string as UTF-8 bytes, then encodes those bytes as base64.
|
|
53
|
+
*
|
|
54
|
+
* @param str - The string to encode
|
|
55
|
+
* @param alphabet - The base64 alphabet to use ('base64' or 'base64url')
|
|
56
|
+
* @returns The base64-encoded string
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* import { utf8ToBase64 } from '@atproto/lex-data'
|
|
61
|
+
*
|
|
62
|
+
* utf8ToBase64('Hello') // 'SGVsbG8='
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
4
65
|
export declare const utf8ToBase64: (str: string, alphabet?: Base64Alphabet) => string;
|
|
66
|
+
/**
|
|
67
|
+
* Decodes a base64 string to UTF-8.
|
|
68
|
+
*
|
|
69
|
+
* Decodes the base64 to bytes, then interprets those bytes as UTF-8 text.
|
|
70
|
+
*
|
|
71
|
+
* @param b64 - The base64 string to decode
|
|
72
|
+
* @param alphabet - The base64 alphabet to use ('base64' or 'base64url')
|
|
73
|
+
* @returns The decoded UTF-8 string
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { utf8FromBase64 } from '@atproto/lex-data'
|
|
78
|
+
*
|
|
79
|
+
* utf8FromBase64('SGVsbG8=') // 'Hello'
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
5
82
|
export declare const utf8FromBase64: (b64: string, alphabet?: Base64Alphabet) => string;
|
|
6
83
|
//# 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":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAShD,eAAO,MAAM,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MACiC,CAAA;AAU5E,eAAO,MAAM,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MACuB,CAAA;AAEjE,eAAO,MAAM,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,KAAK,MACK,CAAA;AAE5E,eAAO,MAAM,cAAc,EAAE,CAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,KACtB,MAC2E,CAAA"}
|
|
1
|
+
{"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAShD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MACiC,CAAA;AAU5E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MACuB,CAAA;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,KAAK,MACK,CAAA;AAE5E;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,EAAE,CAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,KACtB,MAC2E,CAAA"}
|
package/dist/utf8.js
CHANGED
|
@@ -5,6 +5,29 @@ const utf8_from_base64_js_1 = require("./utf8-from-base64.js");
|
|
|
5
5
|
const utf8_grapheme_len_js_1 = require("./utf8-grapheme-len.js");
|
|
6
6
|
const utf8_len_js_1 = require("./utf8-len.js");
|
|
7
7
|
const utf8_to_base64_js_1 = require("./utf8-to-base64.js");
|
|
8
|
+
/**
|
|
9
|
+
* Counts the number of grapheme clusters (user-perceived characters) in a string.
|
|
10
|
+
*
|
|
11
|
+
* Grapheme clusters represent what users typically think of as "characters",
|
|
12
|
+
* handling complex cases like:
|
|
13
|
+
* - Emoji with skin tones and ZWJ sequences (e.g., family emoji)
|
|
14
|
+
* - Combined characters (e.g., 'e' + combining accent)
|
|
15
|
+
* - Regional indicator pairs (flag emoji)
|
|
16
|
+
*
|
|
17
|
+
* Uses native {@link Intl.Segmenter} when available, falling back to a ponyfill.
|
|
18
|
+
*
|
|
19
|
+
* @param str - The string to measure
|
|
20
|
+
* @returns The number of grapheme clusters
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { graphemeLen } from '@atproto/lex-data'
|
|
25
|
+
*
|
|
26
|
+
* graphemeLen('hello') // 5
|
|
27
|
+
* graphemeLen('cafe\u0301') // 4 (cafe with combining accent)
|
|
28
|
+
* graphemeLen('\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}') // 1 (family emoji)
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
8
31
|
exports.graphemeLen =
|
|
9
32
|
/* v8 ignore next -- @preserve */ utf8_grapheme_len_js_1.graphemeLenNative ?? utf8_grapheme_len_js_1.graphemeLenPonyfill;
|
|
10
33
|
/* v8 ignore next -- @preserve */
|
|
@@ -12,10 +35,64 @@ if (exports.graphemeLen === utf8_grapheme_len_js_1.graphemeLenPonyfill) {
|
|
|
12
35
|
/*#__PURE__*/
|
|
13
36
|
console.warn('[@atproto/lex-data]: Intl.Segmenter is not available in this environment. Falling back to ponyfill implementation.');
|
|
14
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Calculates the UTF-8 byte length of a string.
|
|
40
|
+
*
|
|
41
|
+
* Returns the number of bytes the string would occupy when encoded as UTF-8.
|
|
42
|
+
* This is important for Lexicon validation where schemas specify byte limits.
|
|
43
|
+
*
|
|
44
|
+
* Uses Node.js Buffer.byteLength when available for performance,
|
|
45
|
+
* falling back to a computed implementation.
|
|
46
|
+
*
|
|
47
|
+
* @param str - The string to measure
|
|
48
|
+
* @returns The UTF-8 byte length
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { utf8Len } from '@atproto/lex-data'
|
|
53
|
+
*
|
|
54
|
+
* utf8Len('hello') // 5 (ASCII: 1 byte per char)
|
|
55
|
+
* utf8Len('\u00e9') // 2 (e with accent: 2 bytes)
|
|
56
|
+
* utf8Len('\u{1F600}') // 4 (emoji: 4 bytes)
|
|
57
|
+
* utf8Len('\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}') // 25 (family emoji)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
15
60
|
exports.utf8Len =
|
|
16
61
|
/* v8 ignore next -- @preserve */ utf8_len_js_1.utf8LenNode ?? utf8_len_js_1.utf8LenCompute;
|
|
62
|
+
/**
|
|
63
|
+
* Encodes a UTF-8 string to base64.
|
|
64
|
+
*
|
|
65
|
+
* First encodes the string as UTF-8 bytes, then encodes those bytes as base64.
|
|
66
|
+
*
|
|
67
|
+
* @param str - The string to encode
|
|
68
|
+
* @param alphabet - The base64 alphabet to use ('base64' or 'base64url')
|
|
69
|
+
* @returns The base64-encoded string
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { utf8ToBase64 } from '@atproto/lex-data'
|
|
74
|
+
*
|
|
75
|
+
* utf8ToBase64('Hello') // 'SGVsbG8='
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
17
78
|
exports.utf8ToBase64 =
|
|
18
79
|
/* v8 ignore next -- @preserve */ utf8_to_base64_js_1.utf8ToBase64Node ?? utf8_to_base64_js_1.utf8ToBase64Ponyfill;
|
|
80
|
+
/**
|
|
81
|
+
* Decodes a base64 string to UTF-8.
|
|
82
|
+
*
|
|
83
|
+
* Decodes the base64 to bytes, then interprets those bytes as UTF-8 text.
|
|
84
|
+
*
|
|
85
|
+
* @param b64 - The base64 string to decode
|
|
86
|
+
* @param alphabet - The base64 alphabet to use ('base64' or 'base64url')
|
|
87
|
+
* @returns The decoded UTF-8 string
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* import { utf8FromBase64 } from '@atproto/lex-data'
|
|
92
|
+
*
|
|
93
|
+
* utf8FromBase64('SGVsbG8=') // 'Hello'
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
19
96
|
exports.utf8FromBase64 =
|
|
20
97
|
/* v8 ignore next -- @preserve */ utf8_from_base64_js_1.utf8FromBase64Node ?? utf8_from_base64_js_1.utf8FromBase64Ponyfill;
|
|
21
98
|
//# 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":";;;AACA,+DAG8B;AAC9B,iEAA+E;AAC/E,+CAA2D;AAC3D,2DAA4E;
|
|
1
|
+
{"version":3,"file":"utf8.js","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":";;;AACA,+DAG8B;AAC9B,iEAA+E;AAC/E,+CAA2D;AAC3D,2DAA4E;AAE5E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACU,QAAA,WAAW;AACtB,iCAAiC,CAAC,wCAAiB,IAAI,0CAAmB,CAAA;AAE5E,iCAAiC;AACjC,IAAI,mBAAW,KAAK,0CAAmB,EAAE,CAAC;IACxC,aAAa;IACb,OAAO,CAAC,IAAI,CACV,oHAAoH,CACrH,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACU,QAAA,OAAO;AAClB,iCAAiC,CAAC,yBAAW,IAAI,4BAAc,CAAA;AAEjE;;;;;;;;;;;;;;;GAeG;AACU,QAAA,YAAY;AACvB,iCAAiC,CAAC,oCAAgB,IAAI,wCAAoB,CAAA;AAE5E;;;;;;;;;;;;;;;GAeG;AACU,QAAA,cAAc;AAIzB,iCAAiC,CAAC,wCAAkB,IAAI,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\n/**\n * Counts the number of grapheme clusters (user-perceived characters) in a string.\n *\n * Grapheme clusters represent what users typically think of as \"characters\",\n * handling complex cases like:\n * - Emoji with skin tones and ZWJ sequences (e.g., family emoji)\n * - Combined characters (e.g., 'e' + combining accent)\n * - Regional indicator pairs (flag emoji)\n *\n * Uses native {@link Intl.Segmenter} when available, falling back to a ponyfill.\n *\n * @param str - The string to measure\n * @returns The number of grapheme clusters\n *\n * @example\n * ```typescript\n * import { graphemeLen } from '@atproto/lex-data'\n *\n * graphemeLen('hello') // 5\n * graphemeLen('cafe\\u0301') // 4 (cafe with combining accent)\n * graphemeLen('\\u{1F468}\\u{200D}\\u{1F469}\\u{200D}\\u{1F467}\\u{200D}\\u{1F466}') // 1 (family emoji)\n * ```\n */\nexport const graphemeLen: (str: string) => number =\n /* v8 ignore next -- @preserve */ graphemeLenNative ?? 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\n/**\n * Calculates the UTF-8 byte length of a string.\n *\n * Returns the number of bytes the string would occupy when encoded as UTF-8.\n * This is important for Lexicon validation where schemas specify byte limits.\n *\n * Uses Node.js Buffer.byteLength when available for performance,\n * falling back to a computed implementation.\n *\n * @param str - The string to measure\n * @returns The UTF-8 byte length\n *\n * @example\n * ```typescript\n * import { utf8Len } from '@atproto/lex-data'\n *\n * utf8Len('hello') // 5 (ASCII: 1 byte per char)\n * utf8Len('\\u00e9') // 2 (e with accent: 2 bytes)\n * utf8Len('\\u{1F600}') // 4 (emoji: 4 bytes)\n * utf8Len('\\u{1F468}\\u{200D}\\u{1F469}\\u{200D}\\u{1F467}\\u{200D}\\u{1F466}') // 25 (family emoji)\n * ```\n */\nexport const utf8Len: (string: string) => number =\n /* v8 ignore next -- @preserve */ utf8LenNode ?? utf8LenCompute\n\n/**\n * Encodes a UTF-8 string to base64.\n *\n * First encodes the string as UTF-8 bytes, then encodes those bytes as base64.\n *\n * @param str - The string to encode\n * @param alphabet - The base64 alphabet to use ('base64' or 'base64url')\n * @returns The base64-encoded string\n *\n * @example\n * ```typescript\n * import { utf8ToBase64 } from '@atproto/lex-data'\n *\n * utf8ToBase64('Hello') // 'SGVsbG8='\n * ```\n */\nexport const utf8ToBase64: (str: string, alphabet?: Base64Alphabet) => string =\n /* v8 ignore next -- @preserve */ utf8ToBase64Node ?? utf8ToBase64Ponyfill\n\n/**\n * Decodes a base64 string to UTF-8.\n *\n * Decodes the base64 to bytes, then interprets those bytes as UTF-8 text.\n *\n * @param b64 - The base64 string to decode\n * @param alphabet - The base64 alphabet to use ('base64' or 'base64url')\n * @returns The decoded UTF-8 string\n *\n * @example\n * ```typescript\n * import { utf8FromBase64 } from '@atproto/lex-data'\n *\n * utf8FromBase64('SGVsbG8=') // 'Hello'\n * ```\n */\nexport const utf8FromBase64: (\n b64: string,\n alphabet?: Base64Alphabet,\n) => string =\n /* v8 ignore next -- @preserve */ utf8FromBase64Node ?? utf8FromBase64Ponyfill\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-data",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Core utilities for AT Lexicons",
|
|
6
6
|
"keywords": [
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"types": "./dist/index.d.ts",
|
|
32
32
|
"browser": "./dist/index.js",
|
|
33
33
|
"import": "./dist/index.js",
|
|
34
|
-
"
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
package/src/blob.ts
CHANGED
|
@@ -3,7 +3,28 @@ import { LexValue } from './lex.js'
|
|
|
3
3
|
import { isPlainObject, isPlainProto } from './object.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Reference to binary data (like images, videos, etc.) in the AT Protocol data model.
|
|
7
|
+
*
|
|
8
|
+
* A BlobRef is a {@link LexMap} with a specific structure that identifies binary
|
|
9
|
+
* content by its content hash (CID), along with metadata about the content type
|
|
10
|
+
* and size.
|
|
11
|
+
*
|
|
12
|
+
* @typeParam Ref - The type of CID reference, defaults to any {@link Cid}
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import type { BlobRef } from '@atproto/lex-data'
|
|
17
|
+
*
|
|
18
|
+
* const imageRef: BlobRef = {
|
|
19
|
+
* $type: 'blob',
|
|
20
|
+
* mimeType: 'image/jpeg',
|
|
21
|
+
* ref: cid, // CID of the blob content
|
|
22
|
+
* size: 12345
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @see {@link isBlobRef} to check if a value is a valid BlobRef
|
|
27
|
+
* @see {@link LegacyBlobRef} for the older blob reference format
|
|
7
28
|
*/
|
|
8
29
|
export type BlobRef<Ref extends Cid = Cid> = {
|
|
9
30
|
$type: 'blob'
|
|
@@ -12,17 +33,25 @@ export type BlobRef<Ref extends Cid = Cid> = {
|
|
|
12
33
|
size: number
|
|
13
34
|
}
|
|
14
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Options for validating a {@link BlobRef}.
|
|
38
|
+
*/
|
|
15
39
|
export type BlobRefCheckOptions = {
|
|
16
40
|
/**
|
|
17
41
|
* If `false`, skips strict CID validation of {@link BlobRef.ref}, allowing
|
|
18
42
|
* any valid CID. Otherwise, validates that the CID is v1, uses the raw
|
|
19
43
|
* multicodec, and has a sha256 multihash.
|
|
20
44
|
*
|
|
21
|
-
* @
|
|
45
|
+
* @default true
|
|
22
46
|
*/
|
|
23
47
|
strict?: boolean
|
|
24
48
|
}
|
|
25
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Infers the BlobRef type based on the check options.
|
|
52
|
+
*
|
|
53
|
+
* @typeParam TOptions - The options used for checking
|
|
54
|
+
*/
|
|
26
55
|
export type InferCheckedBlobRef<TOptions extends BlobRefCheckOptions> =
|
|
27
56
|
TOptions extends { strict: false }
|
|
28
57
|
? BlobRef
|
|
@@ -30,6 +59,34 @@ export type InferCheckedBlobRef<TOptions extends BlobRefCheckOptions> =
|
|
|
30
59
|
? BlobRef
|
|
31
60
|
: BlobRef<RawCid>
|
|
32
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Type guard to check if a value is a valid {@link BlobRef}.
|
|
64
|
+
*
|
|
65
|
+
* Validates the structure of the input including:
|
|
66
|
+
* - `$type` must be `'blob'`
|
|
67
|
+
* - `mimeType` must be a valid MIME type string (containing '/')
|
|
68
|
+
* - `size` must be a non-negative safe integer
|
|
69
|
+
* - `ref` must be a valid CID (strict validation by default)
|
|
70
|
+
*
|
|
71
|
+
* @param input - The value to check
|
|
72
|
+
* @param options - Optional validation options
|
|
73
|
+
* @returns `true` if the input is a valid BlobRef
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { isBlobRef } from '@atproto/lex-data'
|
|
78
|
+
*
|
|
79
|
+
* if (isBlobRef(data)) {
|
|
80
|
+
* console.log(data.mimeType) // e.g., 'image/jpeg'
|
|
81
|
+
* console.log(data.size) // e.g., 12345
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* // Allow any valid CID (not just raw CIDs)
|
|
85
|
+
* if (isBlobRef(data, { strict: false })) {
|
|
86
|
+
* // ...
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
33
90
|
export function isBlobRef(input: unknown): input is BlobRef<RawCid>
|
|
34
91
|
export function isBlobRef<TOptions extends BlobRefCheckOptions>(
|
|
35
92
|
input: unknown,
|
|
@@ -89,13 +146,53 @@ export function isBlobRef(
|
|
|
89
146
|
}
|
|
90
147
|
|
|
91
148
|
/**
|
|
92
|
-
*
|
|
149
|
+
* Legacy format for blob references used in older AT Protocol data.
|
|
150
|
+
*
|
|
151
|
+
* This is the older format that stores the CID as a string rather than
|
|
152
|
+
* as a structured CID object. New code should use {@link BlobRef} instead.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* import type { LegacyBlobRef } from '@atproto/lex-data'
|
|
157
|
+
*
|
|
158
|
+
* const legacyRef: LegacyBlobRef = {
|
|
159
|
+
* cid: 'bafyreib...',
|
|
160
|
+
* mimeType: 'image/jpeg'
|
|
161
|
+
* }
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @see {@link isLegacyBlobRef} to check if a value is a LegacyBlobRef
|
|
165
|
+
* @see {@link BlobRef} for the current blob reference format
|
|
166
|
+
* @deprecated Use {@link BlobRef} for new code
|
|
93
167
|
*/
|
|
94
168
|
export type LegacyBlobRef = {
|
|
95
169
|
cid: string
|
|
96
170
|
mimeType: string
|
|
97
171
|
}
|
|
98
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Type guard to check if a value is a valid {@link LegacyBlobRef}.
|
|
175
|
+
*
|
|
176
|
+
* Validates the structure of the input:
|
|
177
|
+
* - `cid` must be a valid CID string
|
|
178
|
+
* - `mimeType` must be a non-empty string
|
|
179
|
+
* - No additional properties allowed
|
|
180
|
+
*
|
|
181
|
+
* @param input - The value to check
|
|
182
|
+
* @returns `true` if the input is a valid LegacyBlobRef
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* import { isLegacyBlobRef } from '@atproto/lex-data'
|
|
187
|
+
*
|
|
188
|
+
* if (isLegacyBlobRef(data)) {
|
|
189
|
+
* console.log(data.cid) // CID as string
|
|
190
|
+
* console.log(data.mimeType) // e.g., 'image/jpeg'
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @see {@link isBlobRef} for checking the current blob reference format
|
|
195
|
+
*/
|
|
99
196
|
export function isLegacyBlobRef(input: unknown): input is LegacyBlobRef {
|
|
100
197
|
if (!isPlainObject(input)) {
|
|
101
198
|
return false
|
|
@@ -123,13 +220,24 @@ export function isLegacyBlobRef(input: unknown): input is LegacyBlobRef {
|
|
|
123
220
|
return true
|
|
124
221
|
}
|
|
125
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Options for enumerating blob references within a {@link LexValue}.
|
|
225
|
+
*/
|
|
126
226
|
export type EnumBlobRefsOptions = BlobRefCheckOptions & {
|
|
127
227
|
/**
|
|
128
|
-
* @
|
|
228
|
+
* If `true`, also yields {@link LegacyBlobRef} objects in addition to
|
|
229
|
+
* {@link BlobRef} objects.
|
|
230
|
+
*
|
|
231
|
+
* @default false
|
|
129
232
|
*/
|
|
130
233
|
allowLegacy?: boolean
|
|
131
234
|
}
|
|
132
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Infers the yielded type of {@link enumBlobRefs} based on options.
|
|
238
|
+
*
|
|
239
|
+
* @typeParam TOptions - The options used for enumeration
|
|
240
|
+
*/
|
|
133
241
|
export type InferEnumBlobRefs<TOptions extends EnumBlobRefsOptions> =
|
|
134
242
|
TOptions extends { allowLegacy: true }
|
|
135
243
|
? InferCheckedBlobRef<TOptions> | LegacyBlobRef
|
|
@@ -138,8 +246,37 @@ export type InferEnumBlobRefs<TOptions extends EnumBlobRefsOptions> =
|
|
|
138
246
|
: InferCheckedBlobRef<TOptions>
|
|
139
247
|
|
|
140
248
|
/**
|
|
141
|
-
*
|
|
142
|
-
* found within a {@link LexValue}.
|
|
249
|
+
* Generator that enumerates all {@link BlobRef}s (and, optionally,
|
|
250
|
+
* {@link LegacyBlobRef}s) found within a {@link LexValue}.
|
|
251
|
+
*
|
|
252
|
+
* Performs a deep traversal of the input value, yielding any blob references
|
|
253
|
+
* found. This is useful for extracting all media references from a record.
|
|
254
|
+
*
|
|
255
|
+
* @param input - The LexValue to search for blob references
|
|
256
|
+
* @param options - Optional configuration for the enumeration
|
|
257
|
+
* @yields Each blob reference found in the input
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```typescript
|
|
261
|
+
* import { enumBlobRefs } from '@atproto/lex-data'
|
|
262
|
+
*
|
|
263
|
+
* const record = {
|
|
264
|
+
* text: 'Hello',
|
|
265
|
+
* images: [
|
|
266
|
+
* { $type: 'blob', mimeType: 'image/jpeg', ref: cid1, size: 1000 },
|
|
267
|
+
* { $type: 'blob', mimeType: 'image/png', ref: cid2, size: 2000 }
|
|
268
|
+
* ]
|
|
269
|
+
* }
|
|
270
|
+
*
|
|
271
|
+
* for (const blobRef of enumBlobRefs(record)) {
|
|
272
|
+
* console.log(blobRef.mimeType, blobRef.size)
|
|
273
|
+
* }
|
|
274
|
+
*
|
|
275
|
+
* // Include legacy blob references
|
|
276
|
+
* for (const ref of enumBlobRefs(record, { allowLegacy: true })) {
|
|
277
|
+
* // ref may be BlobRef or LegacyBlobRef
|
|
278
|
+
* }
|
|
279
|
+
* ```
|
|
143
280
|
*/
|
|
144
281
|
export function enumBlobRefs(
|
|
145
282
|
input: LexValue,
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable import/no-deprecated */
|
|
2
|
-
|
|
3
1
|
import { base32 } from 'multiformats/bases/base32'
|
|
4
2
|
import { CID } from 'multiformats/cid'
|
|
5
3
|
import { create as createDigest } from 'multiformats/hashes/digest'
|
|
@@ -75,25 +73,19 @@ describe(BytesCid, () => {
|
|
|
75
73
|
*/
|
|
76
74
|
export function createCustomCid<
|
|
77
75
|
TVersion extends 0 | 1,
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
TCodec extends number,
|
|
77
|
+
THashCode extends number,
|
|
80
78
|
>(
|
|
81
79
|
version: TVersion,
|
|
82
|
-
code:
|
|
83
|
-
|
|
80
|
+
code: TCodec,
|
|
81
|
+
hashCode: THashCode,
|
|
84
82
|
digest: Uint8Array,
|
|
85
|
-
): Cid<TVersion,
|
|
83
|
+
): Cid<TVersion, TCodec, THashCode> {
|
|
86
84
|
return {
|
|
87
85
|
version,
|
|
88
86
|
code,
|
|
89
|
-
multihash: { code:
|
|
90
|
-
bytes: new Uint8Array([
|
|
91
|
-
version,
|
|
92
|
-
code,
|
|
93
|
-
multihashCode,
|
|
94
|
-
digest.length,
|
|
95
|
-
...digest,
|
|
96
|
-
]),
|
|
87
|
+
multihash: { code: hashCode, digest },
|
|
88
|
+
bytes: new Uint8Array([version, code, hashCode, digest.length, ...digest]),
|
|
97
89
|
toString,
|
|
98
90
|
equals,
|
|
99
91
|
}
|