@atproto/repo 0.0.1 → 0.1.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.
- package/bench/mst.bench.ts +7 -4
- package/bench/repo.bench.ts +25 -16
- package/dist/block-map.d.ts +25 -0
- package/dist/data-diff.d.ts +36 -0
- package/dist/error.d.ts +20 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +11605 -10399
- package/dist/index.js.map +4 -4
- package/dist/mst/diff.d.ts +4 -33
- package/dist/mst/mst.d.ts +68 -25
- package/dist/mst/util.d.ts +13 -5
- package/dist/parse.d.ts +16 -0
- package/dist/readable-repo.d.ts +22 -0
- package/dist/repo.d.ts +14 -30
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/memory-blockstore.d.ts +28 -0
- package/dist/storage/readable-blockstore.d.ts +24 -0
- package/dist/storage/repo-storage.d.ts +18 -0
- package/dist/storage/sync-storage.d.ts +15 -0
- package/dist/storage/types.d.ts +3 -0
- package/dist/sync/consumer.d.ts +18 -0
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/provider.d.ts +9 -0
- package/dist/types.d.ts +124 -317
- package/dist/util.d.ts +31 -12
- package/dist/verify.d.ts +26 -4
- package/package.json +4 -2
- package/src/block-map.ts +95 -0
- package/src/cid-set.ts +1 -2
- package/src/data-diff.ts +121 -0
- package/src/error.ts +31 -0
- package/src/index.ts +3 -1
- package/src/mst/diff.ts +120 -90
- package/src/mst/mst.ts +185 -184
- package/src/mst/util.ts +54 -31
- package/src/parse.ts +44 -0
- package/src/readable-repo.ts +75 -0
- package/src/repo.ts +119 -249
- package/src/storage/index.ts +4 -0
- package/src/storage/memory-blockstore.ts +114 -0
- package/src/storage/readable-blockstore.ts +56 -0
- package/src/storage/repo-storage.ts +42 -0
- package/src/storage/sync-storage.ts +35 -0
- package/src/storage/types.ts +3 -0
- package/src/sync/consumer.ts +137 -0
- package/src/sync/index.ts +2 -0
- package/src/sync/provider.ts +91 -0
- package/src/types.ts +101 -62
- package/src/util.ts +237 -56
- package/src/verify.ts +207 -42
- package/tests/_util.ts +132 -97
- package/tests/mst.test.ts +269 -122
- package/tests/repo.test.ts +48 -50
- package/tests/sync/checkout.test.ts +57 -0
- package/tests/sync/diff.test.ts +87 -0
- package/tests/sync/narrow.test.ts +145 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.json +2 -1
- package/src/blockstore/index.ts +0 -2
- package/src/blockstore/ipld-store.ts +0 -103
- package/src/blockstore/memory-blockstore.ts +0 -49
- package/src/sync.ts +0 -38
- package/tests/sync.test.ts +0 -129
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { check } from '@atproto/common'
|
|
2
|
+
import { RepoRecord } from '@atproto/lexicon'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
4
|
+
import BlockMap from '../block-map'
|
|
5
|
+
import { MissingBlockError } from '../error'
|
|
6
|
+
import * as parse from '../parse'
|
|
7
|
+
import { cborToLexRecord } from '../util'
|
|
8
|
+
|
|
9
|
+
export abstract class ReadableBlockstore {
|
|
10
|
+
abstract getBytes(cid: CID): Promise<Uint8Array | null>
|
|
11
|
+
abstract has(cid: CID): Promise<boolean>
|
|
12
|
+
abstract getBlocks(cids: CID[]): Promise<{ blocks: BlockMap; missing: CID[] }>
|
|
13
|
+
|
|
14
|
+
async attemptRead<T>(
|
|
15
|
+
cid: CID,
|
|
16
|
+
def: check.Def<T>,
|
|
17
|
+
): Promise<{ obj: T; bytes: Uint8Array } | null> {
|
|
18
|
+
const bytes = await this.getBytes(cid)
|
|
19
|
+
if (!bytes) return null
|
|
20
|
+
return parse.parseObjByDef(bytes, cid, def)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async readObjAndBytes<T>(
|
|
24
|
+
cid: CID,
|
|
25
|
+
def: check.Def<T>,
|
|
26
|
+
): Promise<{ obj: T; bytes: Uint8Array }> {
|
|
27
|
+
const read = await this.attemptRead(cid, def)
|
|
28
|
+
if (!read) {
|
|
29
|
+
throw new MissingBlockError(cid, def.name)
|
|
30
|
+
}
|
|
31
|
+
return read
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async readObj<T>(cid: CID, def: check.Def<T>): Promise<T> {
|
|
35
|
+
const obj = await this.readObjAndBytes(cid, def)
|
|
36
|
+
return obj.obj
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async attemptReadRecord(cid: CID): Promise<RepoRecord | null> {
|
|
40
|
+
try {
|
|
41
|
+
return await this.readRecord(cid)
|
|
42
|
+
} catch {
|
|
43
|
+
return null
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async readRecord(cid: CID): Promise<RepoRecord> {
|
|
48
|
+
const bytes = await this.getBytes(cid)
|
|
49
|
+
if (!bytes) {
|
|
50
|
+
throw new MissingBlockError(cid)
|
|
51
|
+
}
|
|
52
|
+
return cborToLexRecord(bytes)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default ReadableBlockstore
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid'
|
|
2
|
+
import BlockMap from '../block-map'
|
|
3
|
+
import { CommitBlockData, CommitData } from '../types'
|
|
4
|
+
import ReadableBlockstore from './readable-blockstore'
|
|
5
|
+
|
|
6
|
+
export abstract class RepoStorage extends ReadableBlockstore {
|
|
7
|
+
abstract getHead(forUpdate?: boolean): Promise<CID | null>
|
|
8
|
+
abstract getCommitPath(
|
|
9
|
+
latest: CID,
|
|
10
|
+
earliest: CID | null,
|
|
11
|
+
): Promise<CID[] | null>
|
|
12
|
+
abstract getBlocksForCommits(
|
|
13
|
+
commits: CID[],
|
|
14
|
+
): Promise<{ [commit: string]: BlockMap }>
|
|
15
|
+
|
|
16
|
+
abstract putBlock(cid: CID, block: Uint8Array): Promise<void>
|
|
17
|
+
abstract putMany(blocks: BlockMap): Promise<void>
|
|
18
|
+
abstract updateHead(cid: CID, prev: CID | null): Promise<void>
|
|
19
|
+
abstract indexCommits(commit: CommitData[]): Promise<void>
|
|
20
|
+
|
|
21
|
+
async applyCommit(commit: CommitData): Promise<void> {
|
|
22
|
+
await Promise.all([
|
|
23
|
+
this.indexCommits([commit]),
|
|
24
|
+
this.updateHead(commit.commit, commit.prev),
|
|
25
|
+
])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getCommits(
|
|
29
|
+
latest: CID,
|
|
30
|
+
earliest: CID | null,
|
|
31
|
+
): Promise<CommitBlockData[] | null> {
|
|
32
|
+
const commitPath = await this.getCommitPath(latest, earliest)
|
|
33
|
+
if (!commitPath) return null
|
|
34
|
+
const blocksByCommit = await this.getBlocksForCommits(commitPath)
|
|
35
|
+
return commitPath.map((commit) => ({
|
|
36
|
+
commit,
|
|
37
|
+
blocks: blocksByCommit[commit.toString()] || new BlockMap(),
|
|
38
|
+
}))
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default RepoStorage
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid'
|
|
2
|
+
import BlockMap from '../block-map'
|
|
3
|
+
import ReadableBlockstore from './readable-blockstore'
|
|
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
CHANGED
|
@@ -5,8 +5,11 @@ export interface BlobStore {
|
|
|
5
5
|
putTemp(bytes: Uint8Array | stream.Readable): Promise<string>
|
|
6
6
|
makePermanent(key: string, cid: CID): Promise<void>
|
|
7
7
|
putPermanent(cid: CID, bytes: Uint8Array | stream.Readable): Promise<void>
|
|
8
|
+
quarantine(cid: CID): Promise<void>
|
|
9
|
+
unquarantine(cid: CID): Promise<void>
|
|
8
10
|
getBytes(cid: CID): Promise<Uint8Array>
|
|
9
11
|
getStream(cid: CID): Promise<stream.Readable>
|
|
12
|
+
delete(cid: CID): Promise<void>
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export class BlobNotFoundError extends Error {}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid'
|
|
2
|
+
import { MemoryBlockstore, RepoStorage } from '../storage'
|
|
3
|
+
import Repo from '../repo'
|
|
4
|
+
import * as verify from '../verify'
|
|
5
|
+
import * as util from '../util'
|
|
6
|
+
import { CommitData, RepoContents, WriteLog } from '../types'
|
|
7
|
+
import CidSet from '../cid-set'
|
|
8
|
+
import { MissingBlocksError } from '../error'
|
|
9
|
+
|
|
10
|
+
// Checkouts
|
|
11
|
+
// -------------
|
|
12
|
+
|
|
13
|
+
export const loadCheckout = async (
|
|
14
|
+
storage: RepoStorage,
|
|
15
|
+
repoCar: Uint8Array,
|
|
16
|
+
did: string,
|
|
17
|
+
signingKey: string,
|
|
18
|
+
): Promise<{ root: CID; contents: RepoContents }> => {
|
|
19
|
+
const { root, blocks } = await util.readCarWithRoot(repoCar)
|
|
20
|
+
const updateStorage = new MemoryBlockstore(blocks)
|
|
21
|
+
const checkout = await verify.verifyCheckout(
|
|
22
|
+
updateStorage,
|
|
23
|
+
root,
|
|
24
|
+
did,
|
|
25
|
+
signingKey,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
const checkoutBlocks = await updateStorage.getBlocks(
|
|
29
|
+
checkout.newCids.toList(),
|
|
30
|
+
)
|
|
31
|
+
if (checkoutBlocks.missing.length > 0) {
|
|
32
|
+
throw new MissingBlocksError('sync', checkoutBlocks.missing)
|
|
33
|
+
}
|
|
34
|
+
await Promise.all([
|
|
35
|
+
storage.putMany(checkoutBlocks.blocks),
|
|
36
|
+
storage.updateHead(root, null),
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
root,
|
|
41
|
+
contents: checkout.contents,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Diffs
|
|
46
|
+
// -------------
|
|
47
|
+
|
|
48
|
+
export const loadFullRepo = async (
|
|
49
|
+
storage: RepoStorage,
|
|
50
|
+
repoCar: Uint8Array,
|
|
51
|
+
did: string,
|
|
52
|
+
signingKey: string,
|
|
53
|
+
): Promise<{ root: CID; writeLog: WriteLog }> => {
|
|
54
|
+
const { root, blocks } = await util.readCarWithRoot(repoCar)
|
|
55
|
+
const updateStorage = new MemoryBlockstore(blocks)
|
|
56
|
+
const updates = await verify.verifyFullHistory(
|
|
57
|
+
updateStorage,
|
|
58
|
+
root,
|
|
59
|
+
did,
|
|
60
|
+
signingKey,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
const [writeLog] = await Promise.all([
|
|
64
|
+
persistUpdates(storage, updateStorage, updates),
|
|
65
|
+
storage.updateHead(root, null),
|
|
66
|
+
])
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
root,
|
|
70
|
+
writeLog,
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const loadDiff = async (
|
|
75
|
+
repo: Repo,
|
|
76
|
+
diffCar: Uint8Array,
|
|
77
|
+
did: string,
|
|
78
|
+
signingKey: string,
|
|
79
|
+
): Promise<{ root: CID; writeLog: WriteLog }> => {
|
|
80
|
+
const { root, blocks } = await util.readCarWithRoot(diffCar)
|
|
81
|
+
const updateStorage = new MemoryBlockstore(blocks)
|
|
82
|
+
const updates = await verify.verifyUpdates(
|
|
83
|
+
repo,
|
|
84
|
+
updateStorage,
|
|
85
|
+
root,
|
|
86
|
+
did,
|
|
87
|
+
signingKey,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
const [writeLog] = await Promise.all([
|
|
91
|
+
persistUpdates(repo.storage, updateStorage, updates),
|
|
92
|
+
repo.storage.updateHead(root, repo.cid),
|
|
93
|
+
])
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
root,
|
|
97
|
+
writeLog,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Helpers
|
|
102
|
+
// -------------
|
|
103
|
+
|
|
104
|
+
export const persistUpdates = async (
|
|
105
|
+
storage: RepoStorage,
|
|
106
|
+
updateStorage: RepoStorage,
|
|
107
|
+
updates: verify.VerifiedUpdate[],
|
|
108
|
+
): Promise<WriteLog> => {
|
|
109
|
+
const newCids = new CidSet()
|
|
110
|
+
for (const update of updates) {
|
|
111
|
+
newCids.addSet(update.newCids)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const diffBlocks = await updateStorage.getBlocks(newCids.toList())
|
|
115
|
+
if (diffBlocks.missing.length > 0) {
|
|
116
|
+
throw new MissingBlocksError('sync', diffBlocks.missing)
|
|
117
|
+
}
|
|
118
|
+
const commits: CommitData[] = updates.map((update) => {
|
|
119
|
+
const forCommit = diffBlocks.blocks.getMany(update.newCids.toList())
|
|
120
|
+
if (forCommit.missing.length > 0) {
|
|
121
|
+
throw new MissingBlocksError('sync', forCommit.missing)
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
commit: update.commit,
|
|
125
|
+
prev: update.prev,
|
|
126
|
+
blocks: forCommit.blocks,
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
await storage.indexCommits(commits)
|
|
131
|
+
|
|
132
|
+
return Promise.all(
|
|
133
|
+
updates.map((upd) =>
|
|
134
|
+
util.diffToWriteDescripts(upd.diff, diffBlocks.blocks),
|
|
135
|
+
),
|
|
136
|
+
)
|
|
137
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Commit, def, RecordPath } from '../types'
|
|
2
|
+
import { BlockWriter } from '@ipld/car/writer'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
4
|
+
import CidSet from '../cid-set'
|
|
5
|
+
import { MissingBlocksError } from '../error'
|
|
6
|
+
import { RepoStorage } from '../storage'
|
|
7
|
+
import * as util from '../util'
|
|
8
|
+
import { MST } from '../mst'
|
|
9
|
+
|
|
10
|
+
// Checkouts
|
|
11
|
+
// -------------
|
|
12
|
+
|
|
13
|
+
export const getCheckout = async (
|
|
14
|
+
storage: RepoStorage,
|
|
15
|
+
commitCid: CID,
|
|
16
|
+
): Promise<Uint8Array> => {
|
|
17
|
+
return util.writeCar(commitCid, async (car: BlockWriter) => {
|
|
18
|
+
const commit = await storage.readObjAndBytes(commitCid, def.commit)
|
|
19
|
+
await car.put({ cid: commitCid, bytes: commit.bytes })
|
|
20
|
+
const mst = MST.load(storage, commit.obj.data)
|
|
21
|
+
await mst.writeToCarStream(car)
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Diffs
|
|
26
|
+
// -------------
|
|
27
|
+
|
|
28
|
+
export const getDiff = async (
|
|
29
|
+
storage: RepoStorage,
|
|
30
|
+
latest: CID,
|
|
31
|
+
earliest: CID | null,
|
|
32
|
+
): Promise<Uint8Array> => {
|
|
33
|
+
return util.writeCar(latest, (car: BlockWriter) => {
|
|
34
|
+
return writeCommitsToCarStream(storage, car, latest, earliest)
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const getFullRepo = async (
|
|
39
|
+
storage: RepoStorage,
|
|
40
|
+
cid: CID,
|
|
41
|
+
): Promise<Uint8Array> => {
|
|
42
|
+
return getDiff(storage, cid, null)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const writeCommitsToCarStream = async (
|
|
46
|
+
storage: RepoStorage,
|
|
47
|
+
car: BlockWriter,
|
|
48
|
+
latest: CID,
|
|
49
|
+
earliest: CID | null,
|
|
50
|
+
): Promise<void> => {
|
|
51
|
+
const commits = await storage.getCommits(latest, earliest)
|
|
52
|
+
if (commits === null) {
|
|
53
|
+
throw new Error('Could not find shared history')
|
|
54
|
+
}
|
|
55
|
+
if (commits.length === 0) return
|
|
56
|
+
for (const commit of commits) {
|
|
57
|
+
for (const entry of commit.blocks.entries()) {
|
|
58
|
+
await car.put(entry)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Narrow slices
|
|
64
|
+
// -------------
|
|
65
|
+
|
|
66
|
+
export const getRecords = async (
|
|
67
|
+
storage: RepoStorage,
|
|
68
|
+
commitCid: CID,
|
|
69
|
+
paths: RecordPath[],
|
|
70
|
+
): Promise<Uint8Array> => {
|
|
71
|
+
return util.writeCar(commitCid, async (car: BlockWriter) => {
|
|
72
|
+
const commit = await storage.readObjAndBytes(commitCid, def.commit)
|
|
73
|
+
await car.put({ cid: commitCid, bytes: commit.bytes })
|
|
74
|
+
const mst = MST.load(storage, commit.obj.data)
|
|
75
|
+
const cidsForPaths = await Promise.all(
|
|
76
|
+
paths.map((p) =>
|
|
77
|
+
mst.cidsForPath(util.formatDataKey(p.collection, p.rkey)),
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
const allCids = cidsForPaths.reduce((acc, cur) => {
|
|
81
|
+
return acc.addSet(new CidSet(cur))
|
|
82
|
+
}, new CidSet())
|
|
83
|
+
const found = await storage.getBlocks(allCids.toList())
|
|
84
|
+
if (found.missing.length > 0) {
|
|
85
|
+
throw new MissingBlocksError('writeRecordsToCarStream', found.missing)
|
|
86
|
+
}
|
|
87
|
+
for (const block of found.blocks.entries()) {
|
|
88
|
+
await car.put(block)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,88 +1,127 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { BlockWriter } from '@ipld/car/writer'
|
|
3
|
-
import {
|
|
3
|
+
import { schema as common, def as commonDef } from '@atproto/common'
|
|
4
4
|
import { CID } from 'multiformats'
|
|
5
|
-
import
|
|
5
|
+
import BlockMap from './block-map'
|
|
6
|
+
import { RepoRecord } from '@atproto/lexicon'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// Repo nodes
|
|
9
|
+
// ---------------
|
|
10
|
+
|
|
11
|
+
const unsignedCommit = z.object({
|
|
8
12
|
did: z.string(),
|
|
9
13
|
version: z.number(),
|
|
10
|
-
datastore: z.string(),
|
|
11
|
-
})
|
|
12
|
-
export type RepoMeta = z.infer<typeof repoMeta>
|
|
13
|
-
|
|
14
|
-
const repoRoot = z.object({
|
|
15
|
-
meta: common.cid,
|
|
16
14
|
prev: common.cid.nullable(),
|
|
17
|
-
auth_token: common.cid.nullable(),
|
|
18
15
|
data: common.cid,
|
|
19
16
|
})
|
|
20
|
-
export type
|
|
17
|
+
export type UnsignedCommit = z.infer<typeof unsignedCommit> & { sig?: never }
|
|
21
18
|
|
|
22
19
|
const commit = z.object({
|
|
23
|
-
|
|
20
|
+
did: z.string(),
|
|
21
|
+
version: z.number(),
|
|
22
|
+
prev: common.cid.nullable(),
|
|
23
|
+
data: common.cid,
|
|
24
24
|
sig: common.bytes,
|
|
25
25
|
})
|
|
26
26
|
export type Commit = z.infer<typeof commit>
|
|
27
27
|
|
|
28
|
-
export const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
cid: common.cid,
|
|
33
|
-
})
|
|
34
|
-
export type CidCreateOp = z.infer<typeof cidCreateOp>
|
|
28
|
+
export const schema = {
|
|
29
|
+
...common,
|
|
30
|
+
commit,
|
|
31
|
+
}
|
|
35
32
|
|
|
36
|
-
export const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
33
|
+
export const def = {
|
|
34
|
+
...commonDef,
|
|
35
|
+
commit: {
|
|
36
|
+
name: 'commit',
|
|
37
|
+
schema: schema.commit,
|
|
38
|
+
},
|
|
39
|
+
}
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
collection: z.string(),
|
|
47
|
-
rkey: z.string(),
|
|
48
|
-
})
|
|
49
|
-
export type DeleteOp = z.infer<typeof deleteOp>
|
|
41
|
+
// Repo Operations
|
|
42
|
+
// ---------------
|
|
50
43
|
|
|
51
|
-
export
|
|
52
|
-
|
|
44
|
+
export enum WriteOpAction {
|
|
45
|
+
Create = 'create',
|
|
46
|
+
Update = 'update',
|
|
47
|
+
Delete = 'delete',
|
|
48
|
+
}
|
|
53
49
|
|
|
54
|
-
export
|
|
55
|
-
action:
|
|
56
|
-
collection:
|
|
57
|
-
rkey:
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
export type RecordCreateOp = z.infer<typeof recordCreateOp>
|
|
50
|
+
export type RecordCreateOp = {
|
|
51
|
+
action: WriteOpAction.Create
|
|
52
|
+
collection: string
|
|
53
|
+
rkey: string
|
|
54
|
+
record: RepoRecord
|
|
55
|
+
}
|
|
61
56
|
|
|
62
|
-
export
|
|
63
|
-
action:
|
|
64
|
-
collection:
|
|
65
|
-
rkey:
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
export type RecordUpdateOp = z.infer<typeof recordUpdateOp>
|
|
57
|
+
export type RecordUpdateOp = {
|
|
58
|
+
action: WriteOpAction.Update
|
|
59
|
+
collection: string
|
|
60
|
+
rkey: string
|
|
61
|
+
record: RepoRecord
|
|
62
|
+
}
|
|
69
63
|
|
|
70
|
-
export
|
|
71
|
-
|
|
64
|
+
export type RecordDeleteOp = {
|
|
65
|
+
action: WriteOpAction.Delete
|
|
66
|
+
collection: string
|
|
67
|
+
rkey: string
|
|
68
|
+
}
|
|
72
69
|
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
commit,
|
|
78
|
-
cidWriteOp,
|
|
79
|
-
recordWriteOp,
|
|
70
|
+
export type RecordWriteOp = RecordCreateOp | RecordUpdateOp | RecordDeleteOp
|
|
71
|
+
|
|
72
|
+
export type RecordCreateDescript = RecordCreateOp & {
|
|
73
|
+
cid: CID
|
|
80
74
|
}
|
|
81
75
|
|
|
82
|
-
export
|
|
83
|
-
|
|
76
|
+
export type RecordUpdateDescript = RecordUpdateOp & {
|
|
77
|
+
prev: CID
|
|
78
|
+
cid: CID
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type RecordDeleteDescript = RecordDeleteOp & {
|
|
82
|
+
cid: CID
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type RecordWriteDescript =
|
|
86
|
+
| RecordCreateDescript
|
|
87
|
+
| RecordUpdateDescript
|
|
88
|
+
| RecordDeleteDescript
|
|
89
|
+
|
|
90
|
+
export type WriteLog = RecordWriteDescript[][]
|
|
91
|
+
|
|
92
|
+
// Updates/Commits
|
|
93
|
+
// ---------------
|
|
94
|
+
|
|
95
|
+
export type CommitBlockData = {
|
|
96
|
+
commit: CID
|
|
97
|
+
blocks: BlockMap
|
|
84
98
|
}
|
|
85
99
|
|
|
100
|
+
export type CommitData = CommitBlockData & {
|
|
101
|
+
prev: CID | null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type RepoUpdate = CommitData & {
|
|
105
|
+
ops: RecordWriteOp[]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type CollectionContents = Record<string, RepoRecord>
|
|
109
|
+
export type RepoContents = Record<string, CollectionContents>
|
|
110
|
+
|
|
111
|
+
export type RecordPath = {
|
|
112
|
+
collection: string
|
|
113
|
+
rkey: string
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type RecordClaim = {
|
|
117
|
+
collection: string
|
|
118
|
+
rkey: string
|
|
119
|
+
record: RepoRecord | null
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// DataStores
|
|
123
|
+
// ---------------
|
|
124
|
+
|
|
86
125
|
export type DataValue = {
|
|
87
126
|
key: string
|
|
88
127
|
value: CID
|
|
@@ -93,9 +132,9 @@ export interface DataStore {
|
|
|
93
132
|
update(key: string, value: CID): Promise<DataStore>
|
|
94
133
|
delete(key: string): Promise<DataStore>
|
|
95
134
|
get(key: string): Promise<CID | null>
|
|
96
|
-
list(count
|
|
135
|
+
list(count?: number, after?: string, before?: string): Promise<DataValue[]>
|
|
97
136
|
listWithPrefix(prefix: string, count?: number): Promise<DataValue[]>
|
|
98
|
-
|
|
99
|
-
stage(): Promise<CID>
|
|
137
|
+
getUnstoredBlocks(): Promise<{ root: CID; blocks: BlockMap }>
|
|
100
138
|
writeToCarStream(car: BlockWriter): Promise<void>
|
|
139
|
+
cidsForPath(key: string): Promise<CID[]>
|
|
101
140
|
}
|