-
Notifications
You must be signed in to change notification settings - Fork 0
/
docdb.go
311 lines (246 loc) · 12.3 KB
/
docdb.go
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
package docdb
import (
"context"
fs "github.com/ungerik/go-fs"
"github.com/domonda/go-errs"
"github.com/domonda/go-types/uu"
)
// DocumentExists returns true if a document with the passed docID exists
func DocumentExists(ctx context.Context, docID uu.ID) (exists bool, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.DocumentExists(ctx, docID)
}
// EnumDocumentIDs calls the passed callback with the ID of every document in the database
func EnumDocumentIDs(ctx context.Context, callback func(context.Context, uu.ID) error) (err error) {
defer errs.WrapWithFuncParams(&err, ctx)
return conn.EnumDocumentIDs(ctx, callback)
}
// EnumCompanyDocumentIDs calls the passed callback with the ID of every document of a company in the database
func EnumCompanyDocumentIDs(ctx context.Context, companyID uu.ID, callback func(context.Context, uu.ID) error) (err error) {
defer errs.WrapWithFuncParams(&err, ctx, companyID)
return conn.EnumCompanyDocumentIDs(ctx, companyID, callback)
}
// DocumentCompanyID returns the companyID for a docID
func DocumentCompanyID(ctx context.Context, docID uu.ID) (companyID uu.ID, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.DocumentCompanyID(ctx, docID)
}
// SetDocumentCompanyID changes the companyID for a document
func SetDocumentCompanyID(ctx context.Context, docID, companyID uu.ID) (err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, companyID)
return conn.SetDocumentCompanyID(ctx, docID, companyID)
}
// DocumentVersions returns all version timestamps of a document in ascending order.
// Returns nil and no error if the document does not exist or has no versions.
func DocumentVersions(ctx context.Context, docID uu.ID) (versions []VersionTime, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.DocumentVersions(ctx, docID)
}
// LatestDocumentVersion returns the lates VersionTime of a document
func LatestDocumentVersion(ctx context.Context, docID uu.ID) (version VersionTime, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.LatestDocumentVersion(ctx, docID)
}
// DocumentVersionInfo returns the VersionInfo for a VersionTime
func DocumentVersionInfo(ctx context.Context, docID uu.ID, version VersionTime) (info *VersionInfo, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version)
return conn.DocumentVersionInfo(ctx, docID, version)
}
// LatestDocumentVersionInfo returns the VersionInfo for the latest document version
func LatestDocumentVersionInfo(ctx context.Context, docID uu.ID) (info *VersionInfo, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.LatestDocumentVersionInfo(ctx, docID)
}
// DocumentVersionFileProvider returns a FileProvider for the files of a document version
func DocumentVersionFileProvider(ctx context.Context, docID uu.ID, version VersionTime) (p FileProvider, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version)
return conn.DocumentVersionFileProvider(ctx, docID, version)
}
// ReadDocumentFile reads a file of the latest document version
func ReadDocumentFile(ctx context.Context, docID uu.ID, filename string) (data []byte, versionInfo *VersionInfo, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, filename)
versionInfo, err = conn.LatestDocumentVersionInfo(ctx, docID)
if err != nil {
return nil, nil, err
}
data, err = conn.ReadDocumentVersionFile(ctx, docID, versionInfo.Version, filename)
if err != nil {
return nil, nil, err
}
return data, versionInfo, nil
}
// SubstituteDeletedDocumentVersion will substitue the passed version with
// the next existing version it does not exist anymore.
// Will return ErrDocumentHasNoCommitedVersion if there is no
// other commited version for the document.
func SubstituteDeletedDocumentVersion(ctx context.Context, docID uu.ID, version VersionTime) (validVersion VersionTime, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version)
_, err = conn.DocumentVersionInfo(ctx, docID, version)
if err == nil {
return version, nil
}
if !errs.Has[ErrDocumentVersionNotFound](err) {
return VersionTime{}, err
}
versions, err := conn.DocumentVersions(ctx, docID)
if err != nil {
return VersionTime{}, err
}
if len(versions) == 0 {
return VersionTime{}, NewErrDocumentHasNoCommitedVersion(docID)
}
for i := range versions {
// Return the first version after the deleted one
if versions[i].Time.After(version.Time) {
return versions[i], nil
}
}
// Return latest vesion if none is after the deleted one
return versions[len(versions)-1], nil
}
// ReadDocumentVersionFile returns the contents of a file of a document version.
// Wrapped ErrDocumentNotFound, ErrDocumentVersionNotFound, ErrDocumentFileNotFound
// will be returned in case of such error conditions.
func ReadDocumentVersionFile(ctx context.Context, docID uu.ID, version VersionTime, filename string) (data []byte, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version, filename)
return conn.ReadDocumentVersionFile(ctx, docID, version, filename)
}
func ReadLatestDocumentVersionFile(ctx context.Context, docID uu.ID, filename string) (data []byte, version VersionTime, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version, filename)
version, err = conn.LatestDocumentVersion(ctx, docID)
if err != nil {
return nil, VersionTime{}, err
}
data, err = conn.ReadDocumentVersionFile(ctx, docID, version, filename)
if err != nil {
return nil, VersionTime{}, err
}
return data, version, nil
}
// DocumentVersionFileReader returns a fs.FileReader for a file of a document version.
// Wrapped ErrDocumentNotFound, ErrDocumentVersionNotFound, ErrDocumentFileNotFound
// will be returned in case of such error conditions.
func DocumentVersionFileReader(ctx context.Context, docID uu.ID, version VersionTime, filename string) (fileReader fs.FileReader, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version, filename)
data, err := conn.ReadDocumentVersionFile(ctx, docID, version, filename)
if err != nil {
return nil, err
}
return fs.NewMemFile(filename, data), nil
}
// DocumentFileReader returns a fs.FileReader for a file of the latest document version.
// Wrapped ErrDocumentNotFound, ErrDocumentHasNoCommitedVersion, ErrDocumentFileNotFound
// will be returned in case of such error conditions.
func DocumentFileReader(ctx context.Context, docID uu.ID, filename string) (fileReader fs.FileReader, versionInfo *VersionInfo, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, filename)
versionInfo, err = conn.LatestDocumentVersionInfo(ctx, docID)
if err != nil {
return nil, nil, err
}
data, err := conn.ReadDocumentVersionFile(ctx, docID, versionInfo.Version, filename)
if err != nil {
return nil, nil, err
}
return fs.NewMemFile(filename, data), versionInfo, nil
}
// DocumentFileExists returns if a document file with filename exists in the latest document version.
func DocumentFileExists(ctx context.Context, docID uu.ID, filename string) (exists bool, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, filename)
file, _, err := DocumentFileReader(ctx, docID, filename)
if errs.Has[ErrDocumentFileNotFound](err) {
return false, nil
}
if err != nil {
return false, err
}
return file.Exists(), nil
}
// DocumentCheckOutStatus returns the CheckOutStatus of a document.
// If the document is not checked out, then a nil CheckOutStatus will be returned.
// The methods Valid() and String() can be called on a nil CheckOutStatus.
// ErrDocumentNotFound is returned if the document does not exist.
func DocumentCheckOutStatus(ctx context.Context, docID uu.ID) (status *CheckOutStatus, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.DocumentCheckOutStatus(ctx, docID)
}
// CheckedOutDocumentDir returns a fs.File for the directory
// where a document would be checked out.
func CheckedOutDocumentDir(docID uu.ID) fs.File {
return conn.CheckedOutDocumentDir(docID)
}
// CheckedOutDocumentFileProvider returns a FileProvider for the directory
// where a document would be checked out.
func CheckedOutDocumentFileProvider(docID uu.ID) (p FileProvider, err error) {
defer errs.WrapWithFuncParams(&err, docID)
checkOutDir := conn.CheckedOutDocumentDir(docID)
if !checkOutDir.Exists() {
return nil, NewErrDocumentNotCheckedOut(docID)
}
return DirFileProvider(checkOutDir), nil
}
// CancelCheckOutDocument cancels a potential checkout.
// No error is returned if the document was not checked out.
// If the checkout was created by CheckOutNewDocument,
// then the new document is deleted without leaving any history
// and the returned lastVersion.IsNull() is true.
func CancelCheckOutDocument(ctx context.Context, docID uu.ID) (wasCheckedOut bool, lastVersion VersionTime, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.CancelCheckOutDocument(ctx, docID)
}
// CheckInDocument checks in a checked out document
// and returns the VersionInfo for the newly created version.
func CheckInDocument(ctx context.Context, docID uu.ID) (v *VersionInfo, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.CheckInDocument(ctx, docID)
}
// CheckedOutDocuments returns the CheckOutStatus of all checked out documents.
func CheckedOutDocuments(ctx context.Context) (stati []*CheckOutStatus, err error) {
defer errs.WrapWithFuncParams(&err, ctx)
return conn.CheckedOutDocuments(ctx)
}
// CheckOutNewDocument creates a new document for a company in checked out state.
func CheckOutNewDocument(ctx context.Context, docID, companyID, userID uu.ID, reason string) (status *CheckOutStatus, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, companyID, userID, reason)
return conn.CheckOutNewDocument(ctx, docID, companyID, userID, reason)
}
// CheckOutDocument checks out a document for a user with a stated reason.
// Returns ErrDocumentCheckedOut if the document is already checked out.
func CheckOutDocument(ctx context.Context, docID, userID uu.ID, reason string) (status *CheckOutStatus, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, userID, reason)
return conn.CheckOutDocument(ctx, docID, userID, reason)
}
// DeleteDocument deletes all versions of a document
// including its workspace directory if checked out.
func DeleteDocument(ctx context.Context, docID uu.ID) (err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID)
return conn.DeleteDocument(ctx, docID)
}
// DeleteDocumentVersion deletes a version of a document that must not be checked out
// and returns the left over versions.
// If the version is the only version of the document,
// then the document will be deleted and no leftVersions are returned.
// Returns wrapped ErrDocumentNotFound, ErrDocumentVersionNotFound, ErrDocumentCheckedOut
// in case of such error conditions.
// DeleteDocumentVersion should not be used for normal docdb operations,
// just to clean up mistakes or sync database states.
func DeleteDocumentVersion(ctx context.Context, docID uu.ID, version VersionTime) (leftVersions []VersionTime, err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, version)
return conn.DeleteDocumentVersion(ctx, docID, version)
}
// InsertDocumentVersion inserts a new version for an existing document.
// Returns wrapped ErrDocumentNotFound, ErrDocumentVersionAlreadyExists
// in case of such error conditions.
// InsertDocumentVersion should not be used for normal docdb operations,
// just to clean up mistakes or sync database states.
// func InsertDocumentVersion(ctx context.Context, docID uu.ID, version VersionTime, userID uu.ID, reason string, files []fs.FileReader) (info *VersionInfo, err error) {
// defer errs.WrapWithFuncParams(&err, ctx, docID, version, userID, reason, files)
// return conn.InsertDocumentVersion(ctx, docID, version, userID, reason, files)
// }
func CreateDocument(ctx context.Context, companyID, docID, userID uu.ID, reason string, files []fs.FileReader) (versionInfo *VersionInfo, err error) {
defer errs.WrapWithFuncParams(&err, ctx, companyID, docID, userID, reason, files)
return conn.CreateDocument(ctx, companyID, docID, userID, reason, files)
}
func AddDocumentVersion(ctx context.Context, docID, userID uu.ID, reason string, createVersion CreateVersionFunc, onNewVersion OnNewVersionFunc) (err error) {
defer errs.WrapWithFuncParams(&err, ctx, docID, userID, reason)
return conn.AddDocumentVersion(ctx, docID, userID, reason, createVersion, onNewVersion)
}