@atproto/lex-data 0.0.1 → 0.0.3

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/blob.d.ts +2 -2
  3. package/dist/blob.d.ts.map +1 -1
  4. package/dist/blob.js +4 -3
  5. package/dist/blob.js.map +1 -1
  6. package/dist/cid.d.ts +48 -2
  7. package/dist/cid.d.ts.map +1 -1
  8. package/dist/cid.js +18 -2
  9. package/dist/cid.js.map +1 -1
  10. package/dist/lex-equals.js +1 -1
  11. package/dist/lex-equals.js.map +1 -1
  12. package/dist/lex.d.ts +2 -2
  13. package/dist/lex.js.map +1 -1
  14. package/dist/uint8array-base64.d.ts +3 -0
  15. package/dist/uint8array-base64.d.ts.map +1 -0
  16. package/dist/uint8array-base64.js +3 -0
  17. package/dist/uint8array-base64.js.map +1 -0
  18. package/dist/uint8array-from-base64.d.ts +4 -3
  19. package/dist/uint8array-from-base64.d.ts.map +1 -1
  20. package/dist/uint8array-from-base64.js +9 -6
  21. package/dist/uint8array-from-base64.js.map +1 -1
  22. package/dist/uint8array-to-base64.d.ts +4 -3
  23. package/dist/uint8array-to-base64.d.ts.map +1 -1
  24. package/dist/uint8array-to-base64.js +7 -6
  25. package/dist/uint8array-to-base64.js.map +1 -1
  26. package/dist/uint8array.d.ts +6 -3
  27. package/dist/uint8array.d.ts.map +1 -1
  28. package/dist/uint8array.js +2 -1
  29. package/dist/uint8array.js.map +1 -1
  30. package/package.json +4 -3
  31. package/src/blob.test.ts +3 -3
  32. package/src/blob.ts +12 -5
  33. package/src/cid.ts +82 -4
  34. package/src/lex-equals.test.ts +8 -8
  35. package/src/lex-equals.ts +2 -2
  36. package/src/lex.ts +2 -2
  37. package/src/object.test.ts +3 -3
  38. package/src/uint8array-base64.ts +2 -0
  39. package/src/uint8array-from-base64.test.ts +33 -19
  40. package/src/uint8array-from-base64.ts +19 -6
  41. package/src/uint8array-to-base64.test.ts +170 -0
  42. package/src/uint8array-to-base64.ts +18 -8
  43. package/src/uint8array.ts +13 -5
