1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package repo
import (
"context"
"errors"
"time"
comatproto "github.com/bluesky-social/indigo/api/atproto"
"github.com/bluesky-social/indigo/atproto/atcrypto"
indigorepo "github.com/bluesky-social/indigo/atproto/repo"
"github.com/bluesky-social/indigo/atproto/syntax"
lexutil "github.com/bluesky-social/indigo/lex/util"
"github.com/ipfs/go-cid"
)
const (
MaxWrites = 200
DefaultList = 50
MaxList = 100
DefaultCommits = 100
MaxCommits = 1000
)
var (
ErrRepoNotFound = errors.New("repo not found")
ErrRepoExists = errors.New("repo already exists")
ErrCommitNotFound = errors.New("commit not found")
ErrRecordNotFound = errors.New("record not found")
ErrRecordExists = errors.New("record already exists")
ErrInvalidSwap = errors.New("invalid swap")
ErrInvalidRequest = errors.New("invalid request")
ErrReadOnly = errors.New("repo has no signing key")
ErrCorruptRepo = errors.New("repo is corrupt")
ErrUnsupportedRepo = errors.New("unsupported repo")
)
type Commit = indigorepo.Commit
type WriteAction string
const (
ActionCreate WriteAction = "create"
ActionUpdate WriteAction = "update"
ActionDelete WriteAction = "delete"
actionPut WriteAction = "put"
)
type WriteOp struct {
Action WriteAction
Collection syntax.NSID
Rkey syntax.RecordKey
Record map[string]any
Prev *cid.Cid
}
type CommitOp struct {
Action WriteAction
Path string
CID *cid.Cid
Prev *cid.Cid
}
type CommitEvent struct {
Repo syntax.DID
Seq int64
Commit cid.Cid
Rev syntax.TID
Since *syntax.TID
Data cid.Cid
PrevData *cid.Cid
Blocks []byte
Ops []CommitOp
Blobs []cid.Cid
Time time.Time
}
func (ev *CommitEvent) CommitMessage() *comatproto.SyncSubscribeRepos_Commit {
ops := make([]*comatproto.SyncSubscribeRepos_RepoOp, 0, len(ev.Ops))
for _, op := range ev.Ops {
rop := &comatproto.SyncSubscribeRepos_RepoOp{
Action: string(op.Action),
Path: op.Path,
}
if op.CID != nil {
c := lexutil.LexLink(*op.CID)
rop.Cid = &c
}
if op.Prev != nil {
p := lexutil.LexLink(*op.Prev)
rop.Prev = &p
}
ops = append(ops, rop)
}
var since *string
if ev.Since != nil {
s := ev.Since.String()
since = &s
}
var prevData *lexutil.LexLink
if ev.PrevData != nil {
p := lexutil.LexLink(*ev.PrevData)
prevData = &p
}
blobs := make([]lexutil.LexLink, 0, len(ev.Blobs))
for _, b := range ev.Blobs {
blobs = append(blobs, lexutil.LexLink(b))
}
return &comatproto.SyncSubscribeRepos_Commit{
Blobs: blobs,
Blocks: lexutil.LexBytes(ev.Blocks),
Commit: lexutil.LexLink(ev.Commit),
Ops: ops,
PrevData: prevData,
Repo: ev.Repo.String(),
Rev: ev.Rev.String(),
Seq: ev.Seq,
Since: since,
Time: ev.Time.UTC().Format("2006-01-02T15:04:05.000Z"),
}
}
type Record struct {
Collection syntax.NSID
Rkey syntax.RecordKey
CID cid.Cid
Bytes []byte
Value map[string]any
}
type CommitRecord struct {
DID syntax.DID
CID cid.Cid
Rev syntax.TID
Data cid.Cid
Prev *cid.Cid
Signed *Commit
Seq int64
Time time.Time
}
type EventSink interface {
OnCommit(ctx context.Context, ev *CommitEvent) error
}
type EventSinkFunc func(ctx context.Context, ev *CommitEvent) error
func (f EventSinkFunc) OnCommit(ctx context.Context, ev *CommitEvent) error {
return f(ctx, ev)
}
type RecordStore interface {
GetRecord(ctx context.Context, did syntax.DID, collection syntax.NSID, rkey syntax.RecordKey) (*Record, error)
ListRecords(ctx context.Context, did syntax.DID, collection syntax.NSID, cursor syntax.RecordKey, limit int) ([]Record, *syntax.RecordKey, error)
}
type CommitStore interface {
Head(ctx context.Context, did syntax.DID) (*CommitRecord, error)
GetCommit(ctx context.Context, did syntax.DID, rev syntax.TID) (*CommitRecord, error)
ListCommits(ctx context.Context, did syntax.DID, since *syntax.TID, limit int) ([]CommitRecord, error)
CAR(ctx context.Context, did syntax.DID, since *syntax.TID) ([]byte, error)
CommitCAR(ctx context.Context, did syntax.DID, commit cid.Cid) ([]byte, error)
}
type RepoStore interface {
RecordStore
CommitStore
CreateRepo(ctx context.Context, did syntax.DID, key atcrypto.PrivateKey) (Repo, error)
OpenRepo(ctx context.Context, did syntax.DID, key atcrypto.PrivateKey) (Repo, error)
DeleteRepo(ctx context.Context, did syntax.DID) error
RepoExists(ctx context.Context, did syntax.DID) (bool, error)
ListRepos(ctx context.Context) ([]syntax.DID, error)
ListEvents(ctx context.Context, since int64, limit int) ([]*CommitEvent, error)
SetEventSink(sink EventSink)
Close() error
}
type Repo interface {
DID() syntax.DID
Head(ctx context.Context) (*CommitRecord, error)
GetRecord(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey) (*Record, error)
ListRecords(ctx context.Context, collection syntax.NSID, cursor syntax.RecordKey, limit int) ([]Record, *syntax.RecordKey, error)
Walk(ctx context.Context, prefix string, fn func(path string, c cid.Cid) error) error
ApplyWrites(ctx context.Context, writes []WriteOp, swapCommit *cid.Cid) (*CommitEvent, error)
CreateRecord(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey, record map[string]any) (*Record, *CommitEvent, error)
PutRecord(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey, record map[string]any, swapRecord *cid.Cid) (*Record, *CommitEvent, error)
DeleteRecord(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey, swapRecord *cid.Cid) (*CommitEvent, error)
GetCommit(ctx context.Context, rev syntax.TID) (*CommitRecord, error)
Commits(ctx context.Context, since *syntax.TID, limit int) ([]CommitRecord, error)
CAR(ctx context.Context, since *syntax.TID) ([]byte, error)
CommitCAR(ctx context.Context, commit cid.Cid) ([]byte, error)
Proof(ctx context.Context, collection syntax.NSID, rkey syntax.RecordKey) ([]byte, error)
Diff(ctx context.Context, since syntax.TID) ([]CommitOp, error)
Verify(ctx context.Context) error
}