@atproto/repo 0.10.2 → 0.10.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 (44) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +22 -17
  3. package/jest.config.cjs +0 -24
  4. package/src/block-map.ts +0 -131
  5. package/src/car.ts +0 -357
  6. package/src/cid-set.ts +0 -55
  7. package/src/data-diff.ts +0 -117
  8. package/src/error.ts +0 -43
  9. package/src/index.ts +0 -11
  10. package/src/logger.ts +0 -7
  11. package/src/mst/diff.ts +0 -114
  12. package/src/mst/index.ts +0 -4
  13. package/src/mst/mst.ts +0 -892
  14. package/src/mst/util.ts +0 -160
  15. package/src/mst/walker.ts +0 -118
  16. package/src/parse.ts +0 -44
  17. package/src/readable-repo.ts +0 -86
  18. package/src/repo.ts +0 -236
  19. package/src/storage/index.ts +0 -4
  20. package/src/storage/memory-blockstore.ts +0 -76
  21. package/src/storage/readable-blockstore.ts +0 -55
  22. package/src/storage/sync-storage.ts +0 -35
  23. package/src/storage/types.ts +0 -47
  24. package/src/sync/consumer.ts +0 -207
  25. package/src/sync/index.ts +0 -2
  26. package/src/sync/provider.ts +0 -67
  27. package/src/types.ts +0 -227
  28. package/src/util.ts +0 -146
  29. package/tests/_keys.ts +0 -156
  30. package/tests/_util.ts +0 -265
  31. package/tests/car-file-fixtures.json +0 -28
  32. package/tests/car.test.ts +0 -125
  33. package/tests/commit-data.test.ts +0 -94
  34. package/tests/commit-proof-fixtures.json +0 -118
  35. package/tests/commit-proofs.test.ts +0 -63
  36. package/tests/covering-proofs.test.ts +0 -256
  37. package/tests/mst.test.ts +0 -450
  38. package/tests/proofs.test.ts +0 -155
  39. package/tests/repo.test.ts +0 -106
  40. package/tests/sync.test.ts +0 -95
  41. package/tsconfig.build.json +0 -8
  42. package/tsconfig.build.tsbuildinfo +0 -1
  43. package/tsconfig.json +0 -7
  44. package/tsconfig.tests.json +0 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atproto/repo
2
2
 