package/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # @atproto/lex-data
2
+
3
+ ## 0.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4422](https://github.com/bluesky-social/atproto/pull/4422) [`693784c`](https://github.com/bluesky-social/atproto/commit/693784c3a0dee4b6a29aa1e018fce682dcae148f) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add support for base64url encoding/decoding
8
+
9
+ ## 0.0.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#4390](https://github.com/bluesky-social/atproto/pull/4390) [`1d445af`](https://github.com/bluesky-social/atproto/commit/1d445af2a7fc27eca5a45869b29266e6a2a7f3ba) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use `Cid` interface instead of `CID` class to represent parsed CID data.
14
+
15
+ - [#4390](https://github.com/bluesky-social/atproto/pull/4390) [`1d445af`](https://github.com/bluesky-social/atproto/commit/1d445af2a7fc27eca5a45869b29266e6a2a7f3ba) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Replace use of `CID` with `Cid`
16
+
17
+ - [#4397](https://github.com/bluesky-social/atproto/pull/4397) [`688f9d6`](https://github.com/bluesky-social/atproto/commit/688f9d67597ba96d6e9c4a4aec4d394d42f4cbf4) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `CHANGELOG.md` to npm package
18
+
19
+ - Updated dependencies [[`bcae2b7`](https://github.com/bluesky-social/atproto/commit/bcae2b77b68da6dc2ec202651c8bf41fd5769f69)]:
20
+ - @atproto/syntax@0.4.2
21
+
22
+ ## 0.0.1
23
+
24
+ ### Patch Changes
25
+
26
+ - [#4371](https://github.com/bluesky-social/atproto/pull/4371) [`46550d6`](https://github.com/bluesky-social/atproto/commit/46550d6c1ffb298f57d54eb1904067b2df5a40af) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Release
package/dist/blob.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { CID } from './cid.js';
1
+ import { Cid } from './cid.js';
2
2
  export type BlobRef = {
3
3
  $type: 'blob';
4
4
  mimeType: string;
5
- ref: CID;
5
+ ref: Cid;
6
6
  size: number;
7
7
  };
8
8
  export declare function isBlobRef(input: unknown, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAA+C,MAAM,UAAU,CAAA;AAG3E,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,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,KAAK,IAAI,OAAO,CAmDlB;AAED,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"}
1
+ {"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EAKJ,MAAM,UAAU,CAAA;AAGjB,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,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,KAAK,IAAI,OAAO,CAoDlB;AAED,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"}
package/dist/blob.js CHANGED
@@ -12,7 +12,8 @@ function isBlobRef(input, options) {
12
12
  return false;
13
13
  }
14
14
  const { mimeType, size, ref } = input;
15
- if (typeof mimeType !== 'string') {
15
+ // @NOTE Very basic mime validation
16
+ if (typeof mimeType !== 'string' || !mimeType.includes('/')) {
16
17
  return false;
17
18
  }
18
19
  if (typeof size !== 'number' || size < 0 || !Number.isInteger(size)) {
@@ -29,7 +30,7 @@ function isBlobRef(input, options) {
29
30
  return false;
30
31
  }
31
32
  }
32
- const cid = cid_js_1.CID.asCID(ref);
33
+ const cid = (0, cid_js_1.asCid)(ref);
33
34
  if (!cid) {
34
35
  return false;
35
36
  }
@@ -63,7 +64,7 @@ function isLegacyBlobRef(input) {
63
64
  }
64
65
  }
65
66
  try {
66
- cid_js_1.CID.parse(cid);
67
+ (0, cid_js_1.parseCid)(cid);
67
68
  }
68
69
  catch {
69
70
  return false;
package/dist/blob.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"blob.js","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":";;AAUA,8BAsDC;AAOD,0CA2BC;AAlGD,qCAA2E;AAC3E,2CAA2C;AAS3C,SAAgB,SAAS,CACvB,KAAc,EACd,OAA8B;IAE9B,IAAI,CAAC,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,KAAK,EAAE,KAAK,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;IACrC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QACpE,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IACE,GAAG,KAAK,OAAO;YACf,GAAG,KAAK,UAAU;YAClB,GAAG,KAAK,KAAK;YACb,GAAG,KAAK,MAAM,EACd,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,YAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,2BAAkB,EAAE,CAAC;YACpC,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,gCAAuB,EAAE,CAAC;YACnD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAOD,SAAgB,eAAe,CAAC,KAAc;IAC5C,IAAI,CAAC,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IAC/B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACxC,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,YAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { CID, RAW_BIN_MULTICODEC, SHA2_256_MULTIHASH_CODE } from './cid.js'\nimport { isPlainObject } from './object.js'\n\nexport type BlobRef = {\n $type: 'blob'\n mimeType: string\n ref: CID\n size: number\n}\n\nexport function isBlobRef(\n input: unknown,\n options?: { strict?: boolean },\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 if (typeof mimeType !== 'string') {\n return false\n }\n\n if (typeof size !== 'number' || size < 0 || !Number.isInteger(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 = CID.asCID(ref)\n if (!cid) {\n return false\n }\n\n if (options?.strict) {\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\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') {\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 CID.parse(cid)\n } catch {\n return false\n }\n\n return true\n}\n"]}
1
+ {"version":3,"file":"blob.js","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":";;AAgBA,8BAuDC;AAOD,0CA2BC;AAzGD,qCAMiB;AACjB,2CAA2C;AAS3C,SAAgB,SAAS,CACvB,KAAc,EACd,OAA8B;IAE9B,IAAI,CAAC,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,KAAK,EAAE,KAAK,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;IACrC,mCAAmC;IACnC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QACpE,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IACE,GAAG,KAAK,OAAO;YACf,GAAG,KAAK,UAAU;YAClB,GAAG,KAAK,KAAK;YACb,GAAG,KAAK,MAAM,EACd,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,IAAA,cAAK,EAAC,GAAG,CAAC,CAAA;IACtB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,2BAAkB,EAAE,CAAC;YACpC,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,gCAAuB,EAAE,CAAC;YACnD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAOD,SAAgB,eAAe,CAAC,KAAc;IAC5C,IAAI,CAAC,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IAC/B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACxC,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,IAAA,iBAAQ,EAAC,GAAG,CAAC,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import {\n Cid,\n RAW_BIN_MULTICODEC,\n SHA2_256_MULTIHASH_CODE,\n asCid,\n parseCid,\n} from './cid.js'\nimport { isPlainObject } from './object.js'\n\nexport type BlobRef = {\n $type: 'blob'\n mimeType: string\n ref: Cid\n size: number\n}\n\nexport function isBlobRef(\n input: unknown,\n options?: { strict?: boolean },\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.isInteger(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) {\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\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') {\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"]}
package/dist/cid.d.ts CHANGED
@@ -2,11 +2,57 @@ import { CID } from 'multiformats/cid';
2
2
  export declare const DAG_CBOR_MULTICODEC = 113;
3
3
  export declare const RAW_BIN_MULTICODEC = 85;
4
4
  export declare const SHA2_256_MULTIHASH_CODE = 18;
5
+ export type MultihashDigest<Code extends number = number> = {
6
+ code: Code;
7
+ digest: Uint8Array;
8
+ size: number;
9
+ bytes: Uint8Array;
10
+ };
11
+ declare module 'multiformats/cid' {
12
+ /**
13
+ * @deprecated use the {@link Cid} interface from `@atproto/lex-data`, and
14
+ * related helpers ({@link asCid}, {@link parseCid}, {@link decodeCid},
15
+ * {@link createCid}, {@link isCid}), instead.
16
+ *
17
+ * This is marked as deprecated because we want to discourage direct usage of
18
+ * `multiformats/cid` in dependent packages, and instead have them rely on the
19
+ * {@link Cid} interface from `@atproto/lex-data`. The {@link CID} class from
20
+ * `multiformats` version <10 has compatibility issues with certain TypeScript
21
+ * module resolution strategies, which can lead to type errors in dependent
22
+ * packages.
23
+ *
24
+ * We are stuck with version 9 because `@atproto` packages did not drop
25
+ * CommonJS support yet, and multiformats version 10 only supports ES modules.
26
+ *
27
+ * In order to avoid compatibility issues, while preparing for future breaking
28
+ * changes (CID in multiformats v10+ has a slightly different interface), as
29
+ * we update or swap out `multiformats`, we provide our own stable `Cid`
30
+ * interface.
31
+ */
32
+ interface CID {
33
+ }
34
+ }
5
35
  export { CID };
36
+ /**
37
+ * Interface for working with decoded CID string, compatible with
38
+ * {@link CID} implementation.
39
+ */
40
+ export interface Cid {
41
+ version: 0 | 1;
42
+ code: number;
43
+ multihash: MultihashDigest;
44
+ bytes: Uint8Array;
45
+ equals(other: unknown): boolean;
46
+ toString(): string;
47
+ }
48
+ export declare function asCid(value: unknown): Cid | null;
49
+ export declare function parseCid(input: string): Cid;
50
+ export declare function decodeCid(bytes: Uint8Array): Cid;
51
+ export declare function createCid(code: number, digest: MultihashDigest): Cid;
6
52
  export declare function isCid(value: unknown, options?: {
7
53
  strict?: boolean;
8
- }): value is CID;
54
+ }): value is Cid;
9
55
  export declare function validateCidString(input: string): boolean;
10
- export declare function parseCidString(input: string): CID | undefined;
56
+ export declare function parseCidString(input: string): Cid | undefined;
11
57
  export declare function ensureValidCidString(input: string): void;
12
58
  //# sourceMappingURL=cid.d.ts.map
package/dist/cid.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAEtC,eAAO,MAAM,mBAAmB,MAAO,CAAA;AACvC,eAAO,MAAM,kBAAkB,KAAO,CAAA;AAEtC,eAAO,MAAM,uBAAuB,KAAO,CAAA;AAE3C,OAAO,EAAE,GAAG,EAAE,CAAA;AAEd,wBAAgB,KAAK,CACnB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,KAAK,IAAI,GAAG,CAmBd;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAM7D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAIxD"}
1
+ {"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAEtC,eAAO,MAAM,mBAAmB,MAAO,CAAA;AACvC,eAAO,MAAM,kBAAkB,KAAO,CAAA;AAEtC,eAAO,MAAM,uBAAuB,KAAO,CAAA;AAE3C,MAAM,MAAM,eAAe,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI;IAC1D,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,CAAA;CAClB,CAAA;AAED,OAAO,QAAQ,kBAAkB,CAAC;IAChC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,GAAG;KAAG;CACjB;AAoBD,OAAO,EAAE,GAAG,EAAE,CAAA;AAEd;;;GAGG;AACH,MAAM,WAAW,GAAG;IAClB,OAAO,EAAE,CAAC,GAAG,CAAC,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,eAAe,CAAA;IAC1B,KAAK,EAAE,UAAU,CAAA;IACjB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAA;IAC/B,QAAQ,IAAI,MAAM,CAAA;CACnB;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,GAAG,IAAI,CAEhD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAE3C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,GAAG,CAEhD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,GAAG,CAEpE;AAED,wBAAgB,KAAK,CACnB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,KAAK,IAAI,GAAG,CAmBd;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAM7D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAIxD"}
package/dist/cid.js CHANGED
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CID = exports.SHA2_256_MULTIHASH_CODE = exports.RAW_BIN_MULTICODEC = exports.DAG_CBOR_MULTICODEC = void 0;
4
+ exports.asCid = asCid;
5
+ exports.parseCid = parseCid;
6
+ exports.decodeCid = decodeCid;
7
+ exports.createCid = createCid;
4
8
  exports.isCid = isCid;
5
9
  exports.validateCidString = validateCidString;
6
10
  exports.parseCidString = parseCidString;
@@ -10,8 +14,20 @@ Object.defineProperty(exports, "CID", { enumerable: true, get: function () { ret
10
14
  exports.DAG_CBOR_MULTICODEC = 0x71;
11
15
  exports.RAW_BIN_MULTICODEC = 0x55;
12
16
  exports.SHA2_256_MULTIHASH_CODE = 0x12;
17
+ function asCid(value) {
18
+ return cid_1.CID.asCID(value);
19
+ }
20
+ function parseCid(input) {
21
+ return cid_1.CID.parse(input);
22
+ }
23
+ function decodeCid(bytes) {
24
+ return cid_1.CID.decode(bytes);
25
+ }
26
+ function createCid(code, digest) {
27
+ return cid_1.CID.createV1(code, digest);
28
+ }
13
29
  function isCid(value, options) {
14
- const cid = cid_1.CID.asCID(value);
30
+ const cid = asCid(value);
15
31
  if (!cid) {
16
32
  return false;
17
33
  }
@@ -33,7 +49,7 @@ function validateCidString(input) {
33
49
  }
34
50
  function parseCidString(input) {
35
51
  try {
36
- return cid_1.CID.parse(input);
52
+ return parseCid(input);
37
53
  }
38
54
  catch {
39
55
  return undefined;
package/dist/cid.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cid.js","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":";;;AASA,sBAsBC;AAED,8CAEC;AAED,wCAMC;AAED,oDAIC;AAjDD,0CAAsC;AAO7B,oFAPA,SAAG,OAOA;AALC,QAAA,mBAAmB,GAAG,IAAI,CAAA;AAC1B,QAAA,kBAAkB,GAAG,IAAI,CAAA;AAEzB,QAAA,uBAAuB,GAAG,IAAI,CAAA;AAI3C,SAAgB,KAAK,CACnB,KAAc,EACd,OAA8B;IAE9B,MAAM,GAAG,GAAG,SAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,0BAAkB,IAAI,GAAG,CAAC,IAAI,KAAK,2BAAmB,EAAE,CAAC;YACxE,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,+BAAuB,EAAE,CAAC;YACnD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAAa;IAC7C,OAAO,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,KAAK,CAAA;AACpD,CAAC;AAED,SAAgB,cAAc,CAAC,KAAa;IAC1C,IAAI,CAAC;QACH,OAAO,SAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAgB,oBAAoB,CAAC,KAAa;IAChD,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;AACH,CAAC","sourcesContent":["import { CID } from 'multiformats/cid'\n\nexport const DAG_CBOR_MULTICODEC = 0x71\nexport const RAW_BIN_MULTICODEC = 0x55\n\nexport const SHA2_256_MULTIHASH_CODE = 0x12\n\nexport { CID }\n\nexport function isCid(\n value: unknown,\n options?: { strict?: boolean },\n): value is CID {\n const cid = CID.asCID(value)\n if (!cid) {\n return false\n }\n\n if (options?.strict) {\n if (cid.version !== 1) {\n return false\n }\n if (cid.code !== RAW_BIN_MULTICODEC && cid.code !== DAG_CBOR_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\nexport function validateCidString(input: string): boolean {\n return parseCidString(input)?.toString() === input\n}\n\nexport function parseCidString(input: string): CID | undefined {\n try {\n return CID.parse(input)\n } catch {\n return undefined\n }\n}\n\nexport function ensureValidCidString(input: string): void {\n if (!validateCidString(input)) {\n throw new Error(`Invalid CID string`)\n }\n}\n"]}
1
+ {"version":3,"file":"cid.js","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":";;;AAuEA,sBAEC;AAED,4BAEC;AAED,8BAEC;AAED,8BAEC;AAED,sBAsBC;AAED,8CAEC;AAED,wCAMC;AAED,oDAIC;AA/HD,0CAAsC;AAwD7B,oFAxDA,SAAG,OAwDA;AAtDC,QAAA,mBAAmB,GAAG,IAAI,CAAA;AAC1B,QAAA,kBAAkB,GAAG,IAAI,CAAA;AAEzB,QAAA,uBAAuB,GAAG,IAAI,CAAA;AAkE3C,SAAgB,KAAK,CAAC,KAAc;IAClC,OAAO,SAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AACzB,CAAC;AAED,SAAgB,QAAQ,CAAC,KAAa;IACpC,OAAO,SAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AACzB,CAAC;AAED,SAAgB,SAAS,CAAC,KAAiB;IACzC,OAAO,SAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,SAAgB,SAAS,CAAC,IAAY,EAAE,MAAuB;IAC7D,OAAO,SAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AACnC,CAAC;AAED,SAAgB,KAAK,CACnB,KAAc,EACd,OAA8B;IAE9B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;IACxB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,0BAAkB,IAAI,GAAG,CAAC,IAAI,KAAK,2BAAmB,EAAE,CAAC;YACxE,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,+BAAuB,EAAE,CAAC;YACnD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAAa;IAC7C,OAAO,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,KAAK,CAAA;AACpD,CAAC;AAED,SAAgB,cAAc,CAAC,KAAa;IAC1C,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAgB,oBAAoB,CAAC,KAAa;IAChD,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;AACH,CAAC","sourcesContent":["import { CID } from 'multiformats/cid'\n\nexport const DAG_CBOR_MULTICODEC = 0x71\nexport const RAW_BIN_MULTICODEC = 0x55\n\nexport const SHA2_256_MULTIHASH_CODE = 0x12\n\nexport type MultihashDigest<Code extends number = number> = {\n code: Code\n digest: Uint8Array\n size: number\n bytes: Uint8Array\n}\n\ndeclare module 'multiformats/cid' {\n /**\n * @deprecated use the {@link Cid} interface from `@atproto/lex-data`, and\n * related helpers ({@link asCid}, {@link parseCid}, {@link decodeCid},\n * {@link createCid}, {@link isCid}), instead.\n *\n * This is marked as deprecated because we want to discourage direct usage of\n * `multiformats/cid` in dependent packages, and instead have them rely on the\n * {@link Cid} interface from `@atproto/lex-data`. The {@link CID} class from\n * `multiformats` version <10 has compatibility issues with certain TypeScript\n * module resolution strategies, which can lead to type errors in dependent\n * packages.\n *\n * We are stuck with version 9 because `@atproto` packages did not drop\n * CommonJS support yet, and multiformats version 10 only supports ES modules.\n *\n * In order to avoid compatibility issues, while preparing for future breaking\n * changes (CID in multiformats v10+ has a slightly different interface), as\n * we update or swap out `multiformats`, we provide our own stable `Cid`\n * interface.\n */\n interface CID {}\n}\n\n// CID form \"multiformats\" is not very portable because:\n//\n// - In dependent packages that use \"moduleResolution\" set to \"node16\",\n// \"nodenext\" or \"bundler\", TypeScript fails to properly resolve the\n// multiformats package when importing CID from @atproto/lex-data. This causes\n// type errors in those packages. This is caused by the fact that the\n// multiformats version <10 (which is the last version that supports CommonJS)\n// uses \"exports\" field in package.json, which do not contain \"types\"\n// entrypoints.\n// https://www.npmjs.com/package/multiformats/v/9.9.0?activeTab=code\n// - By defining our own Cid interface and related functions, we can have more\n// control over the API we expose to dependent packages.\n// - It allow us to have a stable interface in case we need to swap out, or\n// eventually update multiformats (should we choose to drop CommonJS support)\n// in the future.\n\n// @NOTE Even though it is not portable, we still re-export CID here so that\n// dependent packages where it can be used, have access to it.\nexport { CID }\n\n/**\n * Interface for working with decoded CID string, compatible with\n * {@link CID} implementation.\n */\nexport interface Cid {\n version: 0 | 1\n code: number\n multihash: MultihashDigest\n bytes: Uint8Array\n equals(other: unknown): boolean\n toString(): string\n}\n\nexport function asCid(value: unknown): Cid | null {\n return CID.asCID(value)\n}\n\nexport function parseCid(input: string): Cid {\n return CID.parse(input)\n}\n\nexport function decodeCid(bytes: Uint8Array): Cid {\n return CID.decode(bytes)\n}\n\nexport function createCid(code: number, digest: MultihashDigest): Cid {\n return CID.createV1(code, digest)\n}\n\nexport function isCid(\n value: unknown,\n options?: { strict?: boolean },\n): value is Cid {\n const cid = asCid(value)\n if (!cid) {\n return false\n }\n\n if (options?.strict) {\n if (cid.version !== 1) {\n return false\n }\n if (cid.code !== RAW_BIN_MULTICODEC && cid.code !== DAG_CBOR_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\nexport function validateCidString(input: string): boolean {\n return parseCidString(input)?.toString() === input\n}\n\nexport function parseCidString(input: string): Cid | undefined {\n try {\n return parseCid(input)\n } catch {\n return undefined\n }\n}\n\nexport function ensureValidCidString(input: string): void {\n if (!validateCidString(input)) {\n throw new Error(`Invalid CID string`)\n }\n}\n"]}
@@ -42,7 +42,7 @@ function lexEquals(a, b) {
42
42
  if ((0, cid_js_1.isCid)(a)) {
43
43
  // @NOTE CID.equals returns its argument when it is falsy (e.g. null or
44
44
  // undefined) so we need to explicitly check that the output is "true".
45
- return cid_js_1.CID.asCID(a).equals(cid_js_1.CID.asCID(b)) === true;
45
+ return (0, cid_js_1.asCid)(a).equals((0, cid_js_1.asCid)(b)) === true;
46
46
  }
47
47
  else if ((0, cid_js_1.isCid)(b)) {
48
48
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"lex-equals.js","sourceRoot":"","sources":["../src/lex-equals.ts"],"names":[],"mappings":"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","sourcesContent":["import { CID, isCid } from './cid.js'\nimport { LexValue } from './lex.js'\nimport { isPlainObject } from './object.js'\nimport { ui8Equals } from './uint8array.js'\n\nexport function lexEquals(a: LexValue, b: LexValue): boolean {\n if (Object.is(a, b)) {\n return true\n }\n\n if (\n a == null ||\n b == null ||\n typeof a !== 'object' ||\n typeof b !== 'object'\n ) {\n return false\n }\n\n if (Array.isArray(a)) {\n if (!Array.isArray(b)) {\n return false\n }\n if (a.length !== b.length) {\n return false\n }\n for (let i = 0; i < a.length; i++) {\n if (!lexEquals(a[i], b[i])) {\n return false\n }\n }\n return true\n } else if (Array.isArray(b)) {\n return false\n }\n\n if (ArrayBuffer.isView(a)) {\n if (!ArrayBuffer.isView(b)) return false\n return ui8Equals(a, b)\n } else if (ArrayBuffer.isView(b)) {\n return false\n }\n\n if (isCid(a)) {\n // @NOTE CID.equals returns its argument when it is falsy (e.g. null or\n // undefined) so we need to explicitly check that the output is \"true\".\n return CID.asCID(a)!.equals(CID.asCID(b)) === true\n } else if (isCid(b)) {\n return false\n }\n\n if (!isPlainObject(a) || !isPlainObject(b)) {\n // Foolproof (should never happen)\n throw new TypeError(\n 'Invalid LexValue (expected CID, Uint8Array, or LexMap)',\n )\n }\n\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (aKeys.length !== bKeys.length) {\n return false\n }\n\n for (const key of aKeys) {\n const aVal = a[key]\n const bVal = b[key]\n\n // Needed because of the optional index signature in the Lex object type\n // though, in practice, aVal should never be undefined here.\n if (aVal === undefined) {\n if (bVal === undefined && bKeys.includes(key)) continue\n return false\n } else if (bVal === undefined) {\n return false\n }\n\n if (!lexEquals(aVal, bVal)) {\n return false\n }\n }\n\n return true\n}\n"]}
1
+ {"version":3,"file":"lex-equals.js","sourceRoot":"","sources":["../src/lex-equals.ts"],"names":[],"mappings":"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","sourcesContent":["import { asCid, isCid } from './cid.js'\nimport { LexValue } from './lex.js'\nimport { isPlainObject } from './object.js'\nimport { ui8Equals } from './uint8array.js'\n\nexport function lexEquals(a: LexValue, b: LexValue): boolean {\n if (Object.is(a, b)) {\n return true\n }\n\n if (\n a == null ||\n b == null ||\n typeof a !== 'object' ||\n typeof b !== 'object'\n ) {\n return false\n }\n\n if (Array.isArray(a)) {\n if (!Array.isArray(b)) {\n return false\n }\n if (a.length !== b.length) {\n return false\n }\n for (let i = 0; i < a.length; i++) {\n if (!lexEquals(a[i], b[i])) {\n return false\n }\n }\n return true\n } else if (Array.isArray(b)) {\n return false\n }\n\n if (ArrayBuffer.isView(a)) {\n if (!ArrayBuffer.isView(b)) return false\n return ui8Equals(a, b)\n } else if (ArrayBuffer.isView(b)) {\n return false\n }\n\n if (isCid(a)) {\n // @NOTE CID.equals returns its argument when it is falsy (e.g. null or\n // undefined) so we need to explicitly check that the output is \"true\".\n return asCid(a)!.equals(asCid(b)) === true\n } else if (isCid(b)) {\n return false\n }\n\n if (!isPlainObject(a) || !isPlainObject(b)) {\n // Foolproof (should never happen)\n throw new TypeError(\n 'Invalid LexValue (expected CID, Uint8Array, or LexMap)',\n )\n }\n\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (aKeys.length !== bKeys.length) {\n return false\n }\n\n for (const key of aKeys) {\n const aVal = a[key]\n const bVal = b[key]\n\n // Needed because of the optional index signature in the Lex object type\n // though, in practice, aVal should never be undefined here.\n if (aVal === undefined) {\n if (bVal === undefined && bKeys.includes(key)) continue\n return false\n } else if (bVal === undefined) {\n return false\n }\n\n if (!lexEquals(aVal, bVal)) {\n return false\n }\n }\n\n return true\n}\n"]}
package/dist/lex.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { CID } from './cid.js';
2
- export type LexScalar = number | string | boolean | null | CID | Uint8Array;
1
+ import { Cid } from './cid.js';
2
+ export type LexScalar = number | string | boolean | null | Cid | Uint8Array;
3
3
  export type LexValue = LexScalar | LexValue[] | {
4
4
  [_ in string]?: LexValue;
5
5
  };
package/dist/lex.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lex.js","sourceRoot":"","sources":["../src/lex.ts"],"names":[],"mappings":"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","sourcesContent":["import { CID, isCid } from './cid.js'\nimport { isPlainObject } from './object.js'\n\n// @NOTE BlobRef is just a special case of LexMap.\n\nexport type LexScalar = number | string | boolean | null | CID | Uint8Array\nexport type LexValue = LexScalar | LexValue[] | { [_ in string]?: LexValue }\nexport type LexMap = { [_ in string]?: LexValue }\nexport type LexArray = LexValue[]\n\nexport function isLexMap(value: unknown): value is LexMap {\n if (!isPlainObject(value)) return false\n for (const key in value) {\n if (!isLexValue(value[key])) return false\n }\n return true\n}\n\nexport function isLexArray(value: unknown): value is LexArray {\n if (!Array.isArray(value)) return false\n for (let i = 0; i < value.length; i++) {\n if (!isLexValue(value[i])) return false\n }\n return true\n}\n\nexport function isLexScalar(value: unknown): value is LexScalar {\n switch (typeof value) {\n case 'object':\n if (value === null) return true\n return value instanceof Uint8Array || isCid(value)\n case 'string':\n case 'boolean':\n return true\n case 'number':\n if (Number.isInteger(value)) return true\n throw new TypeError(`Invalid Lex value: ${value}`)\n default:\n throw new TypeError(`Invalid Lex value: ${typeof value}`)\n }\n}\n\nexport function isLexValue(value: unknown): value is LexValue {\n switch (typeof value) {\n case 'number':\n if (!Number.isInteger(value)) return false\n // fallthrough\n case 'string':\n case 'boolean':\n return true\n case 'object':\n if (value === null) return true\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (!isLexValue(value[i])) return false\n }\n return true\n }\n if (isPlainObject(value)) {\n for (const key in value) {\n if (!isLexValue(value[key])) return false\n }\n return true\n }\n if (value instanceof Uint8Array) return true\n if (isCid(value)) return true\n // fallthrough\n default:\n return false\n }\n}\n\nexport type TypedLexMap = LexMap & { $type: string }\nexport function isTypedLexMap(value: LexValue): value is TypedLexMap {\n return (\n isLexMap(value) && typeof value.$type === 'string' && value.$type.length > 0\n )\n}\n"]}
1
+ {"version":3,"file":"lex.js","sourceRoot":"","sources":["../src/lex.ts"],"names":[],"mappings":"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","sourcesContent":["import { Cid, isCid } from './cid.js'\nimport { isPlainObject } from './object.js'\n\n// @NOTE BlobRef is just a special case of LexMap.\n\nexport type LexScalar = number | string | boolean | null | Cid | Uint8Array\nexport type LexValue = LexScalar | LexValue[] | { [_ in string]?: LexValue }\nexport type LexMap = { [_ in string]?: LexValue }\nexport type LexArray = LexValue[]\n\nexport function isLexMap(value: unknown): value is LexMap {\n if (!isPlainObject(value)) return false\n for (const key in value) {\n if (!isLexValue(value[key])) return false\n }\n return true\n}\n\nexport function isLexArray(value: unknown): value is LexArray {\n if (!Array.isArray(value)) return false\n for (let i = 0; i < value.length; i++) {\n if (!isLexValue(value[i])) return false\n }\n return true\n}\n\nexport function isLexScalar(value: unknown): value is LexScalar {\n switch (typeof value) {\n case 'object':\n if (value === null) return true\n return value instanceof Uint8Array || isCid(value)\n case 'string':\n case 'boolean':\n return true\n case 'number':\n if (Number.isInteger(value)) return true\n throw new TypeError(`Invalid Lex value: ${value}`)\n default:\n throw new TypeError(`Invalid Lex value: ${typeof value}`)\n }\n}\n\nexport function isLexValue(value: unknown): value is LexValue {\n switch (typeof value) {\n case 'number':\n if (!Number.isInteger(value)) return false\n // fallthrough\n case 'string':\n case 'boolean':\n return true\n case 'object':\n if (value === null) return true\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (!isLexValue(value[i])) return false\n }\n return true\n }\n if (isPlainObject(value)) {\n for (const key in value) {\n if (!isLexValue(value[key])) return false\n }\n return true\n }\n if (value instanceof Uint8Array) return true\n if (isCid(value)) return true\n // fallthrough\n default:\n return false\n }\n}\n\nexport type TypedLexMap = LexMap & { $type: string }\nexport function isTypedLexMap(value: LexValue): value is TypedLexMap {\n return (\n isLexMap(value) && typeof value.$type === 'string' && value.$type.length > 0\n )\n}\n"]}
@@ -0,0 +1,3 @@
1
+ /** @default 'base64' */
2
+ export type Base64Alphabet = 'base64' | 'base64url';
3
+ //# sourceMappingURL=uint8array-base64.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint8array-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-base64.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,WAAW,CAAA"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=uint8array-base64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint8array-base64.js","sourceRoot":"","sources":["../src/uint8array-base64.ts"],"names":[],"mappings":"","sourcesContent":["/** @default 'base64' */\nexport type Base64Alphabet = 'base64' | 'base64url'\n"]}
@@ -1,3 +1,4 @@
1
+ import { Base64Alphabet } from './uint8array-base64.js';
1
2
  declare global {
2
3
  interface Uint8ArrayConstructor {
3
4
  /**
@@ -10,7 +11,7 @@ declare global {
10
11
  }) => Uint8Array;
11
12
  }
12
13
  }
13
- export declare const fromBase64Native: ((b64: string) => Uint8Array) | null;
14
- export declare const fromBase64Node: ((b64: string) => Uint8Array) | null;
15
- export declare function fromBase64Ponyfill(b64: string): Uint8Array;
14
+ export declare const fromBase64Native: ((b64: string, alphabet?: Base64Alphabet) => Uint8Array) | null;
15
+ export declare const fromBase64Node: ((b64: string, alphabet?: Base64Alphabet) => Uint8Array) | null;
16
+ export declare function fromBase64Ponyfill(b64: string, alphabet?: Base64Alphabet): Uint8Array;
16
17
  //# sourceMappingURL=uint8array-from-base64.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uint8array-from-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-from-base64.ts"],"names":[],"mappings":"AAKA,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,SAEQ,MAAM,KAAG,UAAU,QAG9C,CAAA;AAEV,eAAO,MAAM,cAAc,SACM,MAAM,KAAG,UAAU,QAQ5C,CAAA;AAER,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAI1D"}
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,QAMT,CAAA;AAEV,eAAO,MAAM,cAAc,SAEhB,MAAM,aACD,cAAc,KACvB,UAAU,QAQT,CAAA;AAER,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,cAAyB,GAClC,UAAU,CAIZ"}
@@ -6,13 +6,16 @@ const from_string_1 = require("uint8arrays/from-string");
6
6
  const nodejs_buffer_js_1 = require("./lib/nodejs-buffer.js");
7
7
  const Buffer = nodejs_buffer_js_1.NodeJSBuffer;
8
8
  exports.fromBase64Native = typeof Uint8Array.fromBase64 === 'function'
9
- ? function fromBase64Native(b64) {
10
- return Uint8Array.fromBase64(b64, { lastChunkHandling: 'loose' });
9
+ ? function fromBase64Native(b64, alphabet = 'base64') {
10
+ return Uint8Array.fromBase64(b64, {
11
+ alphabet,
12
+ lastChunkHandling: 'loose',
13
+ });
11
14
  }
12
15
  : null;
13
16
  exports.fromBase64Node = Buffer
14
- ? function fromBase64Node(b64) {
15
- const bytes = Buffer.from(b64, 'base64');
17
+ ? function fromBase64Node(b64, alphabet = 'base64') {
18
+ const bytes = Buffer.from(b64, alphabet);
16
19
  verifyBase64ForBytes(b64, bytes);
17
20
  // Convert to Uint8Array because even though Buffer is a sub class of
18
21
  // Uint8Array, it serializes differently to Uint8Array (e.g. in JSON) and
@@ -20,8 +23,8 @@ exports.fromBase64Node = Buffer
20
23
  return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
21
24
  }
22
25
  : null;
23
- function fromBase64Ponyfill(b64) {
24
- const bytes = (0, from_string_1.fromString)(b64, 'base64');
26
+ function fromBase64Ponyfill(b64, alphabet = 'base64') {
27
+ const bytes = (0, from_string_1.fromString)(b64, b64.endsWith('=') ? `${alphabet}pad` : alphabet);
25
28
  verifyBase64ForBytes(b64, bytes);
26
29
  return bytes;
27
30
  }
@@ -1 +1 @@
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'\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(b64: string): Uint8Array {\n return Uint8Array.fromBase64!(b64, { lastChunkHandling: 'loose' })\n }\n : null\n\nexport const fromBase64Node = Buffer\n ? function fromBase64Node(b64: string): Uint8Array {\n const bytes = Buffer.from(b64, 'base64')\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 : null\n\nexport function fromBase64Ponyfill(b64: string): Uint8Array {\n const bytes = fromString(b64, 'base64')\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
+ {"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 : 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 : 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,3 +1,4 @@
1
+ import { Base64Alphabet } from './uint8array-base64.js';
1
2
  declare global {
2
3
  interface Uint8Array {
3
4
  /**
@@ -10,7 +11,7 @@ declare global {
10
11
  }) => string;
11
12
  }
12
13
  }
13
- export declare const toBase64Native: ((bytes: Uint8Array) => string) | null;
14
- export declare const toBase64Node: ((bytes: Uint8Array) => string) | null;
15
- export declare function toBase64Ponyfill(bytes: Uint8Array): string;
14
+ export declare const toBase64Native: ((bytes: Uint8Array, alphabet?: Base64Alphabet) => string) | null;
15
+ export declare const toBase64Node: ((bytes: Uint8Array, alphabet?: Base64Alphabet) => string) | null;
16
+ export declare function toBase64Ponyfill(bytes: Uint8Array, alphabet?: Base64Alphabet): string;
16
17
  //# sourceMappingURL=uint8array-to-base64.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uint8array-to-base64.d.ts","sourceRoot":"","sources":["../src/uint8array-to-base64.ts"],"names":[],"mappings":"AAKA,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,WAEU,UAAU,KAAG,MAAM,QAG9C,CAAA;AAEV,eAAO,MAAM,YAAY,WACQ,UAAU,KAAG,MAAM,QAc5C,CAAA;AAER,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE1D"}
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,QAGL,CAAA;AAEV,eAAO,MAAM,YAAY,WAEZ,UAAU,aACP,cAAc,KACvB,MAAM,QAcL,CAAA;AAER,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,QAAQ,GAAE,cAAyB,GAClC,MAAM,CAER"}
@@ -6,13 +6,14 @@ const to_string_1 = require("uint8arrays/to-string");
6
6
  const nodejs_buffer_js_1 = require("./lib/nodejs-buffer.js");
7
7
  const Buffer = nodejs_buffer_js_1.NodeJSBuffer;
8
8
  exports.toBase64Native = typeof Uint8Array.prototype.toBase64 === 'function'
9
- ? function toBase64Native(bytes) {
10
- return bytes.toBase64({ omitPadding: true });
9
+ ? function toBase64Native(bytes, alphabet = 'base64') {
10
+ return bytes.toBase64({ alphabet, omitPadding: true });
11
11
  }
12
12
  : null;
13
13
  exports.toBase64Node = Buffer
14
- ? function toBase64Node(bytes) {
15
- const b64 = (bytes instanceof Buffer ? bytes : Buffer.from(bytes)).toString('base64');
14
+ ? function toBase64Node(bytes, alphabet = 'base64') {
15
+ const buffer = bytes instanceof Buffer ? bytes : Buffer.from(bytes);
16
+ const b64 = buffer.toString(alphabet);
16
17
  // @NOTE We strip padding for strict compatibility with
17
18
  // uint8arrays.toString behavior. Tests failing because of the presence of
18
19
  // padding are not really synonymous with an actual error and we might
@@ -24,7 +25,7 @@ exports.toBase64Node = Buffer
24
25
  : b64;
25
26
  }
26
27
  : null;
27
- function toBase64Ponyfill(bytes) {
28
- return (0, to_string_1.toString)(bytes, 'base64');
28
+ function toBase64Ponyfill(bytes, alphabet = 'base64') {
29
+ return (0, to_string_1.toString)(bytes, alphabet);
29
30
  }
30
31
  //# sourceMappingURL=uint8array-to-base64.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"uint8array-to-base64.js","sourceRoot":"","sources":["../src/uint8array-to-base64.ts"],"names":[],"mappings":";;;AA0CA,4CAEC;AA5CD,qDAAgD;AAChD,6DAAqD;AAErD,MAAM,MAAM,GAAG,+BAAY,CAAA;AAed,QAAA,cAAc,GACzB,OAAO,UAAU,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU;IACjD,CAAC,CAAC,SAAS,cAAc,CAAC,KAAiB;QACvC,OAAO,KAAK,CAAC,QAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/C,CAAC;IACH,CAAC,CAAC,IAAI,CAAA;AAEG,QAAA,YAAY,GAAG,MAAM;IAChC,CAAC,CAAC,SAAS,YAAY,CAAC,KAAiB;QACrC,MAAM,GAAG,GAAG,CACV,KAAK,YAAY,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CACrD,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACpB,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,IAAI,CAAA;AAER,SAAgB,gBAAgB,CAAC,KAAiB;IAChD,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'\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(bytes: Uint8Array): string {\n return bytes.toBase64!({ omitPadding: true })\n }\n : null\n\nexport const toBase64Node = Buffer\n ? function toBase64Node(bytes: Uint8Array): string {\n const b64 = (\n bytes instanceof Buffer ? bytes : Buffer.from(bytes)\n ).toString('base64')\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 : null\n\nexport function toBase64Ponyfill(bytes: Uint8Array): string {\n return toString(bytes, 'base64')\n}\n"]}
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;AAEG,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,IAAI,CAAA;AAER,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 : 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 : null\n\nexport function toBase64Ponyfill(\n bytes: Uint8Array,\n alphabet: Base64Alphabet = 'base64',\n): string {\n return toString(bytes, alphabet)\n}\n"]}
@@ -1,16 +1,19 @@
1
+ import { Base64Alphabet } from './uint8array-base64.js';
2
+ export type { Base64Alphabet };
1
3
  /**
2
4
  * Encodes a Uint8Array into a base64 string.
3
5
  *
4
6
  * @returns The base64 encoded string
5
7
  */
6
- export declare const toBase64: (bytes: Uint8Array) => string;
8
+ export declare const toBase64: (bytes: Uint8Array, alphabet?: Base64Alphabet) => string;
7
9
  /**
8
- * Decodes a base64 string into a Uint8Array.
10
+ * Decodes a base64 string into a Uint8Array. This function supports both padded
11
+ * and unpadded base64 strings.
9
12
  *
10
13
  * @returns The decoded {@link Uint8Array}
11
14
  * @throws If the input is not a valid base64 string
12
15
  */
13
- export declare const fromBase64: (b64: string) => Uint8Array;
16
+ export declare const fromBase64: (b64: string, alphabet?: Base64Alphabet) => Uint8Array;
14
17
  /**
15
18
  * Coerces various binary data representations into a Uint8Array.
16
19
  *
@@ -1 +1 @@
1
- {"version":3,"file":"uint8array.d.ts","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":"AAgBA;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MACM,CAAA;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,UACgB,CAAA;AAS1D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAkBnE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAY/D"}
1
+ {"version":3,"file":"uint8array.d.ts","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAYvD,YAAY,EAAE,cAAc,EAAE,CAAA;AAO9B;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,CACrB,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,cAAc,KACtB,MAA2D,CAAA;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,CACvB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,KACtB,UAAqE,CAAA;AAS1E;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAkBnE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAY/D"}
@@ -16,7 +16,8 @@ const uint8array_to_base64_js_1 = require("./uint8array-to-base64.js");
16
16
  */
17
17
  exports.toBase64 = uint8array_to_base64_js_1.toBase64Native ?? uint8array_to_base64_js_1.toBase64Node ?? uint8array_to_base64_js_1.toBase64Ponyfill;
18
18
  /**
19
- * Decodes a base64 string into a Uint8Array.
19
+ * Decodes a base64 string into a Uint8Array. This function supports both padded
20
+ * and unpadded base64 strings.
20
21
  *
21
22
  * @returns The decoded {@link Uint8Array}
22
23
  * @throws If the input is not a valid base64 string
@@ -1 +1 @@
1
- {"version":3,"file":"uint8array.js","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":";;;AA6CA,oCAkBC;AAED,8BAYC;AA7ED,2EAIoC;AACpC,uEAIkC;AAElC,4EAA4E;AAC5E,2EAA2E;AAC3E,2EAA2E;AAC3E,0CAA0C;AAE1C;;;;GAIG;AACU,QAAA,QAAQ,GACnB,wCAAc,IAAI,sCAAY,IAAI,0CAAgB,CAAA;AAEpD;;;;;GAKG;AACU,QAAA,UAAU,GACrB,4CAAgB,IAAI,0CAAc,IAAI,8CAAkB,CAAA;AAE1D,IAAI,gBAAQ,KAAK,0CAAgB,IAAI,kBAAU,KAAK,8CAAkB,EAAE,CAAC;IACvE,aAAa;IACb,OAAO,CAAC,IAAI,CACV,wJAAwJ,CACzJ,CAAA;AACH,CAAC;AAED;;;;GAIG;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,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","sourcesContent":["import {\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\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 * @returns The base64 encoded string\n */\nexport const toBase64: (bytes: Uint8Array) => string =\n toBase64Native ?? toBase64Node ?? toBase64Ponyfill\n\n/**\n * Decodes a base64 string into a Uint8Array.\n *\n * @returns The decoded {@link Uint8Array}\n * @throws If the input is not a valid base64 string\n */\nexport const fromBase64: (b64: string) => Uint8Array =\n fromBase64Native ?? fromBase64Node ?? fromBase64Ponyfill\n\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 * Coerces various binary data representations into a Uint8Array.\n *\n * @return `undefined` if the input could not be coerced into a {@link Uint8Array}.\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\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"]}
1
+ {"version":3,"file":"uint8array.js","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":";;;AAqDA,oCAkBC;AAED,8BAYC;AApFD,2EAIoC;AACpC,uEAIkC;AAIlC,4EAA4E;AAC5E,2EAA2E;AAC3E,2EAA2E;AAC3E,0CAA0C;AAE1C;;;;GAIG;AACU,QAAA,QAAQ,GAGP,wCAAc,IAAI,sCAAY,IAAI,0CAAgB,CAAA;AAEhE;;;;;;GAMG;AACU,QAAA,UAAU,GAGL,4CAAgB,IAAI,0CAAc,IAAI,8CAAkB,CAAA;AAE1E,IAAI,gBAAQ,KAAK,0CAAgB,IAAI,kBAAU,KAAK,8CAAkB,EAAE,CAAC;IACvE,aAAa;IACb,OAAO,CAAC,IAAI,CACV,wJAAwJ,CACzJ,CAAA;AACH,CAAC;AAED;;;;GAIG;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,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","sourcesContent":["import { Base64Alphabet } from './uint8array-base64.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 * @returns The base64 encoded string\n */\nexport const toBase64: (\n bytes: Uint8Array,\n alphabet?: Base64Alphabet,\n) => string = toBase64Native ?? toBase64Node ?? toBase64Ponyfill\n\n/**\n * Decodes a base64 string into a Uint8Array. This function supports both padded\n * and unpadded base64 strings.\n *\n * @returns The decoded {@link Uint8Array}\n * @throws If the input is not a valid base64 string\n */\nexport const fromBase64: (\n b64: string,\n alphabet?: Base64Alphabet,\n) => Uint8Array = fromBase64Native ?? fromBase64Node ?? fromBase64Ponyfill\n\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 * Coerces various binary data representations into a Uint8Array.\n *\n * @return `undefined` if the input could not be coerced into a {@link Uint8Array}.\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\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex-data",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "license": "MIT",
5
5
  "description": "Core utilities for AT Lexicons",
6
6
  "keywords": [
@@ -19,7 +19,8 @@
19
19
  "./tsconfig.build.json",
20
20
  "./tsconfig.tests.json",
21
21
  "./tsconfig.json",
22
- "./dist"
22
+ "./dist",
23
+ "./CHANGELOG.md"
23
24
  ],
24
25
  "sideEffects": false,
25
26
  "type": "commonjs",
@@ -38,7 +39,7 @@
38
39
  "tslib": "^2.8.1",
39
40
  "uint8arrays": "3.0.0",
40
41
  "unicode-segmenter": "^0.14.0",
41
- "@atproto/syntax": "0.4.1"
42
+ "@atproto/syntax": "0.4.2"
42
43
  },
43
44
  "devDependencies": {
44
45
  "core-js": "^3",
package/src/blob.test.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { isBlobRef, isLegacyBlobRef } from './blob.js'
2
- import { CID } from './cid.js'
2
+ import { parseCid } from './cid.js'
3
3
 
4
4
  // await cidForRawBytes(Buffer.from('Hello, World!'))
5
- const blobCid = CID.parse(
5
+ const blobCid = parseCid(
6
6
  'bafkreig77vqcdozl2wyk6z3cscaj5q5fggi53aoh64fewkdiri3cdauyn4',
7
7
  )
8
8
  // await cidForLex(Buffer.from('Hello, World!'))
9
- const lexCid = CID.parse(
9
+ const lexCid = parseCid(
10
10
  'bafyreic52vzks7wdklat4evp3vimohl55i2unzqpshz2ytka5omzr7exdy',
11
11
  )
12
12
 
package/src/blob.ts CHANGED
@@ -1,10 +1,16 @@
1
- import { CID, RAW_BIN_MULTICODEC, SHA2_256_MULTIHASH_CODE } from './cid.js'
1
+ import {
2
+ Cid,
3
+ RAW_BIN_MULTICODEC,
4
+ SHA2_256_MULTIHASH_CODE,
5
+ asCid,
6
+ parseCid,
7
+ } from './cid.js'
2
8
  import { isPlainObject } from './object.js'
3
9
 
4
10
  export type BlobRef = {
5
11
  $type: 'blob'
6
12
  mimeType: string
7
- ref: CID
13
+ ref: Cid
8
14
  size: number
9
15
  }
10
16
 
@@ -21,7 +27,8 @@ export function isBlobRef(
21
27
  }
22
28
 
23
29
  const { mimeType, size, ref } = input
24
- if (typeof mimeType !== 'string') {
30
+ // @NOTE Very basic mime validation
31
+ if (typeof mimeType !== 'string' || !mimeType.includes('/')) {
25
32
  return false
26
33
  }
27
34
 
@@ -44,7 +51,7 @@ export function isBlobRef(
44
51
  }
45
52
  }
46
53
 
47
- const cid = CID.asCID(ref)
54
+ const cid = asCid(ref)
48
55
  if (!cid) {
49
56
  return false
50
57
  }
@@ -90,7 +97,7 @@ export function isLegacyBlobRef(input: unknown): input is LegacyBlobRef {
90
97
  }
91
98
 
92
99
  try {
93
- CID.parse(cid)
100
+ parseCid(cid)
94
101
  } catch {
95
102
  return false
96
103
  }
package/src/cid.ts CHANGED
@@ -5,13 +5,91 @@ export const RAW_BIN_MULTICODEC = 0x55
5
5
 
6
6
  export const SHA2_256_MULTIHASH_CODE = 0x12
7
7
 
8
+ export type MultihashDigest<Code extends number = number> = {
9
+ code: Code
10
+ digest: Uint8Array
11
+ size: number
12
+ bytes: Uint8Array
13
+ }
14
+
15
+ declare module 'multiformats/cid' {
16
+ /**
17
+ * @deprecated use the {@link Cid} interface from `@atproto/lex-data`, and
18
+ * related helpers ({@link asCid}, {@link parseCid}, {@link decodeCid},
19
+ * {@link createCid}, {@link isCid}), instead.
20
+ *
21
+ * This is marked as deprecated because we want to discourage direct usage of
22
+ * `multiformats/cid` in dependent packages, and instead have them rely on the
23
+ * {@link Cid} interface from `@atproto/lex-data`. The {@link CID} class from
24
+ * `multiformats` version <10 has compatibility issues with certain TypeScript
25
+ * module resolution strategies, which can lead to type errors in dependent
26
+ * packages.
27
+ *
28
+ * We are stuck with version 9 because `@atproto` packages did not drop
29
+ * CommonJS support yet, and multiformats version 10 only supports ES modules.
30
+ *
31
+ * In order to avoid compatibility issues, while preparing for future breaking
32
+ * changes (CID in multiformats v10+ has a slightly different interface), as
33
+ * we update or swap out `multiformats`, we provide our own stable `Cid`
34
+ * interface.
35
+ */
36
+ interface CID {}
37
+ }
38
+
39
+ // CID form "multiformats" is not very portable because:
40
+ //
41
+ // - In dependent packages that use "moduleResolution" set to "node16",
42
+ // "nodenext" or "bundler", TypeScript fails to properly resolve the
43
+ // multiformats package when importing CID from @atproto/lex-data. This causes
44
+ // type errors in those packages. This is caused by the fact that the
45
+ // multiformats version <10 (which is the last version that supports CommonJS)
46
+ // uses "exports" field in package.json, which do not contain "types"
47
+ // entrypoints.
48
+ // https://www.npmjs.com/package/multiformats/v/9.9.0?activeTab=code
49
+ // - By defining our own Cid interface and related functions, we can have more
50
+ // control over the API we expose to dependent packages.
51
+ // - It allow us to have a stable interface in case we need to swap out, or
52
+ // eventually update multiformats (should we choose to drop CommonJS support)
53
+ // in the future.
54
+
55
+ // @NOTE Even though it is not portable, we still re-export CID here so that
56
+ // dependent packages where it can be used, have access to it.
8
57
  export { CID }
9
58
 
59
+ /**
60
+ * Interface for working with decoded CID string, compatible with
61
+ * {@link CID} implementation.
62
+ */
63
+ export interface Cid {
64
+ version: 0 | 1
65
+ code: number
66
+ multihash: MultihashDigest
67
+ bytes: Uint8Array
68
+ equals(other: unknown): boolean
69
+ toString(): string
70
+ }
71
+
72
+ export function asCid(value: unknown): Cid | null {
73
+ return CID.asCID(value)
74
+ }
75
+
76
+ export function parseCid(input: string): Cid {
77
+ return CID.parse(input)
78
+ }
79
+
80
+ export function decodeCid(bytes: Uint8Array): Cid {
81
+ return CID.decode(bytes)
82
+ }
83
+
84
+ export function createCid(code: number, digest: MultihashDigest): Cid {
85
+ return CID.createV1(code, digest)
86
+ }
87
+
10
88
  export function isCid(
11
89
  value: unknown,
12
90
  options?: { strict?: boolean },
13
- ): value is CID {
14
- const cid = CID.asCID(value)
91
+ ): value is Cid {
92
+ const cid = asCid(value)
15
93
  if (!cid) {
16
94
  return false
17
95
  }
@@ -35,9 +113,9 @@ export function validateCidString(input: string): boolean {
35
113
  return parseCidString(input)?.toString() === input
36
114
  }
37
115
 
38
- export function parseCidString(input: string): CID | undefined {
116
+ export function parseCidString(input: string): Cid | undefined {
39
117
  try {
40
- return CID.parse(input)
118
+ return parseCid(input)
41
119
  } catch {
42
120
  return undefined
43
121
  }
@@ -1,4 +1,4 @@
1
- import { CID } from './cid.js'
1
+ import { parseCid } from './cid.js'
2
2
  import { lexEquals } from './lex-equals.js'
3
3
  import { LexValue } from './lex.js'
4
4
 
@@ -48,11 +48,11 @@ describe('lexEquals', () => {
48
48
  })
49
49
 
50
50
  it('compares CIDs', () => {
51
- const cid1 = CID.parse(
51
+ const cid1 = parseCid(
52
52
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
53
53
  )
54
- const cid2 = CID.parse(cid1.toString())
55
- const cid3 = CID.parse(cid1.toString())
54
+ const cid2 = parseCid(cid1.toString())
55
+ const cid3 = parseCid(cid1.toString())
56
56
 
57
57
  expectLexEqual(cid1, cid2, true)
58
58
  expectLexEqual(cid1, cid3, true)
@@ -78,19 +78,19 @@ describe('lexEquals', () => {
78
78
  it('compares nested structures', () => {
79
79
  const lex1 = {
80
80
  foo: [1, 2, { bar: new Uint8Array([3, 4, 5]) }],
81
- baz: CID.parse(
81
+ baz: parseCid(
82
82
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
83
83
  ),
84
84
  }
85
85
  const lex2 = {
86
86
  foo: [1, 2, { bar: new Uint8Array([3, 4, 5]) }],
87
- baz: CID.parse(
87
+ baz: parseCid(
88
88
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
89
89
  ),
90
90
  }
91
91
  const lex3 = {
92
92
  foo: [1, 2, { bar: new Uint8Array([3, 4, 5 + 1]) }],
93
- baz: CID.parse(
93
+ baz: parseCid(
94
94
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
95
95
  ),
96
96
  }
@@ -127,7 +127,7 @@ describe('lexEquals', () => {
127
127
  const u8 = new Uint8Array([1, 2, 3])
128
128
  expectLexEqual(u8, u8, true)
129
129
 
130
- const cid = CID.parse(
130
+ const cid = parseCid(
131
131
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
132
132
  )
133
133
  expectLexEqual(cid, cid, true)
package/src/lex-equals.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CID, isCid } from './cid.js'
1
+ import { asCid, isCid } from './cid.js'
2
2
  import { LexValue } from './lex.js'
3
3
  import { isPlainObject } from './object.js'
4
4
  import { ui8Equals } from './uint8array.js'
@@ -44,7 +44,7 @@ export function lexEquals(a: LexValue, b: LexValue): boolean {
44
44
  if (isCid(a)) {
45
45
  // @NOTE CID.equals returns its argument when it is falsy (e.g. null or
46
46
  // undefined) so we need to explicitly check that the output is "true".
47
- return CID.asCID(a)!.equals(CID.asCID(b)) === true
47
+ return asCid(a)!.equals(asCid(b)) === true
48
48
  } else if (isCid(b)) {
49
49
  return false
50
50
  }
package/src/lex.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { CID, isCid } from './cid.js'
1
+ import { Cid, isCid } from './cid.js'
2
2
  import { isPlainObject } from './object.js'
3
3
 
4
4
  // @NOTE BlobRef is just a special case of LexMap.
5
5
 
6
- export type LexScalar = number | string | boolean | null | CID | Uint8Array
6
+ export type LexScalar = number | string | boolean | null | Cid | Uint8Array
7
7
  export type LexValue = LexScalar | LexValue[] | { [_ in string]?: LexValue }
8
8
  export type LexMap = { [_ in string]?: LexValue }
9
9
  export type LexArray = LexValue[]
@@ -1,4 +1,4 @@
1
- import { CID } from './cid.js'
1
+ import { parseCid } from './cid.js'
2
2
  import { isObject, isPlainObject } from './object.js'
3
3
  describe('isObject', () => {
4
4
  it('returns true for plain objects', () => {
@@ -7,7 +7,7 @@ describe('isObject', () => {
7
7
  })
8
8
 
9
9
  it('returns true for CIDs', () => {
10
- const cid = CID.parse(
10
+ const cid = parseCid(
11
11
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
12
12
  )
13
13
  expect(isObject(cid)).toBe(true)
@@ -54,7 +54,7 @@ describe('isPlainObject', () => {
54
54
  })
55
55
 
56
56
  it('returns false for CIDs', () => {
57
- const cid = CID.parse(
57
+ const cid = parseCid(
58
58
  'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
59
59
  )
60
60
  expect(isPlainObject(cid)).toBe(false)
@@ -0,0 +1,2 @@
1
+ /** @default 'base64' */
2
+ export type Base64Alphabet = 'base64' | 'base64url'
@@ -40,34 +40,48 @@ for (const fromBase64 of [
40
40
  expect(ui8Equals(decoded, bytes)).toBe(true)
41
41
  })
42
42
 
43
- for (const string of [
44
- '',
45
- '\0\0',
46
- '\0\0\0',
47
- '\0\0\0\0',
48
- '__',
49
- 'é',
50
- 'àç',
51
- '\0éàç',
52
- '```',
53
- 'aaa',
54
- 'Hello, World!',
55
- '😀😃😄😁😆😅😂🤣😊😇',
56
- '👩‍💻👨‍💻👩‍🔬👨‍🔬👩‍🚀👨‍🚀',
57
- '🌍🌎🌏🌐🪐🌟✨⚡🔥💧',
58
- ] as const) {
59
- const buffer = Buffer.from(string, 'utf8')
43
+ for (const buffer of [
44
+ Buffer.from(''),
45
+ Buffer.from('\0\0'),
46
+ Buffer.from('\0\0\0'),
47
+ Buffer.from('\0\0\0\0'),
48
+ Buffer.from('__'),
49
+ Buffer.from('é'),
50
+ Buffer.from('àç'),
51
+ Buffer.from('\0éàç'),
52
+ Buffer.from('```'),
53
+ Buffer.from('aaa'),
54
+ Buffer.from('Hello, World!'),
55
+ Buffer.from('😀😃😄😁😆😅😂🤣😊😇'),
56
+ Buffer.from('👩‍💻👨‍💻👩‍🔬👨‍🔬👩‍🚀👨‍🚀'),
57
+ Buffer.from('🌍🌎🌏🌐🪐🌟✨⚡🔥💧'),
58
+ Buffer.from(new Uint8Array([0xfb, 0xff, 0xbf])),
59
+ Buffer.from(new Uint8Array([0xfb, 0xff, 0xbf])),
60
+ Buffer.from(new Uint8Array([0x4d])),
61
+ Buffer.from(new Uint8Array([0x4d, 0x61])),
62
+ Buffer.from(new Uint8Array([0x4d, 0x61, 0x6e])),
63
+ Buffer.from(new Uint8Array([0x4d])),
64
+ Buffer.from(new Uint8Array([0x4d, 0x61])),
65
+ Buffer.from(new Uint8Array([0x00, 0x4d, 0x61, 0x6e, 0x00])),
66
+ ]) {
60
67
  const base64 = buffer.toString('base64')
61
68
  const base64Unpadded = base64.replace(/=+$/, '')
69
+ const base64url = buffer.toString('base64url') // No padding in base64url
62
70
 
63
- it(`decodes ${JSON.stringify(string)}`, () => {
71
+ it(`decodes ${JSON.stringify(base64)}`, () => {
64
72
  const decoded = fromBase64(base64)
65
73
  expect(decoded).toBeInstanceOf(Uint8Array)
66
74
  expect(ui8Equals(decoded, buffer)).toBe(true)
67
75
  })
68
76
 
77
+ it(`decodes ${JSON.stringify(base64url)} (base64url)`, () => {
78
+ const decoded = fromBase64(base64url, 'base64url')
79
+ expect(decoded).toBeInstanceOf(Uint8Array)
80
+ expect(ui8Equals(decoded, buffer)).toBe(true)
81
+ })
82
+
69
83
  if (base64 !== base64Unpadded) {
70
- it(`decodes ${JSON.stringify(string)} (unpadded)`, () => {
84
+ it(`decodes ${JSON.stringify(base64Unpadded)} (unpadded)`, () => {
71
85
  const decoded = fromBase64(base64Unpadded)
72
86
  expect(decoded).toBeInstanceOf(Uint8Array)
73
87
  expect(ui8Equals(decoded, buffer)).toBe(true)
@@ -1,5 +1,6 @@
1
1
  import { fromString } from 'uint8arrays/from-string'
2
2
  import { NodeJSBuffer } from './lib/nodejs-buffer.js'
3
+ import { Base64Alphabet } from './uint8array-base64.js'
3
4
 
4
5
  const Buffer = NodeJSBuffer
5
6
 
@@ -21,14 +22,23 @@ declare global {
21
22
 
22
23
  export const fromBase64Native =
23
24
  typeof Uint8Array.fromBase64 === 'function'
24
- ? function fromBase64Native(b64: string): Uint8Array {
25
- return Uint8Array.fromBase64!(b64, { lastChunkHandling: 'loose' })
25
+ ? function fromBase64Native(
26
+ b64: string,
27
+ alphabet: Base64Alphabet = 'base64',
28
+ ): Uint8Array {
29
+ return Uint8Array.fromBase64!(b64, {
30
+ alphabet,
31
+ lastChunkHandling: 'loose',
32
+ })
26
33
  }
27
34
  : null
28
35
 
29
36
  export const fromBase64Node = Buffer
30
- ? function fromBase64Node(b64: string): Uint8Array {
31
- const bytes = Buffer.from(b64, 'base64')
37
+ ? function fromBase64Node(
38
+ b64: string,
39
+ alphabet: Base64Alphabet = 'base64',
40
+ ): Uint8Array {
41
+ const bytes = Buffer.from(b64, alphabet)
32
42
  verifyBase64ForBytes(b64, bytes)
33
43
  // Convert to Uint8Array because even though Buffer is a sub class of
34
44
  // Uint8Array, it serializes differently to Uint8Array (e.g. in JSON) and
@@ -37,8 +47,11 @@ export const fromBase64Node = Buffer
37
47
  }
38
48
  : null
39
49
 
40
- export function fromBase64Ponyfill(b64: string): Uint8Array {
41
- const bytes = fromString(b64, 'base64')
50
+ export function fromBase64Ponyfill(
51
+ b64: string,
52
+ alphabet: Base64Alphabet = 'base64',
53
+ ): Uint8Array {
54
+ const bytes = fromString(b64, b64.endsWith('=') ? `${alphabet}pad` : alphabet)
42
55
  verifyBase64ForBytes(b64, bytes)
43
56
  return bytes
44
57
  }
@@ -0,0 +1,170 @@
1
+ import 'core-js/modules/es.uint8-array.from-base64.js'
2
+ import 'core-js/modules/es.uint8-array.to-base64.js'
3
+ import assert from 'node:assert'
4
+ import {
5
+ toBase64Native,
6
+ toBase64Node,
7
+ toBase64Ponyfill,
8
+ } from './uint8array-to-base64.js'
9
+
10
+ for (const toBase64 of [
11
+ toBase64Native,
12
+ toBase64Node,
13
+ toBase64Ponyfill,
14
+ ] as const) {
15
+ // Tests should run in NodeJS where implementations are either available or
16
+ // polyfilled (see core-js imports above).
17
+ assert(toBase64 !== null, 'toBase64 implementation should not be null')
18
+
19
+ describe(toBase64.name, () => {
20
+ describe('basic encoding', () => {
21
+ it('encodes empty Uint8Array', () => {
22
+ const encoded = toBase64(new Uint8Array(0))
23
+ expect(typeof encoded).toBe('string')
24
+ expect(encoded).toBe('')
25
+ })
26
+
27
+ it('encodes 10MB', () => {
28
+ const bytes = Buffer.allocUnsafe(10_000_000).fill('🐩')
29
+ const encoded = toBase64(bytes)
30
+ expect(typeof encoded).toBe('string')
31
+ // Verify by decoding back
32
+ const decoded = Buffer.from(encoded, 'base64')
33
+ expect(decoded.equals(bytes)).toBe(true)
34
+ })
35
+ })
36
+
37
+ describe('base64 alphabet (default)', () => {
38
+ for (const string of [
39
+ '',
40
+ '\0\0',
41
+ '\0\0\0',
42
+ '\0\0\0\0',
43
+ '__',
44
+ 'é',
45
+ 'àç',
46
+ '\0éàç',
47
+ '```\x1b',
48
+ 'aaa',
49
+ 'Hello, World!',
50
+ '😀😃😄😁😆😅😂🤣😊😇',
51
+ '👩‍💻👨‍💻👩‍🔬👨‍🔬👩‍🚀👨‍🚀',
52
+ '🌍🌎🌏🌐🪐🌟✨⚡🔥💧',
53
+ ] as const) {
54
+ const buffer = Buffer.from(string, 'utf8')
55
+ const expected = buffer.toString('base64').replace(/=+$/, '')
56
+
57
+ it(`encodes ${JSON.stringify(string)} as ${JSON.stringify(expected)}`, () => {
58
+ const encoded = toBase64(buffer)
59
+ expect(encoded).toBe(expected)
60
+ })
61
+ }
62
+ })
63
+
64
+ describe('base64url alphabet', () => {
65
+ for (const string of [
66
+ '',
67
+ '\0\0',
68
+ '\0\0\0',
69
+ '\0\0\0\0',
70
+ '__',
71
+ 'é',
72
+ 'àç',
73
+ '\0éàç',
74
+ '```\x1b',
75
+ 'aaa',
76
+ 'Hello, World!',
77
+ '😀😃😄😁😆😅😂🤣😊😇',
78
+ '👩‍💻👨‍💻👩‍🔬👨‍🔬👩‍🚀👨‍🚀',
79
+ '🌍🌎🌏🌐🪐🌟✨⚡🔥💧',
80
+ ] as const) {
81
+ const buffer = Buffer.from(string, 'utf8')
82
+ const expected = buffer.toString('base64url')
83
+
84
+ it(`encodes ${JSON.stringify(string)} as ${JSON.stringify(expected)}`, () => {
85
+ const encoded = toBase64(buffer, 'base64url')
86
+ expect(encoded).toBe(expected)
87
+ })
88
+ }
89
+ })
90
+
91
+ describe('base64 vs base64url character differences', () => {
92
+ // Test data that produces + and / in standard base64
93
+ // These should become - and _ in base64url
94
+ it('uses + and / for base64 alphabet', () => {
95
+ // 0xfb, 0xff, 0xbf produces "+/+/" in base64
96
+ const bytes = new Uint8Array([0xfb, 0xff, 0xbf])
97
+ const encoded = toBase64(bytes)
98
+ expect(encoded).toContain('+')
99
+ expect(encoded).toContain('/')
100
+ expect(encoded).not.toContain('-')
101
+ expect(encoded).not.toContain('_')
102
+ })
103
+
104
+ it('uses - and _ for base64url alphabet', () => {
105
+ // Same bytes should use - and _ in base64url
106
+ const bytes = new Uint8Array([0xfb, 0xff, 0xbf])
107
+ const encoded = toBase64(bytes, 'base64url')
108
+ expect(encoded).toContain('-')
109
+ expect(encoded).toContain('_')
110
+ expect(encoded).not.toContain('+')
111
+ expect(encoded).not.toContain('/')
112
+ })
113
+ })
114
+
115
+ describe('padding behavior', () => {
116
+ it('omits padding by default for 1-byte input', () => {
117
+ // 1 byte -> 2 base64 chars + 2 padding
118
+ const bytes = new Uint8Array([0x4d]) // 'M' -> 'TQ=='
119
+ const encoded = toBase64(bytes)
120
+ expect(encoded).toBe('TQ')
121
+ expect(encoded).not.toContain('=')
122
+ })
123
+
124
+ it('omits padding by default for 2-byte input', () => {
125
+ // 2 bytes -> 3 base64 chars + 1 padding
126
+ const bytes = new Uint8Array([0x4d, 0x61]) // 'Ma' -> 'TWE='
127
+ const encoded = toBase64(bytes)
128
+ expect(encoded).toBe('TWE')
129
+ expect(encoded).not.toContain('=')
130
+ })
131
+
132
+ it('no padding needed for 3-byte input', () => {
133
+ // 3 bytes -> 4 base64 chars, no padding needed
134
+ const bytes = new Uint8Array([0x4d, 0x61, 0x6e]) // 'Man' -> 'TWFu'
135
+ const encoded = toBase64(bytes)
136
+ expect(encoded).toBe('TWFu')
137
+ })
138
+
139
+ it('includes double padding when omitPadding: false for 1-byte input', () => {
140
+ const bytes = new Uint8Array([0x4d]) // 'M' -> 'TQ=='
141
+ const encoded = toBase64(bytes)
142
+ expect(encoded).toBe('TQ')
143
+ })
144
+
145
+ it('includes single padding when omitPadding: false for 2-byte input', () => {
146
+ const bytes = new Uint8Array([0x4d, 0x61]) // 'Ma' -> 'TWE='
147
+ const encoded = toBase64(bytes)
148
+ expect(encoded).toBe('TWE')
149
+ })
150
+ })
151
+
152
+ describe('Uint8Array subarray handling', () => {
153
+ it('correctly encodes a subarray', () => {
154
+ const fullArray = new Uint8Array([0x00, 0x4d, 0x61, 0x6e, 0x00])
155
+ const subarray = fullArray.subarray(1, 4) // 'Man'
156
+ const encoded = toBase64(subarray)
157
+ expect(encoded).toBe('TWFu')
158
+ })
159
+
160
+ it('correctly encodes a subarray with offset', () => {
161
+ const buffer = new ArrayBuffer(10)
162
+ const fullView = new Uint8Array(buffer)
163
+ fullView.set([0x00, 0x00, 0x4d, 0x61, 0x6e, 0x00, 0x00])
164
+ const subarray = new Uint8Array(buffer, 2, 3) // 'Man' at offset 2
165
+ const encoded = toBase64(subarray)
166
+ expect(encoded).toBe('TWFu')
167
+ })
168
+ })
169
+ })
170
+ }
@@ -1,5 +1,6 @@
1
1
  import { toString } from 'uint8arrays/to-string'
2
2
  import { NodeJSBuffer } from './lib/nodejs-buffer.js'
3
+ import { Base64Alphabet } from './uint8array-base64.js'
3
4
 
4
5
  const Buffer = NodeJSBuffer
5
6
 
@@ -18,16 +19,22 @@ declare global {
18
19
 
19
20
  export const toBase64Native =
20
21
  typeof Uint8Array.prototype.toBase64 === 'function'
21
- ? function toBase64Native(bytes: Uint8Array): string {
22
- return bytes.toBase64!({ omitPadding: true })
22
+ ? function toBase64Native(
23
+ bytes: Uint8Array,
24
+ alphabet: Base64Alphabet = 'base64',
25
+ ): string {
26
+ return bytes.toBase64!({ alphabet, omitPadding: true })
23
27
  }
24
28
  : null
25
29
 
26
30
  export const toBase64Node = Buffer
27
- ? function toBase64Node(bytes: Uint8Array): string {
28
- const b64 = (
29
- bytes instanceof Buffer ? bytes : Buffer.from(bytes)
30
- ).toString('base64')
31
+ ? function toBase64Node(
32
+ bytes: Uint8Array,
33
+ alphabet: Base64Alphabet = 'base64',
34
+ ): string {
35
+ const buffer = bytes instanceof Buffer ? bytes : Buffer.from(bytes)
36
+ const b64 = buffer.toString(alphabet)
37
+
31
38
  // @NOTE We strip padding for strict compatibility with
32
39
  // uint8arrays.toString behavior. Tests failing because of the presence of
33
40
  // padding are not really synonymous with an actual error and we might
@@ -40,6 +47,9 @@ export const toBase64Node = Buffer
40
47
  }
41
48
  : null
42
49
 
43
- export function toBase64Ponyfill(bytes: Uint8Array): string {
44
- return toString(bytes, 'base64')
50
+ export function toBase64Ponyfill(
51
+ bytes: Uint8Array,
52
+ alphabet: Base64Alphabet = 'base64',
53
+ ): string {
54
+ return toString(bytes, alphabet)
45
55
  }
package/src/uint8array.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Base64Alphabet } from './uint8array-base64.js'
1
2
  import {
2
3
  fromBase64Native,
3
4
  fromBase64Node,
@@ -9,6 +10,8 @@ import {
9
10
  toBase64Ponyfill,
10
11
  } from './uint8array-to-base64.js'
11
12
 
13
+ export type { Base64Alphabet }
14
+
12
15
  // @TODO drop dependency on uint8arrays package once Uint8Array.fromBase64 /
13
16
  // Uint8Array.prototype.toBase64 is widely supported, and mark fromBase64 /
14
17
  // toBase64 as deprecated. We can also drop NodeJS specific implementations
@@ -19,17 +22,22 @@ import {
19
22
  *
20
23
  * @returns The base64 encoded string
21
24
  */
22
- export const toBase64: (bytes: Uint8Array) => string =
23
- toBase64Native ?? toBase64Node ?? toBase64Ponyfill
25
+ export const toBase64: (
26
+ bytes: Uint8Array,
27
+ alphabet?: Base64Alphabet,
28
+ ) => string = toBase64Native ?? toBase64Node ?? toBase64Ponyfill
24
29
 
25
30
  /**
26
- * Decodes a base64 string into a Uint8Array.
31
+ * Decodes a base64 string into a Uint8Array. This function supports both padded
32
+ * and unpadded base64 strings.
27
33
  *
28
34
  * @returns The decoded {@link Uint8Array}
29
35
  * @throws If the input is not a valid base64 string
30
36
  */
31
- export const fromBase64: (b64: string) => Uint8Array =
32
- fromBase64Native ?? fromBase64Node ?? fromBase64Ponyfill
37
+ export const fromBase64: (
38
+ b64: string,
39
+ alphabet?: Base64Alphabet,
40
+ ) => Uint8Array = fromBase64Native ?? fromBase64Node ?? fromBase64Ponyfill
33
41
 
34
42
  if (toBase64 === toBase64Ponyfill || fromBase64 === fromBase64Ponyfill) {
35
43
  /*#__PURE__*/