@atproto/repo 0.8.12 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE.txt +1 -1
  3. package/dist/block-map.d.ts +15 -16
  4. package/dist/block-map.d.ts.map +1 -1
  5. package/dist/block-map.js +9 -44
  6. package/dist/block-map.js.map +1 -1
  7. package/dist/car.d.ts +8 -8
  8. package/dist/car.d.ts.map +1 -1
  9. package/dist/car.js +107 -37
  10. package/dist/car.js.map +1 -1
  11. package/dist/cid-set.d.ts +8 -7
  12. package/dist/cid-set.d.ts.map +1 -1
  13. package/dist/cid-set.js +11 -4
  14. package/dist/cid-set.js.map +1 -1
  15. package/dist/data-diff.d.ts +10 -10
  16. package/dist/data-diff.d.ts.map +1 -1
  17. package/dist/data-diff.js.map +1 -1
  18. package/dist/error.d.ts +10 -10
  19. package/dist/error.d.ts.map +1 -1
  20. package/dist/error.js.map +1 -1
  21. package/dist/logger.d.ts.map +1 -1
  22. package/dist/logger.js +1 -0
  23. package/dist/logger.js.map +1 -1
  24. package/dist/mst/mst.d.ts +29 -29
  25. package/dist/mst/mst.d.ts.map +1 -1
  26. package/dist/mst/mst.js +12 -13
  27. package/dist/mst/mst.js.map +1 -1
  28. package/dist/mst/util.d.ts +2 -2
  29. package/dist/mst/util.d.ts.map +1 -1
  30. package/dist/mst/util.js +19 -40
  31. package/dist/mst/util.js.map +1 -1
  32. package/dist/parse.d.ts +6 -7
  33. package/dist/parse.d.ts.map +1 -1
  34. package/dist/parse.js +2 -3
  35. package/dist/parse.js.map +1 -1
  36. package/dist/readable-repo.d.ts +6 -7
  37. package/dist/readable-repo.d.ts.map +1 -1
  38. package/dist/readable-repo.js +0 -1
  39. package/dist/readable-repo.js.map +1 -1
  40. package/dist/repo.d.ts +4 -4
  41. package/dist/repo.d.ts.map +1 -1
  42. package/dist/repo.js +11 -10
  43. package/dist/repo.js.map +1 -1
  44. package/dist/storage/memory-blockstore.d.ts +9 -9
  45. package/dist/storage/memory-blockstore.d.ts.map +1 -1
  46. package/dist/storage/memory-blockstore.js.map +1 -1
  47. package/dist/storage/readable-blockstore.d.ts +11 -12
  48. package/dist/storage/readable-blockstore.d.ts.map +1 -1
  49. package/dist/storage/readable-blockstore.js +2 -36
  50. package/dist/storage/readable-blockstore.js.map +1 -1
  51. package/dist/storage/sync-storage.d.ts +5 -5
  52. package/dist/storage/sync-storage.d.ts.map +1 -1
  53. package/dist/storage/sync-storage.js.map +1 -1
  54. package/dist/storage/types.d.ts +25 -26
  55. package/dist/storage/types.d.ts.map +1 -1
  56. package/dist/storage/types.js +0 -1
  57. package/dist/storage/types.js.map +1 -1
  58. package/dist/sync/consumer.d.ts +3 -3
  59. package/dist/sync/consumer.d.ts.map +1 -1
  60. package/dist/sync/consumer.js +1 -1
  61. package/dist/sync/consumer.js.map +1 -1
  62. package/dist/sync/provider.d.ts +3 -3
  63. package/dist/sync/provider.d.ts.map +1 -1
  64. package/dist/sync/provider.js.map +1 -1
  65. package/dist/types.d.ts +127 -100
  66. package/dist/types.d.ts.map +1 -1
  67. package/dist/types.js +53 -13
  68. package/dist/types.js.map +1 -1
  69. package/dist/util.d.ts +8 -3
  70. package/dist/util.d.ts.map +1 -1
  71. package/dist/util.js +33 -17
  72. package/dist/util.js.map +1 -1
  73. package/package.json +6 -7
  74. package/src/block-map.ts +31 -28
  75. package/src/car.ts +124 -46
  76. package/src/cid-set.ts +16 -10
  77. package/src/data-diff.ts +10 -10
  78. package/src/error.ts +6 -6
  79. package/src/logger.ts +1 -0
  80. package/src/mst/mst.ts +24 -28
  81. package/src/mst/util.ts +24 -11
  82. package/src/parse.ts +8 -10
  83. package/src/readable-repo.ts +6 -9
  84. package/src/repo.ts +13 -12
  85. package/src/storage/memory-blockstore.ts +8 -8
  86. package/src/storage/readable-blockstore.ts +12 -15
  87. package/src/storage/sync-storage.ts +4 -4
  88. package/src/storage/types.ts +25 -27
  89. package/src/sync/consumer.ts +5 -5
  90. package/src/sync/provider.ts +10 -7
  91. package/src/types.ts +82 -43
  92. package/src/util.ts +31 -16
  93. package/tests/_keys.ts +156 -156
  94. package/tests/_util.ts +28 -14
  95. package/tests/car.test.ts +31 -13
  96. package/tests/commit-proof-fixtures.json +79 -57
  97. package/tests/commit-proofs.test.ts +3 -3
  98. package/tests/covering-proofs.test.ts +6 -6
  99. package/tests/mst.test.ts +18 -19
  100. package/tests/proofs.test.ts +8 -8
  101. package/tests/repo.test.ts +1 -1
  102. package/tests/sync.test.ts +3 -6
  103. package/bench/mst.bench.ts +0 -165
  104. package/bench/repo.bench.ts +0 -48
  105. package/tsconfig.tests.tsbuildinfo +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @atproto/repo
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#4408](https://github.com/bluesky-social/atproto/pull/4408) [`d0c136c`](https://github.com/bluesky-social/atproto/commit/d0c136cba2ec8fa97017849b1023d5af5d2cc60c) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use `Cid` from `@atproto/lex` instead of `CID` from `multiformats` to represent CIDs.
8
+
9
+ - [#4408](https://github.com/bluesky-social/atproto/pull/4408) [`d0c136c`](https://github.com/bluesky-social/atproto/commit/d0c136cba2ec8fa97017849b1023d5af5d2cc60c) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Remove dependency on `multiformats`
10
+
11
+ ### Patch Changes
12
+
13
+ - [#4408](https://github.com/bluesky-social/atproto/pull/4408) [`d0c136c`](https://github.com/bluesky-social/atproto/commit/d0c136cba2ec8fa97017849b1023d5af5d2cc60c) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Remove dependency on `uint8arrays`
14
+
15
+ - [#4408](https://github.com/bluesky-social/atproto/pull/4408) [`d0c136c`](https://github.com/bluesky-social/atproto/commit/d0c136cba2ec8fa97017849b1023d5af5d2cc60c) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Makes `@atproto/repo` less dependent on NodeJS internal (to eventually allow this lib to work in other environments)
16
+
17
+ - Updated dependencies [[`0dbea15`](https://github.com/bluesky-social/atproto/commit/0dbea15da48a6ca913cc3a3a2d8c0ffe64d7c69a), [`d0c136c`](https://github.com/bluesky-social/atproto/commit/d0c136cba2ec8fa97017849b1023d5af5d2cc60c), [`527f5d4`](https://github.com/bluesky-social/atproto/commit/527f5d4c5d0c9264c2ff6f23ad06a41163fc6809)]:
18
+ - @atproto/syntax@0.5.2
19
+
20
+ ## 0.8.13
21
+
22
+ ### Patch Changes
23
+
24
+ - [#4729](https://github.com/bluesky-social/atproto/pull/4729) [`192685f`](https://github.com/bluesky-social/atproto/commit/192685fca75a68c9c50a94817d3f27da7fc02f56) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Optimize BufferedReader implementation
25
+
3
26
  ## 0.8.12
4
27
 
5
28
  ### Patch Changes
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  Dual MIT/Apache-2.0 License
2
2
 
3
- Copyright (c) 2022-2025 Bluesky Social PBC, and Contributors
3
+ Copyright (c) 2022-2026 Bluesky Social PBC, and Contributors
4
4
 
5
5
  Except as otherwise noted in individual files, this software is licensed under the MIT license (<http://opensource.org/licenses/MIT>), or the Apache License, Version 2.0 (<http://www.apache.org/licenses/LICENSE-2.0>).
6
6
 
@@ -1,31 +1,30 @@
1
- import { CID } from 'multiformats/cid';
2
- import { LexValue } from '@atproto/lexicon';
3
- export declare class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
1
+ import { Cid, LexValue } from '@atproto/lex-data';
2
+ export declare class BlockMap implements Iterable<[cid: Cid, bytes: Uint8Array]> {
4
3
  private map;
5
- constructor(entries?: Iterable<readonly [cid: CID, bytes: Uint8Array]>);
6
- add(value: LexValue): Promise<CID>;
7
- set(cid: CID, bytes: Uint8Array): BlockMap;
8
- get(cid: CID): Uint8Array | undefined;
9
- delete(cid: CID): BlockMap;
10
- getMany(cids: CID[]): {
4
+ constructor(entries?: Iterable<readonly [cid: Cid, bytes: Uint8Array]>);
5
+ add(value: LexValue): Promise<Cid>;
6
+ set(cid: Cid, bytes: Uint8Array): BlockMap;
7
+ get(cid: Cid): Uint8Array | undefined;
8
+ delete(cid: Cid): BlockMap;
9
+ getMany(cids: Cid[]): {
11
10
  blocks: BlockMap;
12
- missing: CID[];
11
+ missing: Cid[];
13
12
  };
14
- has(cid: CID): boolean;
13
+ has(cid: Cid): boolean;
15
14
  clear(): void;
16
- forEach(cb: (bytes: Uint8Array, cid: CID) => void): void;
15
+ forEach(cb: (bytes: Uint8Array, cid: Cid) => void): void;
17
16
  entries(): Entry[];
18
- cids(): CID[];
17
+ cids(): Cid[];
19
18
  addMap(toAdd: BlockMap): BlockMap;
20
19
  get size(): number;
21
20
  get byteSize(): number;
22
21
  equals(other: BlockMap): boolean;
23
- keys(): Generator<CID, void, unknown>;
22
+ keys(): Generator<Cid, void, unknown>;
24
23
  values(): Generator<Uint8Array, void, unknown>;
25
- [Symbol.iterator](): Generator<[CID, Uint8Array], void, unknown>;
24
+ [Symbol.iterator](): Generator<[Cid, Uint8Array], void, unknown>;
26
25
  }
27
26
  type Entry = {
28
- cid: CID;
27
+ cid: Cid;
29
28
  bytes: Uint8Array;
30
29
  };
31
30
  export default BlockMap;
@@ -1 +1 @@
1
- {"version":3,"file":"block-map.d.ts","sourceRoot":"","sources":["../src/block-map.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAGtC,OAAO,EAAE,QAAQ,EAAa,MAAM,kBAAkB,CAAA;AAEtD,qBAAa,QAAS,YAAW,QAAQ,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAqC;gBAEpC,OAAO,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAQhE,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAMxC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,QAAQ;IAK1C,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,GAAG,SAAS;IAIrC,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IAK1B,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG;QAAE,MAAM,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,GAAG,EAAE,CAAA;KAAE;IAc1D,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAItB,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIxD,OAAO,IAAI,KAAK,EAAE;IAIlB,IAAI,IAAI,GAAG,EAAE;IAIb,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAKjC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,QAAQ,IAAI,MAAM,CAIrB;IAED,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAc/B,IAAI,IAAI,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC;IAMrC,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC;IAI9C,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;CAKlE;AAMD,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,UAAU,CAAA;CAClB,CAAA;AAED,eAAe,QAAQ,CAAA"}
1
+ {"version":3,"file":"block-map.d.ts","sourceRoot":"","sources":["../src/block-map.ts"],"names":[],"mappings":"AACA,OAAO,EACL,GAAG,EACH,QAAQ,EAIT,MAAM,mBAAmB,CAAA;AAE1B,qBAAa,QAAS,YAAW,QAAQ,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAqC;gBAEpC,OAAO,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAQhE,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAOxC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,QAAQ;IAK1C,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,GAAG,SAAS;IAIrC,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IAK1B,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG;QAAE,MAAM,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,GAAG,EAAE,CAAA;KAAE;IAc1D,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAItB,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIxD,OAAO,IAAI,KAAK,EAAE;IAIlB,IAAI,IAAI,GAAG,EAAE;IAIb,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAKjC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,QAAQ,IAAI,MAAM,CAIrB;IAED,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAc/B,IAAI,IAAI,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC;IAMrC,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC;IAI9C,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;CAKlE;AAMD,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,UAAU,CAAA;CAClB,CAAA;AAED,eAAe,QAAQ,CAAA"}
package/dist/block-map.js CHANGED
@@ -1,44 +1,8 @@
1
1
  "use strict";
2
- /* eslint-disable import/no-deprecated */
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || (function () {
20
- var ownKeys = function(o) {
21
- ownKeys = Object.getOwnPropertyNames || function (o) {
22
- var ar = [];
23
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
- return ar;
25
- };
26
- return ownKeys(o);
27
- };
28
- return function (mod) {
29
- if (mod && mod.__esModule) return mod;
30
- var result = {};
31
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
- __setModuleDefault(result, mod);
33
- return result;
34
- };
35
- })();
36
2
  Object.defineProperty(exports, "__esModule", { value: true });
37
3
  exports.BlockMap = void 0;
38
- const cid_1 = require("multiformats/cid");
39
- const uint8arrays = __importStar(require("uint8arrays"));
40
- const common_1 = require("@atproto/common");
41
- const lexicon_1 = require("@atproto/lexicon");
4
+ const lex_cbor_1 = require("@atproto/lex-cbor");
5
+ const lex_data_1 = require("@atproto/lex-data");
42
6
  class BlockMap {
43
7
  constructor(entries) {
44
8
  Object.defineProperty(this, "map", {
@@ -54,9 +18,10 @@ class BlockMap {
54
18
  }
55
19
  }
56
20
  async add(value) {
57
- const block = await (0, common_1.dataToCborBlock)((0, lexicon_1.lexToIpld)(value));
58
- this.set(block.cid, block.bytes);
59
- return block.cid;
21
+ const bytes = (0, lex_cbor_1.encode)(value);
22
+ const cid = await (0, lex_data_1.cidForCbor)(bytes);
23
+ this.set(cid, bytes);
24
+ return cid;
60
25
  }
61
26
  set(cid, bytes) {
62
27
  this.map.set(cid.toString(), bytes);
@@ -121,7 +86,7 @@ class BlockMap {
121
86
  const otherBytes = other.get(cid);
122
87
  if (!otherBytes)
123
88
  return false;
124
- if (!uint8arrays.equals(bytes, otherBytes)) {
89
+ if (!(0, lex_data_1.ui8Equals)(bytes, otherBytes)) {
125
90
  return false;
126
91
  }
127
92
  }
@@ -129,7 +94,7 @@ class BlockMap {
129
94
  }
130
95
  *keys() {
131
96
  for (const key of this.map.keys()) {
132
- yield cid_1.CID.parse(key);
97
+ yield (0, lex_data_1.parseCid)(key);
133
98
  }
134
99
  }
135
100
  *values() {
@@ -137,7 +102,7 @@ class BlockMap {
137
102
  }
138
103
  *[Symbol.iterator]() {
139
104
  for (const [key, value] of this.map) {
140
- yield [cid_1.CID.parse(key), value];
105
+ yield [(0, lex_data_1.parseCid)(key), value];
141
106
  }
142
107
  }
143
108
  }
@@ -1 +1 @@
1
- {"version":3,"file":"block-map.js","sourceRoot":"","sources":["../src/block-map.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable import/no-deprecated */\n\nimport { CID } from 'multiformats/cid'\nimport * as uint8arrays from 'uint8arrays'\nimport { dataToCborBlock } from '@atproto/common'\nimport { LexValue, lexToIpld } from '@atproto/lexicon'\n\nexport class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {\n private map: Map<string, Uint8Array> = new Map()\n\n constructor(entries?: Iterable<readonly [cid: CID, bytes: Uint8Array]>) {\n if (entries) {\n for (const [cid, bytes] of entries) {\n this.set(cid, bytes)\n }\n }\n }\n\n async add(value: LexValue): Promise<CID> {\n const block = await dataToCborBlock(lexToIpld(value))\n this.set(block.cid, block.bytes)\n return block.cid\n }\n\n set(cid: CID, bytes: Uint8Array): BlockMap {\n this.map.set(cid.toString(), bytes)\n return this\n }\n\n get(cid: CID): Uint8Array | undefined {\n return this.map.get(cid.toString())\n }\n\n delete(cid: CID): BlockMap {\n this.map.delete(cid.toString())\n return this\n }\n\n getMany(cids: CID[]): { blocks: BlockMap; missing: CID[] } {\n const missing: CID[] = []\n const blocks = new BlockMap()\n for (const cid of cids) {\n const got = this.map.get(cid.toString())\n if (got) {\n blocks.set(cid, got)\n } else {\n missing.push(cid)\n }\n }\n return { blocks, missing }\n }\n\n has(cid: CID): boolean {\n return this.map.has(cid.toString())\n }\n\n clear(): void {\n this.map.clear()\n }\n\n forEach(cb: (bytes: Uint8Array, cid: CID) => void): void {\n for (const [cid, bytes] of this) cb(bytes, cid)\n }\n\n entries(): Entry[] {\n return Array.from(this, toEntry)\n }\n\n cids(): CID[] {\n return Array.from(this.keys())\n }\n\n addMap(toAdd: BlockMap): BlockMap {\n for (const [cid, bytes] of toAdd) this.set(cid, bytes)\n return this\n }\n\n get size(): number {\n return this.map.size\n }\n\n get byteSize(): number {\n let size = 0\n for (const bytes of this.values()) size += bytes.length\n return size\n }\n\n equals(other: BlockMap): boolean {\n if (this.size !== other.size) {\n return false\n }\n for (const [cid, bytes] of this) {\n const otherBytes = other.get(cid)\n if (!otherBytes) return false\n if (!uint8arrays.equals(bytes, otherBytes)) {\n return false\n }\n }\n return true\n }\n\n *keys(): Generator<CID, void, unknown> {\n for (const key of this.map.keys()) {\n yield CID.parse(key)\n }\n }\n\n *values(): Generator<Uint8Array, void, unknown> {\n yield* this.map.values()\n }\n\n *[Symbol.iterator](): Generator<[CID, Uint8Array], void, unknown> {\n for (const [key, value] of this.map) {\n yield [CID.parse(key), value]\n }\n }\n}\n\nfunction toEntry([cid, bytes]: readonly [CID, Uint8Array]): Entry {\n return { cid, bytes }\n}\n\ntype Entry = {\n cid: CID\n bytes: Uint8Array\n}\n\nexport default BlockMap\n"]}
1
+ {"version":3,"file":"block-map.js","sourceRoot":"","sources":["../src/block-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode } from '@atproto/lex-cbor'\nimport {\n Cid,\n LexValue,\n cidForCbor,\n parseCid,\n ui8Equals,\n} from '@atproto/lex-data'\n\nexport class BlockMap implements Iterable<[cid: Cid, bytes: Uint8Array]> {\n private map: Map<string, Uint8Array> = new Map()\n\n constructor(entries?: Iterable<readonly [cid: Cid, bytes: Uint8Array]>) {\n if (entries) {\n for (const [cid, bytes] of entries) {\n this.set(cid, bytes)\n }\n }\n }\n\n async add(value: LexValue): Promise<Cid> {\n const bytes = encode(value)\n const cid = await cidForCbor(bytes)\n this.set(cid, bytes)\n return cid\n }\n\n set(cid: Cid, bytes: Uint8Array): BlockMap {\n this.map.set(cid.toString(), bytes)\n return this\n }\n\n get(cid: Cid): Uint8Array | undefined {\n return this.map.get(cid.toString())\n }\n\n delete(cid: Cid): BlockMap {\n this.map.delete(cid.toString())\n return this\n }\n\n getMany(cids: Cid[]): { blocks: BlockMap; missing: Cid[] } {\n const missing: Cid[] = []\n const blocks = new BlockMap()\n for (const cid of cids) {\n const got = this.map.get(cid.toString())\n if (got) {\n blocks.set(cid, got)\n } else {\n missing.push(cid)\n }\n }\n return { blocks, missing }\n }\n\n has(cid: Cid): boolean {\n return this.map.has(cid.toString())\n }\n\n clear(): void {\n this.map.clear()\n }\n\n forEach(cb: (bytes: Uint8Array, cid: Cid) => void): void {\n for (const [cid, bytes] of this) cb(bytes, cid)\n }\n\n entries(): Entry[] {\n return Array.from(this, toEntry)\n }\n\n cids(): Cid[] {\n return Array.from(this.keys())\n }\n\n addMap(toAdd: BlockMap): BlockMap {\n for (const [cid, bytes] of toAdd) this.set(cid, bytes)\n return this\n }\n\n get size(): number {\n return this.map.size\n }\n\n get byteSize(): number {\n let size = 0\n for (const bytes of this.values()) size += bytes.length\n return size\n }\n\n equals(other: BlockMap): boolean {\n if (this.size !== other.size) {\n return false\n }\n for (const [cid, bytes] of this) {\n const otherBytes = other.get(cid)\n if (!otherBytes) return false\n if (!ui8Equals(bytes, otherBytes)) {\n return false\n }\n }\n return true\n }\n\n *keys(): Generator<Cid, void, unknown> {\n for (const key of this.map.keys()) {\n yield parseCid(key)\n }\n }\n\n *values(): Generator<Uint8Array, void, unknown> {\n yield* this.map.values()\n }\n\n *[Symbol.iterator](): Generator<[Cid, Uint8Array], void, unknown> {\n for (const [key, value] of this.map) {\n yield [parseCid(key), value]\n }\n }\n}\n\nfunction toEntry([cid, bytes]: readonly [Cid, Uint8Array]): Entry {\n return { cid, bytes }\n}\n\ntype Entry = {\n cid: Cid\n bytes: Uint8Array\n}\n\nexport default BlockMap\n"]}
package/dist/car.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { CID } from 'multiformats/cid';
1
+ import { Cid } from '@atproto/lex-data';
2
2
  import { BlockMap } from './block-map';
3
3
  import { CarBlock } from './types';
4
- export declare function writeCarStream(root: CID | null, blocks: AsyncIterable<CarBlock>): AsyncIterable<Uint8Array>;
5
- export declare const blocksToCarFile: (root: CID | null, blocks: BlockMap) => Promise<Uint8Array>;
6
- export declare const blocksToCarStream: (root: CID | null, blocks: BlockMap) => AsyncIterable<Uint8Array>;
4
+ export declare function writeCarStream(root: Cid | null, blocks: AsyncIterable<CarBlock>): AsyncIterable<Uint8Array>;
5
+ export declare function blocksToCarFile(root: Cid | null, blocks: BlockMap): Promise<Uint8Array>;
6
+ export declare const blocksToCarStream: (root: Cid | null, blocks: BlockMap) => AsyncIterable<Uint8Array>;
7
7
  export type ReadCarOptions = {
8
8
  /**
9
9
  * When true, does not verify CID-to-content mapping within CAR.
@@ -11,22 +11,22 @@ export type ReadCarOptions = {
11
11
  skipCidVerification?: boolean;
12
12
  };
13
13
  export declare const readCar: (bytes: Uint8Array, opts?: ReadCarOptions) => Promise<{
14
- roots: CID[];
14
+ roots: Cid[];
15
15
  blocks: BlockMap;
16
16
  }>;
17
17
  export declare const readCarWithRoot: (bytes: Uint8Array, opts?: ReadCarOptions) => Promise<{
18
- root: CID;
18
+ root: Cid;
19
19
  blocks: BlockMap;
20
20
  }>;
21
21
  export type CarBlockIterable = AsyncGenerator<CarBlock, void, unknown> & {
22
22
  dump: () => Promise<void>;
23
23
  };
24
24
  export declare const readCarStream: (car: Iterable<Uint8Array> | AsyncIterable<Uint8Array>, opts?: ReadCarOptions) => Promise<{
25
- roots: CID[];
25
+ roots: Cid[];
26
26
  blocks: CarBlockIterable;
27
27
  }>;
28
28
  export declare const readCarReader: (reader: BytesReader, opts?: ReadCarOptions) => Promise<{
29
- roots: CID[];
29
+ roots: Cid[];
30
30
  blocks: CarBlockIterable;
31
31
  }>;
32
32
  export declare function verifyIncomingCarBlocks(car: AsyncIterable<CarBlock>): AsyncGenerator<CarBlock, void, unknown>;
package/dist/car.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"car.d.ts","sourceRoot":"","sources":["../src/car.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAUtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAElC,wBAAuB,cAAc,CACnC,IAAI,EAAE,GAAG,GAAG,IAAI,EAChB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC9B,aAAa,CAAC,UAAU,CAAC,CAgB3B;AAED,eAAO,MAAM,eAAe,GAC1B,MAAM,GAAG,GAAG,IAAI,EAChB,QAAQ,QAAQ,KACf,OAAO,CAAC,UAAU,CAGpB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,MAAM,GAAG,GAAG,IAAI,EAChB,QAAQ,QAAQ,KACf,aAAa,CAAC,UAAU,CAE1B,CAAA;AAQD,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED,eAAO,MAAM,OAAO,GAClB,OAAO,UAAU,EACjB,OAAO,cAAc,KACpB,OAAO,CAAC;IAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAO5C,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,OAAO,UAAU,EACjB,OAAO,cAAc,KACpB,OAAO,CAAC;IAAE,IAAI,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAUzC,CAAA;AACD,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG;IACvE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,KAAK,QAAQ,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,UAAU,CAAC,EACrD,OAAO,cAAc,KACpB,OAAO,CAAC;IACT,KAAK,EAAE,GAAG,EAAE,CAAA;IACZ,MAAM,EAAE,gBAAgB,CAAA;CACzB,CAEA,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,QAAQ,WAAW,EACnB,OAAO,cAAc,KACpB,OAAO,CAAC;IACT,KAAK,EAAE,GAAG,EAAE,CAAA;IACZ,MAAM,EAAE,gBAAgB,CAAA;CACzB,CAmBA,CAAA;AAoDD,wBAAuB,uBAAuB,CAC5C,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC3B,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAKzC;AAuBD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB"}
1
+ {"version":3,"file":"car.d.ts","sourceRoot":"","sources":["../src/car.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAA4B,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAU,MAAM,SAAS,CAAA;AAG1C,wBAAuB,cAAc,CACnC,IAAI,EAAE,GAAG,GAAG,IAAI,EAChB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC9B,aAAa,CAAC,UAAU,CAAC,CAgB3B;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,GAAG,IAAI,EAChB,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,eAAO,MAAM,iBAAiB,GAC5B,MAAM,GAAG,GAAG,IAAI,EAChB,QAAQ,QAAQ,KACf,aAAa,CAAC,UAAU,CAE1B,CAAA;AAQD,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED,eAAO,MAAM,OAAO,GAClB,OAAO,UAAU,EACjB,OAAO,cAAc,KACpB,OAAO,CAAC;IAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAO5C,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,OAAO,UAAU,EACjB,OAAO,cAAc,KACpB,OAAO,CAAC;IAAE,IAAI,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAUzC,CAAA;AACD,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG;IACvE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,KAAK,QAAQ,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,UAAU,CAAC,EACrD,OAAO,cAAc,KACpB,OAAO,CAAC;IACT,KAAK,EAAE,GAAG,EAAE,CAAA;IACZ,MAAM,EAAE,gBAAgB,CAAA;CACzB,CAEA,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,QAAQ,WAAW,EACnB,OAAO,cAAc,KACpB,OAAO,CAAC;IACT,KAAK,EAAE,GAAG,EAAE,CAAA;IACZ,MAAM,EAAE,gBAAgB,CAAA;CACzB,CAoBA,CAAA;AAoDD,wBAAuB,uBAAuB,CAC5C,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC3B,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAOzC;AAuBD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB"}
package/dist/car.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- /* eslint-disable import/no-deprecated */
3
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
3
  if (k2 === undefined) k2 = k;
5
4
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -34,15 +33,17 @@ var __importStar = (this && this.__importStar) || (function () {
34
33
  };
35
34
  })();
36
35
  Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.readCarReader = exports.readCarStream = exports.readCarWithRoot = exports.readCar = exports.blocksToCarStream = exports.blocksToCarFile = void 0;
36
+ exports.readCarReader = exports.readCarStream = exports.readCarWithRoot = exports.readCar = exports.blocksToCarStream = void 0;
38
37
  exports.writeCarStream = writeCarStream;
38
+ exports.blocksToCarFile = blocksToCarFile;
39
39
  exports.verifyIncomingCarBlocks = verifyIncomingCarBlocks;
40
40
  const promises_1 = require("node:timers/promises");
41
- const cbor = __importStar(require("@ipld/dag-cbor"));
42
- const ui8 = __importStar(require("uint8arrays"));
43
41
  const varint = __importStar(require("varint"));
44
- const common_1 = require("@atproto/common");
42
+ const cbor = __importStar(require("@atproto/lex-cbor"));
43
+ const lex_data_1 = require("@atproto/lex-data");
45
44
  const block_map_1 = require("./block-map");
45
+ const types_1 = require("./types");
46
+ const util_1 = require("./util");
46
47
  async function* writeCarStream(root, blocks) {
47
48
  const header = new Uint8Array(cbor.encode({
48
49
  version: 1,
@@ -56,11 +57,9 @@ async function* writeCarStream(root, blocks) {
56
57
  yield block.bytes;
57
58
  }
58
59
  }
59
- const blocksToCarFile = (root, blocks) => {
60
- const carStream = (0, exports.blocksToCarStream)(root, blocks);
61
- return (0, common_1.streamToBuffer)(carStream);
62
- };
63
- exports.blocksToCarFile = blocksToCarFile;
60
+ async function blocksToCarFile(root, blocks) {
61
+ return (0, util_1.concatBytesAsync)((0, exports.blocksToCarStream)(root, blocks));
62
+ }
64
63
  const blocksToCarStream = (root, blocks) => {
65
64
  return writeCarStream(root, iterateBlocks(blocks));
66
65
  };
@@ -103,11 +102,12 @@ const readCarReader = async (reader, opts) => {
103
102
  }
104
103
  const headerBytes = await reader.read(headerSize);
105
104
  const header = cbor.decode(headerBytes);
106
- if (!common_1.check.is(header, common_1.schema.carHeader)) {
107
- throw new Error('Could not parse CAR header');
105
+ const result = types_1.schema.carHeader.safeParse(header);
106
+ if (!result.success) {
107
+ throw new Error('Could not parse CAR header', { cause: result.error });
108
108
  }
109
109
  return {
110
- roots: header.roots,
110
+ roots: result.data.roots,
111
111
  blocks: readCarBlocksIter(reader, opts),
112
112
  };
113
113
  }
@@ -146,7 +146,7 @@ async function* readCarBlocksIterGenerator(reader) {
146
146
  break;
147
147
  }
148
148
  const blockBytes = await reader.read(blockSize);
149
- const cid = (0, common_1.parseCidFromBytes)(blockBytes.subarray(0, 36));
149
+ const cid = (0, lex_data_1.decodeCid)(blockBytes.subarray(0, 36));
150
150
  const bytes = blockBytes.subarray(36);
151
151
  yield { cid, bytes };
152
152
  // yield to the event loop every 25 blocks
@@ -163,7 +163,9 @@ async function* readCarBlocksIterGenerator(reader) {
163
163
  }
164
164
  async function* verifyIncomingCarBlocks(car) {
165
165
  for await (const block of car) {
166
- await (0, common_1.verifyCidForBytes)(block.cid, block.bytes);
166
+ if (!(await (0, lex_data_1.isCidForBytes)(block.cid, block.bytes))) {
167
+ throw new Error(`Not a valid CID for bytes (${block.cid.toString()})`);
168
+ }
167
169
  yield block;
168
170
  }
169
171
  }
@@ -185,7 +187,7 @@ const readVarint = async (reader) => {
185
187
  done = true;
186
188
  }
187
189
  }
188
- const concatted = ui8.concat(bytes);
190
+ const concatted = Buffer.concat(bytes);
189
191
  return varint.decode(concatted);
190
192
  };
191
193
  class Ui8Reader {
@@ -219,14 +221,13 @@ class Ui8Reader {
219
221
  }
220
222
  async close() { }
221
223
  }
224
+ /**
225
+ * This code was optimized for performance. See
226
+ * {@link https://github.com/bluesky-social/atproto/pull/4729 #4729} for more details
227
+ * and benchmarks.
228
+ */
222
229
  class BufferedReader {
223
230
  constructor(stream) {
224
- Object.defineProperty(this, "buffer", {
225
- enumerable: true,
226
- configurable: true,
227
- writable: true,
228
- value: new Uint8Array()
229
- });
230
231
  Object.defineProperty(this, "iterator", {
231
232
  enumerable: true,
232
233
  configurable: true,
@@ -239,36 +240,105 @@ class BufferedReader {
239
240
  writable: true,
240
241
  value: false
241
242
  });
243
+ /** fifo list of chunks to consume */
244
+ Object.defineProperty(this, "chunks", {
245
+ enumerable: true,
246
+ configurable: true,
247
+ writable: true,
248
+ value: []
249
+ });
242
250
  this.iterator =
243
251
  Symbol.asyncIterator in stream
244
252
  ? stream[Symbol.asyncIterator]()
245
253
  : stream[Symbol.iterator]();
246
254
  }
247
- async read(bytesToRead) {
248
- await this.readUntilBuffered(bytesToRead);
249
- const value = this.buffer.subarray(0, bytesToRead);
250
- this.buffer = this.buffer.subarray(bytesToRead);
251
- return value;
255
+ /** Number of bytes currently buffered and available for reading */
256
+ get bufferedByteLength() {
257
+ let total = 0;
258
+ for (let i = 0; i < this.chunks.length; i++) {
259
+ total += this.chunks[i].byteLength;
260
+ }
261
+ return total;
252
262
  }
253
- async readUntilBuffered(bytesToRead) {
254
- if (this.isDone) {
255
- return;
263
+ /**
264
+ * @note concurrent reads are **NOT** supported by the current implementation
265
+ * and would require call to readUntilBuffered to be using a fifo lock for
266
+ * read()s to be processed in fifo order.
267
+ */
268
+ async read(bytesToRead) {
269
+ const bytesNeeded = bytesToRead - this.bufferedByteLength;
270
+ if (bytesNeeded > 0 && !this.isDone) {
271
+ await this.readUntilBuffered(bytesNeeded);
272
+ }
273
+ const resultLength = Math.min(bytesToRead, this.bufferedByteLength);
274
+ if (resultLength <= 0)
275
+ return new Uint8Array();
276
+ const firstChunk = this.consumeChunk(resultLength);
277
+ if (firstChunk.byteLength === resultLength) {
278
+ // If the data consumed from the first chunk contains all we need, return
279
+ // it as-is. This allows to avoid any copy operation.
280
+ return firstChunk;
256
281
  }
257
- while (this.buffer.length < bytesToRead) {
282
+ // The first chunk does not have all the data we need. We have to copy
283
+ // multiple chunks into a larger buffer
284
+ const result = new Uint8Array(resultLength);
285
+ let resultWriteIndex = 0;
286
+ // Copy the first chunk into the result buffer
287
+ result.set(firstChunk, resultWriteIndex);
288
+ resultWriteIndex += firstChunk.byteLength;
289
+ // Copy more chunks as needed (we use do-while because we *know* we need
290
+ // more than one chunk)
291
+ do {
292
+ const missingLength = resultLength - resultWriteIndex;
293
+ const currentChunk = this.consumeChunk(missingLength);
294
+ result.set(currentChunk, resultWriteIndex);
295
+ resultWriteIndex += currentChunk.byteLength;
296
+ } while (resultWriteIndex < resultLength);
297
+ return result;
298
+ }
299
+ async readUntilBuffered(bytesNeeded) {
300
+ let bytesRead = 0;
301
+ while (bytesRead < bytesNeeded) {
258
302
  const next = await this.iterator.next();
259
303
  if (next.done) {
260
304
  this.isDone = true;
261
- return;
305
+ break;
262
306
  }
263
- this.buffer = ui8.concat([this.buffer, next.value]);
307
+ else {
308
+ this.chunks.push(next.value);
309
+ bytesRead += next.value.byteLength;
310
+ }
311
+ }
312
+ return bytesRead;
313
+ }
314
+ consumeChunk(bytesToConsume) {
315
+ const firstChunk = this.chunks[0];
316
+ if (bytesToConsume < firstChunk.byteLength) {
317
+ // return a sub-view of the data being read and replace the first chunk
318
+ // with a sub-view that does not contain that data.
319
+ // @NOTE for some reason, subarray() revealed to be 7-8% slower in NodeJS
320
+ // benchmarks.
321
+ // this.chunks[0] = firstChunk.subarray(bytesToConsume)
322
+ // return firstChunk.subarray(0, bytesToConsume)
323
+ this.chunks[0] = new Uint8Array(firstChunk.buffer, firstChunk.byteOffset + bytesToConsume, firstChunk.byteLength - bytesToConsume);
324
+ return new Uint8Array(firstChunk.buffer, firstChunk.byteOffset, bytesToConsume);
325
+ }
326
+ else {
327
+ // First chunk is being read in full, discard it
328
+ this.chunks.shift();
329
+ return firstChunk;
264
330
  }
265
331
  }
266
332
  async close() {
267
- if (!this.isDone && this.iterator.return) {
268
- await this.iterator.return();
333
+ try {
334
+ if (!this.isDone && this.iterator.return) {
335
+ await this.iterator.return();
336
+ }
337
+ }
338
+ finally {
339
+ this.isDone = true;
340
+ this.chunks.length = 0;
269
341
  }
270
- this.isDone = true;
271
- this.buffer = new Uint8Array();
272
342
  }
273
343
  }
274
344
  //# sourceMappingURL=car.js.map
package/dist/car.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"car.js","sourceRoot":"","sources":["../src/car.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable import/no-deprecated */\n\nimport { setImmediate } from 'node:timers/promises'\nimport * as cbor from '@ipld/dag-cbor'\nimport { CID } from 'multiformats/cid'\nimport * as ui8 from 'uint8arrays'\nimport * as varint from 'varint'\nimport {\n check,\n parseCidFromBytes,\n schema,\n streamToBuffer,\n verifyCidForBytes,\n} from '@atproto/common'\nimport { BlockMap } from './block-map'\nimport { CarBlock } from './types'\n\nexport async function* writeCarStream(\n root: CID | null,\n blocks: AsyncIterable<CarBlock>,\n): AsyncIterable<Uint8Array> {\n const header = new Uint8Array(\n cbor.encode({\n version: 1,\n roots: root ? [root] : [],\n }),\n )\n yield new Uint8Array(varint.encode(header.byteLength))\n yield header\n for await (const block of blocks) {\n yield new Uint8Array(\n varint.encode(block.cid.bytes.byteLength + block.bytes.byteLength),\n )\n yield block.cid.bytes\n yield block.bytes\n }\n}\n\nexport const blocksToCarFile = (\n root: CID | null,\n blocks: BlockMap,\n): Promise<Uint8Array> => {\n const carStream = blocksToCarStream(root, blocks)\n return streamToBuffer(carStream)\n}\n\nexport const blocksToCarStream = (\n root: CID | null,\n blocks: BlockMap,\n): AsyncIterable<Uint8Array> => {\n return writeCarStream(root, iterateBlocks(blocks))\n}\n\nasync function* iterateBlocks(blocks: BlockMap) {\n for (const entry of blocks.entries()) {\n yield { cid: entry.cid, bytes: entry.bytes }\n }\n}\n\nexport type ReadCarOptions = {\n /**\n * When true, does not verify CID-to-content mapping within CAR.\n */\n skipCidVerification?: boolean\n}\n\nexport const readCar = async (\n bytes: Uint8Array,\n opts?: ReadCarOptions,\n): Promise<{ roots: CID[]; blocks: BlockMap }> => {\n const { roots, blocks } = await readCarReader(new Ui8Reader(bytes), opts)\n const blockMap = new BlockMap()\n for await (const block of blocks) {\n blockMap.set(block.cid, block.bytes)\n }\n return { roots, blocks: blockMap }\n}\n\nexport const readCarWithRoot = async (\n bytes: Uint8Array,\n opts?: ReadCarOptions,\n): Promise<{ root: CID; blocks: BlockMap }> => {\n const { roots, blocks } = await readCar(bytes, opts)\n if (roots.length !== 1) {\n throw new Error(`Expected one root, got ${roots.length}`)\n }\n const root = roots[0]\n return {\n root,\n blocks,\n }\n}\nexport type CarBlockIterable = AsyncGenerator<CarBlock, void, unknown> & {\n dump: () => Promise<void>\n}\n\nexport const readCarStream = async (\n car: Iterable<Uint8Array> | AsyncIterable<Uint8Array>,\n opts?: ReadCarOptions,\n): Promise<{\n roots: CID[]\n blocks: CarBlockIterable\n}> => {\n return readCarReader(new BufferedReader(car), opts)\n}\n\nexport const readCarReader = async (\n reader: BytesReader,\n opts?: ReadCarOptions,\n): Promise<{\n roots: CID[]\n blocks: CarBlockIterable\n}> => {\n try {\n const headerSize = await readVarint(reader)\n if (headerSize === null) {\n throw new Error('Could not parse CAR header')\n }\n const headerBytes = await reader.read(headerSize)\n const header = cbor.decode(headerBytes)\n if (!check.is(header, schema.carHeader)) {\n throw new Error('Could not parse CAR header')\n }\n return {\n roots: header.roots,\n blocks: readCarBlocksIter(reader, opts),\n }\n } catch (err) {\n await reader.close()\n throw err\n }\n}\n\nconst readCarBlocksIter = (\n reader: BytesReader,\n opts?: ReadCarOptions,\n): CarBlockIterable => {\n let generator = readCarBlocksIterGenerator(reader)\n if (!opts?.skipCidVerification) {\n generator = verifyIncomingCarBlocks(generator)\n }\n return Object.assign(generator, {\n async dump() {\n // try/finally to ensure that reader.close is called even if blocks.return throws.\n try {\n // Prevent the iterator from being started after this method is called.\n await generator.return()\n } finally {\n // @NOTE the \"finally\" block of the async generator won't be called\n // if the iteration was never started so we need to manually close here.\n await reader.close()\n }\n },\n })\n}\n\nasync function* readCarBlocksIterGenerator(\n reader: BytesReader,\n): AsyncGenerator<CarBlock, void, unknown> {\n let blocks = 0\n try {\n while (!reader.isDone) {\n const blockSize = await readVarint(reader)\n if (blockSize === null) {\n break\n }\n const blockBytes = await reader.read(blockSize)\n const cid = parseCidFromBytes(blockBytes.subarray(0, 36))\n const bytes = blockBytes.subarray(36)\n yield { cid, bytes }\n\n // yield to the event loop every 25 blocks\n // in the case the incoming CAR is synchronous, this can end up jamming up the thread\n blocks++\n if (blocks % 25 === 0) {\n await setImmediate()\n }\n }\n } finally {\n await reader.close()\n }\n}\n\nexport async function* verifyIncomingCarBlocks(\n car: AsyncIterable<CarBlock>,\n): AsyncGenerator<CarBlock, void, unknown> {\n for await (const block of car) {\n await verifyCidForBytes(block.cid, block.bytes)\n yield block\n }\n}\n\nconst readVarint = async (reader: BytesReader): Promise<number | null> => {\n let done = false\n const bytes: Uint8Array[] = []\n while (!done) {\n const byte = await reader.read(1)\n if (byte.byteLength === 0) {\n if (bytes.length > 0) {\n throw new Error('could not parse varint')\n } else {\n return null\n }\n }\n bytes.push(byte)\n if (byte[0] < 128) {\n done = true\n }\n }\n const concatted = ui8.concat(bytes)\n return varint.decode(concatted)\n}\n\ninterface BytesReader {\n isDone: boolean\n read(bytesToRead: number): Promise<Uint8Array>\n close(): Promise<void>\n}\n\nclass Ui8Reader implements BytesReader {\n idx = 0\n isDone = false\n\n constructor(public bytes: Uint8Array) {}\n\n async read(bytesToRead: number): Promise<Uint8Array> {\n const value = this.bytes.subarray(this.idx, this.idx + bytesToRead)\n this.idx += bytesToRead\n if (this.idx >= this.bytes.length) {\n this.isDone = true\n }\n return value\n }\n\n async close(): Promise<void> {}\n}\n\nclass BufferedReader implements BytesReader {\n buffer: Uint8Array = new Uint8Array()\n iterator: Iterator<Uint8Array> | AsyncIterator<Uint8Array>\n isDone = false\n\n constructor(stream: Iterable<Uint8Array> | AsyncIterable<Uint8Array>) {\n this.iterator =\n Symbol.asyncIterator in stream\n ? stream[Symbol.asyncIterator]()\n : stream[Symbol.iterator]()\n }\n\n async read(bytesToRead: number): Promise<Uint8Array> {\n await this.readUntilBuffered(bytesToRead)\n const value = this.buffer.subarray(0, bytesToRead)\n this.buffer = this.buffer.subarray(bytesToRead)\n return value\n }\n\n private async readUntilBuffered(bytesToRead: number) {\n if (this.isDone) {\n return\n }\n while (this.buffer.length < bytesToRead) {\n const next = await this.iterator.next()\n if (next.done) {\n this.isDone = true\n return\n }\n this.buffer = ui8.concat([this.buffer, next.value])\n }\n }\n\n async close(): Promise<void> {\n if (!this.isDone && this.iterator.return) {\n await this.iterator.return()\n }\n this.isDone = true\n this.buffer = new Uint8Array()\n }\n}\n"]}
1
+ {"version":3,"file":"car.js","sourceRoot":"","sources":["../src/car.ts"],"names":[],"mappings":"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","sourcesContent":["import { setImmediate } from 'node:timers/promises'\nimport * as varint from 'varint'\nimport * as cbor from '@atproto/lex-cbor'\nimport { Cid, decodeCid, isCidForBytes } from '@atproto/lex-data'\nimport { BlockMap } from './block-map'\nimport { CarBlock, schema } from './types'\nimport { concatBytesAsync } from './util'\n\nexport async function* writeCarStream(\n root: Cid | null,\n blocks: AsyncIterable<CarBlock>,\n): AsyncIterable<Uint8Array> {\n const header = new Uint8Array(\n cbor.encode({\n version: 1,\n roots: root ? [root] : [],\n }),\n )\n yield new Uint8Array(varint.encode(header.byteLength))\n yield header\n for await (const block of blocks) {\n yield new Uint8Array(\n varint.encode(block.cid.bytes.byteLength + block.bytes.byteLength),\n )\n yield block.cid.bytes\n yield block.bytes\n }\n}\n\nexport async function blocksToCarFile(\n root: Cid | null,\n blocks: BlockMap,\n): Promise<Uint8Array> {\n return concatBytesAsync(blocksToCarStream(root, blocks))\n}\n\nexport const blocksToCarStream = (\n root: Cid | null,\n blocks: BlockMap,\n): AsyncIterable<Uint8Array> => {\n return writeCarStream(root, iterateBlocks(blocks))\n}\n\nasync function* iterateBlocks(blocks: BlockMap) {\n for (const entry of blocks.entries()) {\n yield { cid: entry.cid, bytes: entry.bytes }\n }\n}\n\nexport type ReadCarOptions = {\n /**\n * When true, does not verify CID-to-content mapping within CAR.\n */\n skipCidVerification?: boolean\n}\n\nexport const readCar = async (\n bytes: Uint8Array,\n opts?: ReadCarOptions,\n): Promise<{ roots: Cid[]; blocks: BlockMap }> => {\n const { roots, blocks } = await readCarReader(new Ui8Reader(bytes), opts)\n const blockMap = new BlockMap()\n for await (const block of blocks) {\n blockMap.set(block.cid, block.bytes)\n }\n return { roots, blocks: blockMap }\n}\n\nexport const readCarWithRoot = async (\n bytes: Uint8Array,\n opts?: ReadCarOptions,\n): Promise<{ root: Cid; blocks: BlockMap }> => {\n const { roots, blocks } = await readCar(bytes, opts)\n if (roots.length !== 1) {\n throw new Error(`Expected one root, got ${roots.length}`)\n }\n const root = roots[0]\n return {\n root,\n blocks,\n }\n}\nexport type CarBlockIterable = AsyncGenerator<CarBlock, void, unknown> & {\n dump: () => Promise<void>\n}\n\nexport const readCarStream = async (\n car: Iterable<Uint8Array> | AsyncIterable<Uint8Array>,\n opts?: ReadCarOptions,\n): Promise<{\n roots: Cid[]\n blocks: CarBlockIterable\n}> => {\n return readCarReader(new BufferedReader(car), opts)\n}\n\nexport const readCarReader = async (\n reader: BytesReader,\n opts?: ReadCarOptions,\n): Promise<{\n roots: Cid[]\n blocks: CarBlockIterable\n}> => {\n try {\n const headerSize = await readVarint(reader)\n if (headerSize === null) {\n throw new Error('Could not parse CAR header')\n }\n const headerBytes = await reader.read(headerSize)\n const header = cbor.decode(headerBytes)\n const result = schema.carHeader.safeParse(header)\n if (!result.success) {\n throw new Error('Could not parse CAR header', { cause: result.error })\n }\n return {\n roots: result.data.roots,\n blocks: readCarBlocksIter(reader, opts),\n }\n } catch (err) {\n await reader.close()\n throw err\n }\n}\n\nconst readCarBlocksIter = (\n reader: BytesReader,\n opts?: ReadCarOptions,\n): CarBlockIterable => {\n let generator = readCarBlocksIterGenerator(reader)\n if (!opts?.skipCidVerification) {\n generator = verifyIncomingCarBlocks(generator)\n }\n return Object.assign(generator, {\n async dump() {\n // try/finally to ensure that reader.close is called even if blocks.return throws.\n try {\n // Prevent the iterator from being started after this method is called.\n await generator.return()\n } finally {\n // @NOTE the \"finally\" block of the async generator won't be called\n // if the iteration was never started so we need to manually close here.\n await reader.close()\n }\n },\n })\n}\n\nasync function* readCarBlocksIterGenerator(\n reader: BytesReader,\n): AsyncGenerator<CarBlock, void, unknown> {\n let blocks = 0\n try {\n while (!reader.isDone) {\n const blockSize = await readVarint(reader)\n if (blockSize === null) {\n break\n }\n const blockBytes = await reader.read(blockSize)\n const cid = decodeCid(blockBytes.subarray(0, 36))\n const bytes = blockBytes.subarray(36)\n yield { cid, bytes }\n\n // yield to the event loop every 25 blocks\n // in the case the incoming CAR is synchronous, this can end up jamming up the thread\n blocks++\n if (blocks % 25 === 0) {\n await setImmediate()\n }\n }\n } finally {\n await reader.close()\n }\n}\n\nexport async function* verifyIncomingCarBlocks(\n car: AsyncIterable<CarBlock>,\n): AsyncGenerator<CarBlock, void, unknown> {\n for await (const block of car) {\n if (!(await isCidForBytes(block.cid, block.bytes))) {\n throw new Error(`Not a valid CID for bytes (${block.cid.toString()})`)\n }\n yield block\n }\n}\n\nconst readVarint = async (reader: BytesReader): Promise<number | null> => {\n let done = false\n const bytes: Uint8Array[] = []\n while (!done) {\n const byte = await reader.read(1)\n if (byte.byteLength === 0) {\n if (bytes.length > 0) {\n throw new Error('could not parse varint')\n } else {\n return null\n }\n }\n bytes.push(byte)\n if (byte[0] < 128) {\n done = true\n }\n }\n const concatted = Buffer.concat(bytes)\n return varint.decode(concatted)\n}\n\ninterface BytesReader {\n isDone: boolean\n read(bytesToRead: number): Promise<Uint8Array>\n close(): Promise<void>\n}\n\nclass Ui8Reader implements BytesReader {\n idx = 0\n isDone = false\n\n constructor(public bytes: Uint8Array) {}\n\n async read(bytesToRead: number): Promise<Uint8Array> {\n const value = this.bytes.subarray(this.idx, this.idx + bytesToRead)\n this.idx += bytesToRead\n if (this.idx >= this.bytes.length) {\n this.isDone = true\n }\n return value\n }\n\n async close(): Promise<void> {}\n}\n\n/**\n * This code was optimized for performance. See\n * {@link https://github.com/bluesky-social/atproto/pull/4729 #4729} for more details\n * and benchmarks.\n */\nclass BufferedReader implements BytesReader {\n iterator: Iterator<Uint8Array> | AsyncIterator<Uint8Array>\n isDone = false\n\n /** fifo list of chunks to consume */\n private chunks: Uint8Array[] = []\n\n constructor(stream: Iterable<Uint8Array> | AsyncIterable<Uint8Array>) {\n this.iterator =\n Symbol.asyncIterator in stream\n ? stream[Symbol.asyncIterator]()\n : stream[Symbol.iterator]()\n }\n\n /** Number of bytes currently buffered and available for reading */\n get bufferedByteLength() {\n let total = 0\n for (let i = 0; i < this.chunks.length; i++) {\n total += this.chunks[i].byteLength\n }\n return total\n }\n\n /**\n * @note concurrent reads are **NOT** supported by the current implementation\n * and would require call to readUntilBuffered to be using a fifo lock for\n * read()s to be processed in fifo order.\n */\n async read(bytesToRead: number): Promise<Uint8Array> {\n const bytesNeeded = bytesToRead - this.bufferedByteLength\n if (bytesNeeded > 0 && !this.isDone) {\n await this.readUntilBuffered(bytesNeeded)\n }\n\n const resultLength = Math.min(bytesToRead, this.bufferedByteLength)\n if (resultLength <= 0) return new Uint8Array()\n\n const firstChunk = this.consumeChunk(resultLength)\n if (firstChunk.byteLength === resultLength) {\n // If the data consumed from the first chunk contains all we need, return\n // it as-is. This allows to avoid any copy operation.\n return firstChunk\n }\n\n // The first chunk does not have all the data we need. We have to copy\n // multiple chunks into a larger buffer\n const result = new Uint8Array(resultLength)\n let resultWriteIndex = 0\n\n // Copy the first chunk into the result buffer\n result.set(firstChunk, resultWriteIndex)\n resultWriteIndex += firstChunk.byteLength\n\n // Copy more chunks as needed (we use do-while because we *know* we need\n // more than one chunk)\n do {\n const missingLength = resultLength - resultWriteIndex\n const currentChunk = this.consumeChunk(missingLength)\n\n result.set(currentChunk, resultWriteIndex)\n resultWriteIndex += currentChunk.byteLength\n } while (resultWriteIndex < resultLength)\n\n return result\n }\n\n private async readUntilBuffered(bytesNeeded: number) {\n let bytesRead = 0\n while (bytesRead < bytesNeeded) {\n const next = await this.iterator.next()\n if (next.done) {\n this.isDone = true\n break\n } else {\n this.chunks.push(next.value)\n bytesRead += next.value.byteLength\n }\n }\n return bytesRead\n }\n\n private consumeChunk(bytesToConsume: number) {\n const firstChunk = this.chunks[0]!\n if (bytesToConsume < firstChunk.byteLength) {\n // return a sub-view of the data being read and replace the first chunk\n // with a sub-view that does not contain that data.\n\n // @NOTE for some reason, subarray() revealed to be 7-8% slower in NodeJS\n // benchmarks.\n\n // this.chunks[0] = firstChunk.subarray(bytesToConsume)\n // return firstChunk.subarray(0, bytesToConsume)\n\n this.chunks[0] = new Uint8Array(\n firstChunk.buffer,\n firstChunk.byteOffset + bytesToConsume,\n firstChunk.byteLength - bytesToConsume,\n )\n return new Uint8Array(\n firstChunk.buffer,\n firstChunk.byteOffset,\n bytesToConsume,\n )\n } else {\n // First chunk is being read in full, discard it\n this.chunks.shift()\n return firstChunk\n }\n }\n\n async close(): Promise<void> {\n try {\n if (!this.isDone && this.iterator.return) {\n await this.iterator.return()\n }\n } finally {\n this.isDone = true\n this.chunks.length = 0\n }\n }\n}\n"]}
package/dist/cid-set.d.ts CHANGED
@@ -1,15 +1,16 @@
1
- import { CID } from 'multiformats';
2
- export declare class CidSet {
1
+ import { Cid } from '@atproto/lex-data';
2
+ export declare class CidSet implements Iterable<Cid> {
3
3
  private set;
4
- constructor(arr?: CID[]);
5
- add(cid: CID): CidSet;
4
+ constructor(arr?: Cid[]);
5
+ add(cid: Cid): CidSet;
6
6
  addSet(toMerge: CidSet): CidSet;
7
7
  subtractSet(toSubtract: CidSet): CidSet;
8
- delete(cid: CID): this;
9
- has(cid: CID): boolean;
8
+ delete(cid: Cid): this;
9
+ has(cid: Cid): boolean;
10
10
  size(): number;
11
11
  clear(): CidSet;
12
- toList(): CID[];
12
+ toList(): Cid[];
13
+ [Symbol.iterator](): Generator<Cid, void, unknown>;
13
14
  }
14
15
  export default CidSet;
15
16
  //# sourceMappingURL=cid-set.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cid-set.d.ts","sourceRoot":"","sources":["../src/cid-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAElC,qBAAa,MAAM;IACjB,OAAO,CAAC,GAAG,CAAa;gBAEZ,GAAG,GAAE,GAAG,EAAO;IAK3B,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM;IAKrB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAK/B,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAKvC,MAAM,CAAC,GAAG,EAAE,GAAG;IAKf,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAItB,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,MAAM;IAKf,MAAM,IAAI,GAAG,EAAE;CAGhB;AAED,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"cid-set.d.ts","sourceRoot":"","sources":["../src/cid-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAY,MAAM,mBAAmB,CAAA;AAEjD,qBAAa,MAAO,YAAW,QAAQ,CAAC,GAAG,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAa;gBAEZ,GAAG,GAAE,GAAG,EAAO;IAK3B,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM;IAKrB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAK/B,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAKvC,MAAM,CAAC,GAAG,EAAE,GAAG;IAKf,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAItB,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,MAAM;IAKf,MAAM,IAAI,GAAG,EAAE;IAId,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC;CAKpD;AAED,eAAe,MAAM,CAAA"}