3
+ ## 0.10.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update TypeScript build to rely on references to composite internal projects
8
+
9
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Bundle only necessary files in the NPM tarball, including the `CHANGELOG.md` and `README.md` files (if present).
10
+
11
+ - Updated dependencies [[`28a0b58`](https://github.com/bluesky-social/atproto/commit/28a0b588147863eaef948cd2bb8fc0f19d08cda9), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07)]:
12
+ - @atproto/syntax@0.6.4
13
+ - @atproto/lex-cbor@0.1.3
14
+ - @atproto/lex-data@0.1.4
15
+ - @atproto/common-web@0.5.3
16
+ - @atproto/common@0.6.5
17
+ - @atproto/crypto@0.5.3
18
+
3
19
  ## 0.10.2
4
20
 
5
21
  ### Patch Changes
package/package.json CHANGED
@@ -1,34 +1,26 @@
1
1
  {
2
2
  "name": "@atproto/repo",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
+ "engines": {
5
+ "node": ">=22"
6
+ },
4
7
  "license": "MIT",
5
8
  "description": "atproto repo and MST implementation",
6
9
  "keywords": [
7
10
  "atproto",
8
11
  "mst"
9
12
  ],
10
- "engines": {
11
- "node": ">=22"
12
- },
13
13
  "homepage": "https://atproto.com",
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "https://github.com/bluesky-social/atproto",
17
17
  "directory": "packages/repo"
18
18
  },
19
- "dependencies": {
20
- "varint": "^6.0.0",
21
- "zod": "^3.23.8",
22
- "@atproto/common": "^0.6.4",
23
- "@atproto/common-web": "^0.5.2",
24
- "@atproto/crypto": "^0.5.2",
25
- "@atproto/lex-cbor": "^0.1.2",
26
- "@atproto/lex-data": "^0.1.3",
27
- "@atproto/syntax": "^0.6.3"
28
- },
29
- "devDependencies": {
30
- "jest": "^30.0.0"
31
- },
19
+ "files": [
20
+ "./dist",
21
+ "./README.md",
22
+ "./CHANGELOG.md"
23
+ ],
32
24
  "type": "module",
33
25
  "exports": {
34
26
  ".": {
@@ -36,6 +28,19 @@
36
28
  "default": "./dist/index.js"
37
29
  }
38
30
  },
31
+ "dependencies": {
32
+ "varint": "^6.0.0",
33
+ "zod": "^3.23.8",
34
+ "@atproto/common-web": "^0.5.3",
35
+ "@atproto/crypto": "^0.5.3",
36
+ "@atproto/lex-cbor": "^0.1.3",
37
+ "@atproto/syntax": "^0.6.4",
38
+ "@atproto/lex-data": "^0.1.4",
39
+ "@atproto/common": "^0.6.5"
40
+ },
41
+ "devDependencies": {
42
+ "jest": "^30.0.0"
43
+ },
39
44
  "scripts": {
40
45
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
41
46
  "test:profile": "node --experimental-vm-modules --inspect ../../node_modules/.bin/jest",
package/jest.config.cjs DELETED
@@ -1,24 +0,0 @@
1
- /** @type {import('jest').Config} */
2
- module.exports = {
3
- displayName: 'Repo',
4
- transform: {
5
- '^.+\\.(t|j)s$': [
6
- '@swc/jest',
7
- {
8
- jsc: {
9
- parser: { syntax: 'typescript', importAttributes: true },
10
- experimental: { keepImportAttributes: true },
11
- transform: {},
12
- },
13
- module: { type: 'es6' },
14
- },
15
- ],
16
- },
17
- extensionsToTreatAsEsm: ['.ts'],
18
- transformIgnorePatterns: [],
19
- setupFiles: ['<rootDir>/../../test.setup.ts'],
20
- moduleNameMapper: {
21
- '^varint$': '<rootDir>/../../jest.varint-shim.cjs',
22
- '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'],
23
- },
24
- }
package/src/block-map.ts DELETED
@@ -1,131 +0,0 @@
1
- import { encode } from '@atproto/lex-cbor'
2
- import {
3
- Cid,
4
- LexValue,
5
- cidForCbor,
6
- parseCid,
7
- ui8Equals,
8
- } from '@atproto/lex-data'
9
-
10
- export class BlockMap implements Iterable<[cid: Cid, bytes: Uint8Array]> {
11
- private map: Map<string, Uint8Array> = new Map()
12
-
13
- constructor(entries?: Iterable<readonly [cid: Cid, bytes: Uint8Array]>) {
14
- if (entries) {
15
- for (const [cid, bytes] of entries) {
16
- this.set(cid, bytes)
17
- }
18
- }
19
- }
20
-
21
- async add(value: LexValue): Promise<Cid> {
22
- const bytes = encode(value)
23
- const cid = await cidForCbor(bytes)
24
- this.set(cid, bytes)
25
- return cid
26
- }
27
-
28
- set(cid: Cid, bytes: Uint8Array): BlockMap {
29
- this.map.set(cid.toString(), bytes)
30
- return this
31
- }
32
-
33
- get(cid: Cid): Uint8Array | undefined {
34
- return this.map.get(cid.toString())
35
- }
36
-
37
- delete(cid: Cid): BlockMap {
38
- this.map.delete(cid.toString())
39
- return this
40
- }
41
-
42
- getMany(cids: Cid[]): { blocks: BlockMap; missing: Cid[] } {
43
- const missing: Cid[] = []
44
- const blocks = new BlockMap()
45
- for (const cid of cids) {
46
- const got = this.map.get(cid.toString())
47
- if (got) {
48
- blocks.set(cid, got)
49
- } else {
50
- missing.push(cid)
51
- }
52
- }
53
- return { blocks, missing }
54
- }
55
-
56
- has(cid: Cid): boolean {
57
- return this.map.has(cid.toString())
58
- }
59
-
60
- clear(): void {
61
- this.map.clear()
62
- }
63
-
64
- forEach(cb: (bytes: Uint8Array, cid: Cid) => void): void {
65
- for (const [cid, bytes] of this) cb(bytes, cid)
66
- }
67
-
68
- entries(): Entry[] {
69
- return Array.from(this, toEntry)
70
- }
71
-
72
- cids(): Cid[] {
73
- return Array.from(this.keys())
74
- }
75
-
76
- addMap(toAdd: BlockMap): BlockMap {
77
- for (const [cid, bytes] of toAdd) this.set(cid, bytes)
78
- return this
79
- }
80
-
81
- get size(): number {
82
- return this.map.size
83
- }
84
-
85
- get byteSize(): number {
86
- let size = 0
87
- for (const bytes of this.values()) size += bytes.length
88
- return size
89
- }
90
-
91
- equals(other: BlockMap): boolean {
92
- if (this.size !== other.size) {
93
- return false
94
- }
95
- for (const [cid, bytes] of this) {
96
- const otherBytes = other.get(cid)
97
- if (!otherBytes) return false
98
- if (!ui8Equals(bytes, otherBytes)) {
99
- return false
100
- }
101
- }
102
- return true
103
- }
104
-
105
- *keys(): Generator<Cid, void, unknown> {
106
- for (const key of this.map.keys()) {
107
- yield parseCid(key)
108
- }
109
- }
110
-
111
- *values(): Generator<Uint8Array, void, unknown> {
112
- yield* this.map.values()
113
- }
114
-
115
- *[Symbol.iterator](): Generator<[Cid, Uint8Array], void, unknown> {
116
- for (const [key, value] of this.map) {
117
- yield [parseCid(key), value]
118
- }
119
- }
120
- }
121
-
122
- function toEntry([cid, bytes]: readonly [Cid, Uint8Array]): Entry {
123
- return { cid, bytes }
124
- }
125
-
126
- type Entry = {
127
- cid: Cid
128
- bytes: Uint8Array
129
- }
130
-
131
- export default BlockMap
package/src/car.ts DELETED
@@ -1,357 +0,0 @@
1
- import { setImmediate } from 'node:timers/promises'
2
- // eslint-disable-next-line import/default, import/no-named-as-default-member
3
- import varint from 'varint'
4
- import * as cbor from '@atproto/lex-cbor'
5
- import { Cid, decodeCid, isCidForBytes } from '@atproto/lex-data'
6
- import { BlockMap } from './block-map.js'
7
- import { CarBlock, schema } from './types.js'
8
- import { concatBytesAsync } from './util.js'
9
-
10
- export async function* writeCarStream(
11
- root: Cid | null,
12
- blocks: AsyncIterable<CarBlock>,
13
- ): AsyncIterable<Uint8Array> {
14
- const header = new Uint8Array(
15
- cbor.encode({
16
- version: 1,
17
- roots: root ? [root] : [],
18
- }),
19
- )
20
- yield new Uint8Array(varint.encode(header.byteLength))
21
- yield header
22
- for await (const block of blocks) {
23
- yield new Uint8Array(
24
- varint.encode(block.cid.bytes.byteLength + block.bytes.byteLength),
25
- )
26
- yield block.cid.bytes
27
- yield block.bytes
28
- }
29
- }
30
-
31
- export async function blocksToCarFile(
32
- root: Cid | null,
33
- blocks: BlockMap,
34
- ): Promise<Uint8Array> {
35
- return concatBytesAsync(blocksToCarStream(root, blocks))
36
- }
37
-
38
- export const blocksToCarStream = (
39
- root: Cid | null,
40
- blocks: BlockMap,
41
- ): AsyncIterable<Uint8Array> => {
42
- return writeCarStream(root, iterateBlocks(blocks))
43
- }
44
-
45
- async function* iterateBlocks(blocks: BlockMap) {
46
- for (const entry of blocks.entries()) {
47
- yield { cid: entry.cid, bytes: entry.bytes }
48
- }
49
- }
50
-
51
- export type ReadCarOptions = {
52
- /**
53
- * When true, does not verify CID-to-content mapping within CAR.
54
- */
55
- skipCidVerification?: boolean
56
- }
57
-
58
- export const readCar = async (
59
- bytes: Uint8Array,
60
- opts?: ReadCarOptions,
61
- ): Promise<{ roots: Cid[]; blocks: BlockMap }> => {
62
- const { roots, blocks } = await readCarReader(new Ui8Reader(bytes), opts)
63
- const blockMap = new BlockMap()
64
- for await (const block of blocks) {
65
- blockMap.set(block.cid, block.bytes)
66
- }
67
- return { roots, blocks: blockMap }
68
- }
69
-
70
- export const readCarWithRoot = async (
71
- bytes: Uint8Array,
72
- opts?: ReadCarOptions,
73
- ): Promise<{ root: Cid; blocks: BlockMap }> => {
74
- const { roots, blocks } = await readCar(bytes, opts)
75
- if (roots.length !== 1) {
76
- throw new Error(`Expected one root, got ${roots.length}`)
77
- }
78
- const root = roots[0]
79
- return {
80
- root,
81
- blocks,
82
- }
83
- }
84
- export type CarBlockIterable = AsyncGenerator<CarBlock, void, unknown> & {
85
- dump: () => Promise<void>
86
- }
87
-
88
- export const readCarStream = async (
89
- car: Iterable<Uint8Array> | AsyncIterable<Uint8Array>,
90
- opts?: ReadCarOptions,
91
- ): Promise<{
92
- roots: Cid[]
93
- blocks: CarBlockIterable
94
- }> => {
95
- return readCarReader(new BufferedReader(car), opts)
96
- }
97
-
98
- export const readCarReader = async (
99
- reader: BytesReader,
100
- opts?: ReadCarOptions,
101
- ): Promise<{
102
- roots: Cid[]
103
- blocks: CarBlockIterable
104
- }> => {
105
- try {
106
- const headerSize = await readVarint(reader)
107
- if (headerSize === null) {
108
- throw new Error('Could not parse CAR header')
109
- }
110
- const headerBytes = await reader.read(headerSize)
111
- const header = cbor.decode(headerBytes)
112
- const result = schema.carHeader.safeParse(header)
113
- if (!result.success) {
114
- throw new Error('Could not parse CAR header', { cause: result.error })
115
- }
116
- return {
117
- roots: result.data.roots,
118
- blocks: readCarBlocksIter(reader, opts),
119
- }
120
- } catch (err) {
121
- await reader.close()
122
- throw err
123
- }
124
- }
125
-
126
- const readCarBlocksIter = (
127
- reader: BytesReader,
128
- opts?: ReadCarOptions,
129
- ): CarBlockIterable => {
130
- let generator = readCarBlocksIterGenerator(reader)
131
- if (!opts?.skipCidVerification) {
132
- generator = verifyIncomingCarBlocks(generator)
133
- }
134
- return Object.assign(generator, {
135
- async dump() {
136
- // try/finally to ensure that reader.close is called even if blocks.return throws.
137
- try {
138
- // Prevent the iterator from being started after this method is called.
139
- await generator.return()
140
- } finally {
141
- // @NOTE the "finally" block of the async generator won't be called
142
- // if the iteration was never started so we need to manually close here.
143
- await reader.close()
144
- }
145
- },
146
- })
147
- }
148
-
149
- async function* readCarBlocksIterGenerator(
150
- reader: BytesReader,
151
- ): AsyncGenerator<CarBlock, void, unknown> {
152
- let blocks = 0
153
- try {
154
- while (!reader.isDone) {
155
- const blockSize = await readVarint(reader)
156
- if (blockSize === null) {
157
- break
158
- }
159
- const blockBytes = await reader.read(blockSize)
160
- const cid = decodeCid(blockBytes.subarray(0, 36))
161
- const bytes = blockBytes.subarray(36)
162
- yield { cid, bytes }
163
-
164
- // yield to the event loop every 25 blocks
165
- // in the case the incoming CAR is synchronous, this can end up jamming up the thread
166
- blocks++
167
- if (blocks % 25 === 0) {
168
- await setImmediate()
169
- }
170
- }
171
- } finally {
172
- await reader.close()
173
- }
174
- }
175
-
176
- export async function* verifyIncomingCarBlocks(
177
- car: AsyncIterable<CarBlock>,
178
- ): AsyncGenerator<CarBlock, void, unknown> {
179
- for await (const block of car) {
180
- if (!(await isCidForBytes(block.cid, block.bytes))) {
181
- throw new Error(`Not a valid CID for bytes (${block.cid.toString()})`)
182
- }
183
- yield block
184
- }
185
- }
186
-
187
- const readVarint = async (reader: BytesReader): Promise<number | null> => {
188
- let done = false
189
- const bytes: Uint8Array[] = []
190
- while (!done) {
191
- const byte = await reader.read(1)
192
- if (byte.byteLength === 0) {
193
- if (bytes.length > 0) {
194
- throw new Error('could not parse varint')
195
- } else {
196
- return null
197
- }
198
- }
199
- bytes.push(byte)
200
- if (byte[0] < 128) {
201
- done = true
202
- }
203
- }
204
- const concatted = Buffer.concat(bytes)
205
- return varint.decode(concatted)
206
- }
207
-
208
- interface BytesReader {
209
- isDone: boolean
210
- read(bytesToRead: number): Promise<Uint8Array>
211
- close(): Promise<void>
212
- }
213
-
214
- class Ui8Reader implements BytesReader {
215
- idx = 0
216
- isDone = false
217
-
218
- constructor(public bytes: Uint8Array) {}
219
-
220
- async read(bytesToRead: number): Promise<Uint8Array> {
221
- const value = this.bytes.subarray(this.idx, this.idx + bytesToRead)
222
- this.idx += bytesToRead
223
- if (this.idx >= this.bytes.length) {
224
- this.isDone = true
225
- }
226
- return value
227
- }
228
-
229
- async close(): Promise<void> {}
230
- }
231
-
232
- /**
233
- * This code was optimized for performance. See
234
- * {@link https://github.com/bluesky-social/atproto/pull/4729 #4729} for more details
235
- * and benchmarks.
236
- */
237
- class BufferedReader implements BytesReader {
238
- iterator: Iterator<Uint8Array> | AsyncIterator<Uint8Array>
239
- isDone = false
240
-
241
- /** fifo list of chunks to consume */
242
- private chunks: Uint8Array[] = []
243
-
244
- constructor(stream: Iterable<Uint8Array> | AsyncIterable<Uint8Array>) {
245
- this.iterator =
246
- Symbol.asyncIterator in stream
247
- ? stream[Symbol.asyncIterator]()
248
- : stream[Symbol.iterator]()
249
- }
250
-
251
- /** Number of bytes currently buffered and available for reading */
252
- get bufferedByteLength() {
253
- let total = 0
254
- for (let i = 0; i < this.chunks.length; i++) {
255
- total += this.chunks[i].byteLength
256
- }
257
- return total
258
- }
259
-
260
- /**
261
- * @note concurrent reads are **NOT** supported by the current implementation
262
- * and would require call to readUntilBuffered to be using a fifo lock for
263
- * read()s to be processed in fifo order.
264
- */
265
- async read(bytesToRead: number): Promise<Uint8Array> {
266
- const bytesNeeded = bytesToRead - this.bufferedByteLength
267
- if (bytesNeeded > 0 && !this.isDone) {
268
- await this.readUntilBuffered(bytesNeeded)
269
- }
270
-
271
- const resultLength = Math.min(bytesToRead, this.bufferedByteLength)
272
- if (resultLength <= 0) return new Uint8Array()
273
-
274
- const firstChunk = this.consumeChunk(resultLength)
275
- if (firstChunk.byteLength === resultLength) {
276
- // If the data consumed from the first chunk contains all we need, return
277
- // it as-is. This allows to avoid any copy operation.
278
- return firstChunk
279
- }
280
-
281
- // The first chunk does not have all the data we need. We have to copy
282
- // multiple chunks into a larger buffer
283
- const result = new Uint8Array(resultLength)
284
- let resultWriteIndex = 0
285
-
286
- // Copy the first chunk into the result buffer
287
- result.set(firstChunk, resultWriteIndex)
288
- resultWriteIndex += firstChunk.byteLength
289
-
290
- // Copy more chunks as needed (we use do-while because we *know* we need
291
- // more than one chunk)
292
- do {
293
- const missingLength = resultLength - resultWriteIndex
294
- const currentChunk = this.consumeChunk(missingLength)
295
-
296
- result.set(currentChunk, resultWriteIndex)
297
- resultWriteIndex += currentChunk.byteLength
298
- } while (resultWriteIndex < resultLength)
299
-
300
- return result
301
- }
302
-
303
- private async readUntilBuffered(bytesNeeded: number) {
304
- let bytesRead = 0
305
- while (bytesRead < bytesNeeded) {
306
- const next = await this.iterator.next()
307
- if (next.done) {
308
- this.isDone = true
309
- break
310
- } else {
311
- this.chunks.push(next.value)
312
- bytesRead += next.value.byteLength
313
- }
314
- }
315
- return bytesRead
316
- }
317
-
318
- private consumeChunk(bytesToConsume: number) {
319
- const firstChunk = this.chunks[0]!
320
- if (bytesToConsume < firstChunk.byteLength) {
321
- // return a sub-view of the data being read and replace the first chunk
322
- // with a sub-view that does not contain that data.
323
-
324
- // @NOTE for some reason, subarray() revealed to be 7-8% slower in NodeJS
325
- // benchmarks.
326
-
327
- // this.chunks[0] = firstChunk.subarray(bytesToConsume)
328
- // return firstChunk.subarray(0, bytesToConsume)
329
-
330
- this.chunks[0] = new Uint8Array(
331
- firstChunk.buffer,
332
- firstChunk.byteOffset + bytesToConsume,
333
- firstChunk.byteLength - bytesToConsume,
334
- )
335
- return new Uint8Array(
336
- firstChunk.buffer,
337
- firstChunk.byteOffset,
338
- bytesToConsume,
339
- )
340
- } else {
341
- // First chunk is being read in full, discard it
342
- this.chunks.shift()
343
- return firstChunk
344
- }
345
- }
346
-
347
- async close(): Promise<void> {
348
- try {
349
- if (!this.isDone && this.iterator.return) {
350
- await this.iterator.return()
351
- }
352
- } finally {
353
- this.isDone = true
354
- this.chunks.length = 0
355
- }
356
- }
357
- }
package/src/cid-set.ts DELETED
@@ -1,55 +0,0 @@
1
- import { Cid, parseCid } from '@atproto/lex-data'
2
-
3
- export class CidSet implements Iterable<Cid> {
4
- private set: Set<string>
5
-
6
- constructor(arr: Cid[] = []) {
7
- const strArr = arr.map((c) => c.toString())
8
- this.set = new Set(strArr)
9
- }
10
-
11
- add(cid: Cid): CidSet {
12
- this.set.add(cid.toString())
13
- return this
14
- }
15
-
16
- addSet(toMerge: CidSet): CidSet {
17
- for (const c of toMerge.set) this.set.add(c)
18
- return this
19
- }
20
-
21
- subtractSet(toSubtract: CidSet): CidSet {
22
- for (const c of toSubtract.set) this.set.delete(c)
23
- return this
24
- }
25
-
26
- delete(cid: Cid) {
27
- this.set.delete(cid.toString())
28
- return this
29
- }
30
-
31
- has(cid: Cid): boolean {
32
- return this.set.has(cid.toString())
33
- }
34
-
35
- size(): number {
36
- return this.set.size
37
- }
38
-
39
- clear(): CidSet {
40
- this.set.clear()
41
- return this
42
- }
43
-
44
- toList(): Cid[] {
45
- return Array.from(this)
46
- }
47
-
48
- *[Symbol.iterator](): Generator<Cid, void, unknown> {
49
- for (const c of this.set) {
50
- yield parseCid(c)
51
- }
52
- }
53
- }
54
-
55
- export default CidSet