@@ -10,15 +10,23 @@ import { combineQueries } from '../../database/combineQueries.js'
10
10
import { APIError , Forbidden , NotFound } from '../../errors/index.js'
11
11
import { afterChange } from '../../fields/hooks/afterChange/index.js'
12
12
import { afterRead } from '../../fields/hooks/afterRead/index.js'
13
+ import { beforeChange } from '../../fields/hooks/beforeChange/index.js'
14
+ import { beforeValidate } from '../../fields/hooks/beforeValidate/index.js'
15
+ import { commitTransaction } from '../../utilities/commitTransaction.js'
16
+ import { deepCopyObjectSimple } from '../../utilities/deepCopyObject.js'
17
+ import { initTransaction } from '../../utilities/initTransaction.js'
13
18
import { killTransaction } from '../../utilities/killTransaction.js'
14
19
import { sanitizeSelect } from '../../utilities/sanitizeSelect.js'
15
20
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion.js'
21
+ import { saveVersion } from '../../versions/saveVersion.js'
22
+ import { buildAfterOperation } from './utils.js'
16
23
17
24
export type Arguments = {
18
25
collection : Collection
19
26
currentDepth ?: number
20
27
depth ?: number
21
28
disableErrors ?: boolean
29
+ disableTransaction ?: boolean
22
30
draft ?: boolean
23
31
id : number | string
24
32
overrideAccess ?: boolean
@@ -35,7 +43,7 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
35
43
id,
36
44
collection : { config : collectionConfig } ,
37
45
depth,
38
- draft,
46
+ draft : draftArg = false ,
39
47
overrideAccess = false ,
40
48
populate,
41
49
req,
@@ -45,6 +53,25 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
45
53
} = args
46
54
47
55
try {
56
+ const shouldCommit = ! args . disableTransaction && ( await initTransaction ( args . req ) )
57
+
58
+ // /////////////////////////////////////
59
+ // beforeOperation - Collection
60
+ // /////////////////////////////////////
61
+
62
+ if ( args . collection . config . hooks ?. beforeOperation ?. length ) {
63
+ for ( const hook of args . collection . config . hooks . beforeOperation ) {
64
+ args =
65
+ ( await hook ( {
66
+ args,
67
+ collection : args . collection . config ,
68
+ context : args . req . context ,
69
+ operation : 'restoreVersion' ,
70
+ req : args . req ,
71
+ } ) ) || args
72
+ }
73
+ }
74
+
48
75
if ( ! id ) {
49
76
throw new APIError ( 'Missing ID of version to restore.' , httpStatus . BAD_REQUEST )
50
77
}
@@ -68,7 +95,7 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
68
95
throw new NotFound ( req . t )
69
96
}
70
97
71
- const parentDocID = rawVersion . parent
98
+ const { parent : parentDocID , version : versionToRestoreWithLocales } = rawVersion
72
99
73
100
// /////////////////////////////////////
74
101
// Access
@@ -90,6 +117,7 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
90
117
where : combineQueries ( { id : { equals : parentDocID } } , accessResults ) ,
91
118
}
92
119
120
+ // Get the document from the non versioned collection
93
121
const doc = await req . payload . db . findOne ( findOneArgs )
94
122
95
123
if ( ! doc && ! hasWherePolicy ) {
@@ -109,7 +137,6 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
109
137
// /////////////////////////////////////
110
138
// fetch previousDoc
111
139
// /////////////////////////////////////
112
-
113
140
const prevDocWithLocales = await getLatestCollectionVersion ( {
114
141
id : parentDocID ,
115
142
config : collectionConfig ,
@@ -118,6 +145,109 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
118
145
req,
119
146
} )
120
147
148
+ // originalDoc with hoisted localized data
149
+ const originalDoc = await afterRead ( {
150
+ collection : collectionConfig ,
151
+ context : req . context ,
152
+ depth : 0 ,
153
+ doc : deepCopyObjectSimple ( prevDocWithLocales ) ,
154
+ draft : draftArg ,
155
+ fallbackLocale : null ,
156
+ global : null ,
157
+ locale : locale ! ,
158
+ overrideAccess : true ,
159
+ req,
160
+ showHiddenFields : true ,
161
+ } )
162
+
163
+ // version data with hoisted localized data
164
+ const prevVersionDoc = await afterRead ( {
165
+ collection : collectionConfig ,
166
+ context : req . context ,
167
+ depth : 0 ,
168
+ doc : deepCopyObjectSimple ( versionToRestoreWithLocales ) ,
169
+ draft : draftArg ,
170
+ fallbackLocale : null ,
171
+ global : null ,
172
+ locale : locale ! ,
173
+ overrideAccess : true ,
174
+ req,
175
+ showHiddenFields : true ,
176
+ } )
177
+
178
+ let data = deepCopyObjectSimple ( prevVersionDoc )
179
+
180
+ // /////////////////////////////////////
181
+ // beforeValidate - Fields
182
+ // /////////////////////////////////////
183
+
184
+ data = await beforeValidate ( {
185
+ id : parentDocID ,
186
+ collection : collectionConfig ,
187
+ context : req . context ,
188
+ data,
189
+ doc : originalDoc ,
190
+ global : null ,
191
+ operation : 'update' ,
192
+ overrideAccess,
193
+ req,
194
+ } )
195
+
196
+ // /////////////////////////////////////
197
+ // beforeValidate - Collection
198
+ // /////////////////////////////////////
199
+
200
+ if ( collectionConfig . hooks ?. beforeValidate ?. length ) {
201
+ for ( const hook of collectionConfig . hooks . beforeValidate ) {
202
+ data =
203
+ ( await hook ( {
204
+ collection : collectionConfig ,
205
+ context : req . context ,
206
+ data,
207
+ operation : 'update' ,
208
+ originalDoc,
209
+ req,
210
+ } ) ) || data
211
+ }
212
+ }
213
+
214
+ // /////////////////////////////////////
215
+ // beforeChange - Collection
216
+ // /////////////////////////////////////
217
+
218
+ if ( collectionConfig . hooks ?. beforeChange ?. length ) {
219
+ for ( const hook of collectionConfig . hooks . beforeChange ) {
220
+ data =
221
+ ( await hook ( {
222
+ collection : collectionConfig ,
223
+ context : req . context ,
224
+ data,
225
+ operation : 'update' ,
226
+ originalDoc,
227
+ req,
228
+ } ) ) || data
229
+ }
230
+ }
231
+
232
+ // /////////////////////////////////////
233
+ // beforeChange - Fields
234
+ // /////////////////////////////////////
235
+
236
+ let result = await beforeChange ( {
237
+ id : parentDocID ,
238
+ collection : collectionConfig ,
239
+ context : req . context ,
240
+ data : { ...data , id : parentDocID } ,
241
+ doc : originalDoc ,
242
+ docWithLocales : versionToRestoreWithLocales ,
243
+ global : null ,
244
+ operation : 'update' ,
245
+ overrideAccess,
246
+ req,
247
+ skipValidation :
248
+ draftArg && collectionConfig . versions . drafts && ! collectionConfig . versions . drafts . validate ,
249
+ } )
250
+
121
251
// /////////////////////////////////////
122
252
// Update
123
253
// /////////////////////////////////////
@@ -128,10 +258,10 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
128
258
select : incomingSelect ,
129
259
} )
130
260
131
- let result = await req . payload . db . updateOne ( {
261
+ result = await req . payload . db . updateOne ( {
132
262
id : parentDocID ,
133
263
collection : collectionConfig . slug ,
134
- data : rawVersion . version ,
264
+ data : result ,
135
265
req,
136
266
select,
137
267
} )
@@ -140,18 +270,16 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
140
270
// Save `previousDoc` as a version after restoring
141
271
// /////////////////////////////////////
142
272
143
- const prevVersion = { ...prevDocWithLocales }
144
-
145
- delete prevVersion . id
146
-
147
- await payload . db . createVersion ( {
273
+ result = await saveVersion ( {
274
+ id : parentDocID ,
148
275
autosave : false ,
149
- collectionSlug : collectionConfig . slug ,
150
- createdAt : prevVersion . createdAt ,
151
- parent : parentDocID ,
276
+ collection : collectionConfig ,
277
+ docWithLocales : result ,
278
+ draft : draftArg ,
279
+ operation : 'restoreVersion' ,
280
+ payload,
152
281
req,
153
- updatedAt : new Date ( ) . toISOString ( ) ,
154
- versionData : draft ? { ...rawVersion . version , _status : 'draft' } : rawVersion . version ,
282
+ select,
155
283
} )
156
284
157
285
// /////////////////////////////////////
@@ -225,6 +353,21 @@ export const restoreVersionOperation = async <TData extends TypeWithID = any>(
225
353
}
226
354
}
227
355
356
+ // /////////////////////////////////////
357
+ // afterOperation - Collection
358
+ // /////////////////////////////////////
359
+
360
+ result = await buildAfterOperation ( {
361
+ args,
362
+ collection : collectionConfig ,
363
+ operation : 'restoreVersion' ,
364
+ result,
365
+ } )
366
+
367
+ if ( shouldCommit ) {
368
+ await commitTransaction ( req )
369
+ }
370
+
228
371
return result
229
372
} catch ( error : unknown ) {
230
373
await killTransaction ( req )
0 commit comments