@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.
- package/CHANGELOG.md +16 -0
- package/package.json +22 -17
- package/jest.config.cjs +0 -24
- package/src/block-map.ts +0 -131
- package/src/car.ts +0 -357
- package/src/cid-set.ts +0 -55
- package/src/data-diff.ts +0 -117
- package/src/error.ts +0 -43
- package/src/index.ts +0 -11
- package/src/logger.ts +0 -7
- package/src/mst/diff.ts +0 -114
- package/src/mst/index.ts +0 -4
- package/src/mst/mst.ts +0 -892
- package/src/mst/util.ts +0 -160
- package/src/mst/walker.ts +0 -118
- package/src/parse.ts +0 -44
- package/src/readable-repo.ts +0 -86
- package/src/repo.ts +0 -236
- package/src/storage/index.ts +0 -4
- package/src/storage/memory-blockstore.ts +0 -76
- package/src/storage/readable-blockstore.ts +0 -55
- package/src/storage/sync-storage.ts +0 -35
- package/src/storage/types.ts +0 -47
- package/src/sync/consumer.ts +0 -207
- package/src/sync/index.ts +0 -2
- package/src/sync/provider.ts +0 -67
- package/src/types.ts +0 -227
- package/src/util.ts +0 -146
- package/tests/_keys.ts +0 -156
- package/tests/_util.ts +0 -265
- package/tests/car-file-fixtures.json +0 -28
- package/tests/car.test.ts +0 -125
- package/tests/commit-data.test.ts +0 -94
- package/tests/commit-proof-fixtures.json +0 -118
- package/tests/commit-proofs.test.ts +0 -63
- package/tests/covering-proofs.test.ts +0 -256
- package/tests/mst.test.ts +0 -450
- package/tests/proofs.test.ts +0 -155
- package/tests/repo.test.ts +0 -106
- package/tests/sync.test.ts +0 -95
- package/tsconfig.build.json +0 -8
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -7
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { Cid } from '@atproto/lex-data'
|
|
2
|
-
import { BlockMap } from '../block-map.js'
|
|
3
|
-
import { CommitData } from '../types.js'
|
|
4
|
-
import { ReadableBlockstore } from './readable-blockstore.js'
|
|
5
|
-
import { RepoStorage } from './types.js'
|
|
6
|
-
|
|
7
|
-
export class MemoryBlockstore
|
|
8
|
-
extends ReadableBlockstore
|
|
9
|
-
implements RepoStorage
|
|
10
|
-
{
|
|
11
|
-
blocks: BlockMap
|
|
12
|
-
root: Cid | null = null
|
|
13
|
-
rev: string | null = null
|
|
14
|
-
|
|
15
|
-
constructor(blocks?: BlockMap) {
|
|
16
|
-
super()
|
|
17
|
-
this.blocks = new BlockMap()
|
|
18
|
-
if (blocks) {
|
|
19
|
-
this.blocks.addMap(blocks)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async getRoot(): Promise<Cid | null> {
|
|
24
|
-
return this.root
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async getBytes(cid: Cid): Promise<Uint8Array | null> {
|
|
28
|
-
return this.blocks.get(cid) || null
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async has(cid: Cid): Promise<boolean> {
|
|
32
|
-
return this.blocks.has(cid)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async getBlocks(cids: Cid[]): Promise<{ blocks: BlockMap; missing: Cid[] }> {
|
|
36
|
-
return this.blocks.getMany(cids)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async putBlock(cid: Cid, block: Uint8Array): Promise<void> {
|
|
40
|
-
this.blocks.set(cid, block)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async putMany(blocks: BlockMap): Promise<void> {
|
|
44
|
-
this.blocks.addMap(blocks)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async updateRoot(cid: Cid, rev: string): Promise<void> {
|
|
48
|
-
this.root = cid
|
|
49
|
-
this.rev = rev
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async applyCommit(commit: CommitData): Promise<void> {
|
|
53
|
-
this.root = commit.cid
|
|
54
|
-
const rmCids = commit.removedCids.toList()
|
|
55
|
-
for (const cid of rmCids) {
|
|
56
|
-
this.blocks.delete(cid)
|
|
57
|
-
}
|
|
58
|
-
commit.newBlocks.forEach((bytes, cid) => {
|
|
59
|
-
this.blocks.set(cid, bytes)
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async sizeInBytes(): Promise<number> {
|
|
64
|
-
let total = 0
|
|
65
|
-
this.blocks.forEach((bytes) => {
|
|
66
|
-
total += bytes.byteLength
|
|
67
|
-
})
|
|
68
|
-
return total
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async destroy(): Promise<void> {
|
|
72
|
-
this.blocks.clear()
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export default MemoryBlockstore
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { check } from '@atproto/common-web'
|
|
2
|
-
import { Cid, LexMap } from '@atproto/lex-data'
|
|
3
|
-
import { BlockMap } from '../block-map.js'
|
|
4
|
-
import { MissingBlockError } from '../error.js'
|
|
5
|
-
import { parseObjByDef } from '../parse.js'
|
|
6
|
-
import { cborToLexRecord } from '../util.js'
|
|
7
|
-
|
|
8
|
-
export abstract class ReadableBlockstore {
|
|
9
|
-
abstract getBytes(cid: Cid): Promise<Uint8Array | null>
|
|
10
|
-
abstract has(cid: Cid): Promise<boolean>
|
|
11
|
-
abstract getBlocks(cids: Cid[]): Promise<{ blocks: BlockMap; missing: Cid[] }>
|
|
12
|
-
|
|
13
|
-
async attemptRead<T>(
|
|
14
|
-
cid: Cid,
|
|
15
|
-
def: check.Def<T>,
|
|
16
|
-
): Promise<{ obj: T; bytes: Uint8Array } | null> {
|
|
17
|
-
const bytes = await this.getBytes(cid)
|
|
18
|
-
if (!bytes) return null
|
|
19
|
-
return parseObjByDef(bytes, cid, def)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async readObjAndBytes<T>(
|
|
23
|
-
cid: Cid,
|
|
24
|
-
def: check.Def<T>,
|
|
25
|
-
): Promise<{ obj: T; bytes: Uint8Array }> {
|
|
26
|
-
const read = await this.attemptRead(cid, def)
|
|
27
|
-
if (!read) {
|
|
28
|
-
throw new MissingBlockError(cid, def.name)
|
|
29
|
-
}
|
|
30
|
-
return read
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async readObj<T>(cid: Cid, def: check.Def<T>): Promise<T> {
|
|
34
|
-
const obj = await this.readObjAndBytes(cid, def)
|
|
35
|
-
return obj.obj
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async attemptReadRecord(cid: Cid): Promise<LexMap | null> {
|
|
39
|
-
try {
|
|
40
|
-
return await this.readRecord(cid)
|
|
41
|
-
} catch {
|
|
42
|
-
return null
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async readRecord(cid: Cid): Promise<LexMap> {
|
|
47
|
-
const bytes = await this.getBytes(cid)
|
|
48
|
-
if (!bytes) {
|
|
49
|
-
throw new MissingBlockError(cid)
|
|
50
|
-
}
|
|
51
|
-
return cborToLexRecord(bytes)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export default ReadableBlockstore
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Cid } from '@atproto/lex-data'
|
|
2
|
-
import { BlockMap } from '../block-map.js'
|
|
3
|
-
import { ReadableBlockstore } from './readable-blockstore.js'
|
|
4
|
-
|
|
5
|
-
export class SyncStorage extends ReadableBlockstore {
|
|
6
|
-
constructor(
|
|
7
|
-
public staged: ReadableBlockstore,
|
|
8
|
-
public saved: ReadableBlockstore,
|
|
9
|
-
) {
|
|
10
|
-
super()
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async getBytes(cid: Cid): Promise<Uint8Array | null> {
|
|
14
|
-
const got = await this.staged.getBytes(cid)
|
|
15
|
-
if (got) return got
|
|
16
|
-
return this.saved.getBytes(cid)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async getBlocks(cids: Cid[]): Promise<{ blocks: BlockMap; missing: Cid[] }> {
|
|
20
|
-
const fromStaged = await this.staged.getBlocks(cids)
|
|
21
|
-
const fromSaved = await this.saved.getBlocks(fromStaged.missing)
|
|
22
|
-
const blocks = fromStaged.blocks
|
|
23
|
-
blocks.addMap(fromSaved.blocks)
|
|
24
|
-
return {
|
|
25
|
-
blocks,
|
|
26
|
-
missing: fromSaved.missing,
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async has(cid: Cid): Promise<boolean> {
|
|
31
|
-
return (await this.staged.has(cid)) || (await this.saved.has(cid))
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default SyncStorage
|
package/src/storage/types.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { Readable } from 'node:stream'
|
|
2
|
-
import { check } from '@atproto/common-web'
|
|
3
|
-
import { Cid, LexMap } from '@atproto/lex-data'
|
|
4
|
-
import { BlockMap } from '../block-map.js'
|
|
5
|
-
import { CommitData } from '../types.js'
|
|
6
|
-
|
|
7
|
-
export interface RepoStorage {
|
|
8
|
-
// Writable
|
|
9
|
-
getRoot(): Promise<Cid | null>
|
|
10
|
-
putBlock(cid: Cid, block: Uint8Array, rev: string): Promise<void>
|
|
11
|
-
putMany(blocks: BlockMap, rev: string): Promise<void>
|
|
12
|
-
updateRoot(cid: Cid, rev: string): Promise<void>
|
|
13
|
-
applyCommit(commit: CommitData)
|
|
14
|
-
|
|
15
|
-
// Readable
|
|
16
|
-
getBytes(cid: Cid): Promise<Uint8Array | null>
|
|
17
|
-
has(cid: Cid): Promise<boolean>
|
|
18
|
-
getBlocks(cids: Cid[]): Promise<{ blocks: BlockMap; missing: Cid[] }>
|
|
19
|
-
attemptRead<T>(
|
|
20
|
-
cid: Cid,
|
|
21
|
-
def: check.Def<T>,
|
|
22
|
-
): Promise<{ obj: T; bytes: Uint8Array } | null>
|
|
23
|
-
readObjAndBytes<T>(
|
|
24
|
-
cid: Cid,
|
|
25
|
-
def: check.Def<T>,
|
|
26
|
-
): Promise<{ obj: T; bytes: Uint8Array }>
|
|
27
|
-
readObj<T>(cid: Cid, def: check.Def<T>): Promise<T>
|
|
28
|
-
attemptReadRecord(cid: Cid): Promise<LexMap | null>
|
|
29
|
-
readRecord(cid: Cid): Promise<LexMap>
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// @TODO make this less node-js specific by using AsyncIterable<Uint8Array> instead of Readable
|
|
33
|
-
export interface BlobStore {
|
|
34
|
-
putTemp(bytes: Uint8Array | Readable): Promise<string>
|
|
35
|
-
makePermanent(key: string, cid: Cid): Promise<void>
|
|
36
|
-
putPermanent(cid: Cid, bytes: Uint8Array | Readable): Promise<void>
|
|
37
|
-
quarantine(cid: Cid): Promise<void>
|
|
38
|
-
unquarantine(cid: Cid): Promise<void>
|
|
39
|
-
getBytes(cid: Cid): Promise<Uint8Array>
|
|
40
|
-
getStream(cid: Cid): Promise<Readable>
|
|
41
|
-
hasTemp(key: string): Promise<boolean>
|
|
42
|
-
hasStored(cid: Cid): Promise<boolean>
|
|
43
|
-
delete(cid: Cid): Promise<void>
|
|
44
|
-
deleteMany(cid: Cid[]): Promise<void>
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export class BlobNotFoundError extends Error {}
|
package/src/sync/consumer.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { Cid } from '@atproto/lex-data'
|
|
2
|
-
import { BlockMap } from '../block-map.js'
|
|
3
|
-
import { readCarWithRoot } from '../car.js'
|
|
4
|
-
import { DataDiff } from '../data-diff.js'
|
|
5
|
-
import { MST } from '../mst/index.js'
|
|
6
|
-
import { ReadableRepo } from '../readable-repo.js'
|
|
7
|
-
import {
|
|
8
|
-
MemoryBlockstore,
|
|
9
|
-
ReadableBlockstore,
|
|
10
|
-
SyncStorage,
|
|
11
|
-
} from '../storage/index.js'
|
|
12
|
-
import {
|
|
13
|
-
RecordCidClaim,
|
|
14
|
-
RecordClaim,
|
|
15
|
-
VerifiedDiff,
|
|
16
|
-
VerifiedRepo,
|
|
17
|
-
def,
|
|
18
|
-
} from '../types.js'
|
|
19
|
-
import * as util from '../util.js'
|
|
20
|
-
|
|
21
|
-
export const verifyRepoCar = async (
|
|
22
|
-
carBytes: Uint8Array,
|
|
23
|
-
did?: string,
|
|
24
|
-
signingKey?: string,
|
|
25
|
-
): Promise<VerifiedRepo> => {
|
|
26
|
-
const car = await readCarWithRoot(carBytes)
|
|
27
|
-
return verifyRepo(car.blocks, car.root, did, signingKey)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const verifyRepo = async (
|
|
31
|
-
blocks: BlockMap,
|
|
32
|
-
head: Cid,
|
|
33
|
-
did?: string,
|
|
34
|
-
signingKey?: string,
|
|
35
|
-
opts?: { ensureLeaves?: boolean },
|
|
36
|
-
): Promise<VerifiedRepo> => {
|
|
37
|
-
const diff = await verifyDiff(null, blocks, head, did, signingKey, opts)
|
|
38
|
-
const creates = util.ensureCreates(diff.writes)
|
|
39
|
-
return {
|
|
40
|
-
creates,
|
|
41
|
-
commit: diff.commit,
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const verifyDiffCar = async (
|
|
46
|
-
repo: ReadableRepo | null,
|
|
47
|
-
carBytes: Uint8Array,
|
|
48
|
-
did?: string,
|
|
49
|
-
signingKey?: string,
|
|
50
|
-
opts?: { ensureLeaves?: boolean },
|
|
51
|
-
): Promise<VerifiedDiff> => {
|
|
52
|
-
const car = await readCarWithRoot(carBytes)
|
|
53
|
-
return verifyDiff(repo, car.blocks, car.root, did, signingKey, opts)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const verifyDiff = async (
|
|
57
|
-
repo: ReadableRepo | null,
|
|
58
|
-
updateBlocks: BlockMap,
|
|
59
|
-
updateRoot: Cid,
|
|
60
|
-
did?: string,
|
|
61
|
-
signingKey?: string,
|
|
62
|
-
opts?: { ensureLeaves?: boolean },
|
|
63
|
-
): Promise<VerifiedDiff> => {
|
|
64
|
-
const { ensureLeaves = true } = opts ?? {}
|
|
65
|
-
const stagedStorage = new MemoryBlockstore(updateBlocks)
|
|
66
|
-
const updateStorage = repo
|
|
67
|
-
? new SyncStorage(stagedStorage, repo.storage)
|
|
68
|
-
: stagedStorage
|
|
69
|
-
const updated = await verifyRepoRoot(
|
|
70
|
-
updateStorage,
|
|
71
|
-
updateRoot,
|
|
72
|
-
did,
|
|
73
|
-
signingKey,
|
|
74
|
-
)
|
|
75
|
-
const diff = await DataDiff.of(updated.data, repo?.data ?? null)
|
|
76
|
-
const writes = await util.diffToWriteDescripts(diff)
|
|
77
|
-
const newBlocks = diff.newMstBlocks
|
|
78
|
-
const leaves = updateBlocks.getMany(diff.newLeafCids.toList())
|
|
79
|
-
if (leaves.missing.length > 0 && ensureLeaves) {
|
|
80
|
-
throw new Error(`missing leaf blocks: ${leaves.missing}`)
|
|
81
|
-
}
|
|
82
|
-
newBlocks.addMap(leaves.blocks)
|
|
83
|
-
const removedCids = diff.removedCids
|
|
84
|
-
const commitCid = await newBlocks.add(updated.commit)
|
|
85
|
-
// ensure the commit cid actually changed
|
|
86
|
-
if (repo) {
|
|
87
|
-
if (commitCid.equals(repo.cid)) {
|
|
88
|
-
newBlocks.delete(commitCid)
|
|
89
|
-
} else {
|
|
90
|
-
removedCids.add(repo.cid)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return {
|
|
94
|
-
writes,
|
|
95
|
-
commit: {
|
|
96
|
-
cid: updated.cid,
|
|
97
|
-
rev: updated.commit.rev,
|
|
98
|
-
prev: repo?.cid ?? null,
|
|
99
|
-
since: repo?.commit.rev ?? null,
|
|
100
|
-
newBlocks,
|
|
101
|
-
relevantBlocks: newBlocks,
|
|
102
|
-
removedCids,
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// @NOTE only verifies the root, not the repo contents
|
|
108
|
-
const verifyRepoRoot = async (
|
|
109
|
-
storage: ReadableBlockstore,
|
|
110
|
-
head: Cid,
|
|
111
|
-
did?: string,
|
|
112
|
-
signingKey?: string,
|
|
113
|
-
): Promise<ReadableRepo> => {
|
|
114
|
-
const repo = await ReadableRepo.load(storage, head)
|
|
115
|
-
if (did !== undefined && repo.did !== did) {
|
|
116
|
-
throw new RepoVerificationError(`Invalid repo did: ${repo.did}`)
|
|
117
|
-
}
|
|
118
|
-
if (signingKey !== undefined) {
|
|
119
|
-
const validSig = await util.verifyCommitSig(repo.commit, signingKey)
|
|
120
|
-
if (!validSig) {
|
|
121
|
-
throw new RepoVerificationError(
|
|
122
|
-
`Invalid signature on commit: ${repo.cid.toString()}`,
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return repo
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export const verifyProofs = async (
|
|
130
|
-
proofs: Uint8Array,
|
|
131
|
-
claims: RecordCidClaim[],
|
|
132
|
-
did: string,
|
|
133
|
-
didKey: string,
|
|
134
|
-
): Promise<{ verified: RecordCidClaim[]; unverified: RecordCidClaim[] }> => {
|
|
135
|
-
const car = await readCarWithRoot(proofs)
|
|
136
|
-
const blockstore = new MemoryBlockstore(car.blocks)
|
|
137
|
-
const commit = await blockstore.readObj(car.root, def.commit)
|
|
138
|
-
if (commit.did !== did) {
|
|
139
|
-
throw new RepoVerificationError(`Invalid repo did: ${commit.did}`)
|
|
140
|
-
}
|
|
141
|
-
const validSig = await util.verifyCommitSig(commit, didKey)
|
|
142
|
-
if (!validSig) {
|
|
143
|
-
throw new RepoVerificationError(
|
|
144
|
-
`Invalid signature on commit: ${car.root.toString()}`,
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
const mst = MST.load(blockstore, commit.data)
|
|
148
|
-
const verified: RecordCidClaim[] = []
|
|
149
|
-
const unverified: RecordCidClaim[] = []
|
|
150
|
-
for (const claim of claims) {
|
|
151
|
-
const found = await mst.get(
|
|
152
|
-
util.formatDataKey(claim.collection, claim.rkey),
|
|
153
|
-
)
|
|
154
|
-
const record = found ? await blockstore.readObj(found, def.map) : null
|
|
155
|
-
if (claim.cid === null) {
|
|
156
|
-
if (record === null) {
|
|
157
|
-
verified.push(claim)
|
|
158
|
-
} else {
|
|
159
|
-
unverified.push(claim)
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
if (found?.equals(claim.cid)) {
|
|
163
|
-
verified.push(claim)
|
|
164
|
-
} else {
|
|
165
|
-
unverified.push(claim)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return { verified, unverified }
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export const verifyRecords = async (
|
|
173
|
-
proofs: Uint8Array,
|
|
174
|
-
did: string,
|
|
175
|
-
signingKey: string,
|
|
176
|
-
): Promise<RecordClaim[]> => {
|
|
177
|
-
const car = await readCarWithRoot(proofs)
|
|
178
|
-
const blockstore = new MemoryBlockstore(car.blocks)
|
|
179
|
-
const commit = await blockstore.readObj(car.root, def.commit)
|
|
180
|
-
if (commit.did !== did) {
|
|
181
|
-
throw new RepoVerificationError(`Invalid repo did: ${commit.did}`)
|
|
182
|
-
}
|
|
183
|
-
const validSig = await util.verifyCommitSig(commit, signingKey)
|
|
184
|
-
if (!validSig) {
|
|
185
|
-
throw new RepoVerificationError(
|
|
186
|
-
`Invalid signature on commit: ${car.root.toString()}`,
|
|
187
|
-
)
|
|
188
|
-
}
|
|
189
|
-
const mst = MST.load(blockstore, commit.data)
|
|
190
|
-
|
|
191
|
-
const records: RecordClaim[] = []
|
|
192
|
-
const leaves = await mst.reachableLeaves()
|
|
193
|
-
for (const leaf of leaves) {
|
|
194
|
-
const { collection, rkey } = util.parseDataKey(leaf.key)
|
|
195
|
-
const record = await blockstore.attemptReadRecord(leaf.value)
|
|
196
|
-
if (record) {
|
|
197
|
-
records.push({
|
|
198
|
-
collection,
|
|
199
|
-
rkey,
|
|
200
|
-
record,
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return records
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export class RepoVerificationError extends Error {}
|
package/src/sync/index.ts
DELETED
package/src/sync/provider.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Cid } from '@atproto/lex-data'
|
|
2
|
-
import { writeCarStream } from '../car.js'
|
|
3
|
-
import { CidSet } from '../cid-set.js'
|
|
4
|
-
import { MissingBlocksError } from '../error.js'
|
|
5
|
-
import { MST } from '../mst/index.js'
|
|
6
|
-
import { ReadableBlockstore, RepoStorage } from '../storage/index.js'
|
|
7
|
-
import { CarBlock, RecordPath, def } from '../types.js'
|
|
8
|
-
import * as util from '../util.js'
|
|
9
|
-
|
|
10
|
-
// Full Repo
|
|
11
|
-
// -------------
|
|
12
|
-
|
|
13
|
-
export const getFullRepo = (
|
|
14
|
-
storage: RepoStorage,
|
|
15
|
-
commitCid: Cid,
|
|
16
|
-
): AsyncIterable<Uint8Array> => {
|
|
17
|
-
return writeCarStream(commitCid, iterateFullRepo(storage, commitCid))
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function* iterateFullRepo(
|
|
21
|
-
storage: RepoStorage,
|
|
22
|
-
commitCid: Cid,
|
|
23
|
-
): AsyncGenerator<CarBlock> {
|
|
24
|
-
const commit = await storage.readObjAndBytes(commitCid, def.commit)
|
|
25
|
-
yield { cid: commitCid, bytes: commit.bytes }
|
|
26
|
-
const mst = MST.load(storage, commit.obj.data)
|
|
27
|
-
for await (const block of mst.carBlockStream()) {
|
|
28
|
-
yield block
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Narrow slices
|
|
33
|
-
// -------------
|
|
34
|
-
|
|
35
|
-
export const getRecords = (
|
|
36
|
-
storage: ReadableBlockstore,
|
|
37
|
-
commitCid: Cid,
|
|
38
|
-
paths: RecordPath[],
|
|
39
|
-
): AsyncIterable<Uint8Array> => {
|
|
40
|
-
return writeCarStream(
|
|
41
|
-
commitCid,
|
|
42
|
-
iterateRecordBlocks(storage, commitCid, paths),
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function* iterateRecordBlocks(
|
|
47
|
-
storage: ReadableBlockstore,
|
|
48
|
-
commitCid: Cid,
|
|
49
|
-
paths: RecordPath[],
|
|
50
|
-
): AsyncGenerator<CarBlock> {
|
|
51
|
-
const commit = await storage.readObjAndBytes(commitCid, def.commit)
|
|
52
|
-
yield { cid: commitCid, bytes: commit.bytes }
|
|
53
|
-
const mst = MST.load(storage, commit.obj.data)
|
|
54
|
-
const cidsForPaths = await Promise.all(
|
|
55
|
-
paths.map((p) => mst.cidsForPath(util.formatDataKey(p.collection, p.rkey))),
|
|
56
|
-
)
|
|
57
|
-
const allCids = cidsForPaths.reduce((acc, cur) => {
|
|
58
|
-
return acc.addSet(new CidSet(cur))
|
|
59
|
-
}, new CidSet())
|
|
60
|
-
const found = await storage.getBlocks(allCids.toList())
|
|
61
|
-
if (found.missing.length > 0) {
|
|
62
|
-
throw new MissingBlocksError('writeRecordsToCarStream', found.missing)
|
|
63
|
-
}
|
|
64
|
-
for (const block of found.blocks.entries()) {
|
|
65
|
-
yield block
|
|
66
|
-
}
|
|
67
|
-
}
|