feat: consolidates logic in update and updateByID operations (#9998)

### What?
Consolidates logic in update and updateByID. These two operations used a
lot of the same core functionality. This is a QOL improvement for future
features/fixes on each operation. You will not need to make changes to
both operations now.

### Why?
Recently we released a feature for `publishSpecificLocale` and that was
only implemented on the updateByID operation. I think future
enhancements and fixes may suffer the same treatment.

### How?
Moves shared logic into a new file with a function called
`updateDocument`.
This commit is contained in:
Jarrod Flesch
2025-01-13 09:28:25 -05:00
committed by GitHub
parent 04a8083658
commit 690e99f2f9
3 changed files with 434 additions and 535 deletions

View File

@@ -13,26 +13,18 @@ import type {
SelectFromCollectionSlug,
} from '../config/types.js'
import { ensureUsernameOrEmail } from '../../auth/ensureUsernameOrEmail.js'
import executeAccess from '../../auth/executeAccess.js'
import { combineQueries } from '../../database/combineQueries.js'
import { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths.js'
import { APIError } from '../../errors/index.js'
import { afterChange } from '../../fields/hooks/afterChange/index.js'
import { afterRead } from '../../fields/hooks/afterRead/index.js'
import { beforeChange } from '../../fields/hooks/beforeChange/index.js'
import { beforeValidate } from '../../fields/hooks/beforeValidate/index.js'
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles.js'
import { generateFileData } from '../../uploads/generateFileData.js'
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles.js'
import { uploadFiles } from '../../uploads/uploadFiles.js'
import { checkDocumentLockStatus } from '../../utilities/checkDocumentLockStatus.js'
import { commitTransaction } from '../../utilities/commitTransaction.js'
import { initTransaction } from '../../utilities/initTransaction.js'
import { killTransaction } from '../../utilities/killTransaction.js'
import { buildVersionCollectionFields } from '../../versions/buildCollectionFields.js'
import { appendVersionToQueryKey } from '../../versions/drafts/appendVersionToQueryKey.js'
import { saveVersion } from '../../versions/saveVersion.js'
import { updateDocument } from './utilities/update.js'
import { buildAfterOperation } from './utils.js'
export type Arguments<TSlug extends CollectionSlug> = {
@@ -47,6 +39,7 @@ export type Arguments<TSlug extends CollectionSlug> = {
overrideLock?: boolean
overwriteExistingFiles?: boolean
populate?: PopulateType
publishSpecificLocale?: string
req: PayloadRequest
select?: SelectType
showHiddenFields?: boolean
@@ -91,6 +84,7 @@ export const updateOperation = async <
overrideLock,
overwriteExistingFiles = false,
populate,
publishSpecificLocale,
req: {
fallbackLocale,
locale,
@@ -172,7 +166,7 @@ export const updateOperation = async <
// Generate data for all files and sizes
// /////////////////////////////////////
const { data: newFileData, files: filesToUpload } = await generateFileData({
const { data, files: filesToUpload } = await generateFileData({
collection,
config,
data: bulkUpdateData,
@@ -184,251 +178,37 @@ export const updateOperation = async <
const errors = []
const promises = docs.map(async (doc) => {
const { id } = doc
let data = {
...newFileData,
...bulkUpdateData,
}
const promises = docs.map(async (docWithLocales) => {
const { id } = docWithLocales
try {
// /////////////////////////////////////
// Handle potentially locked documents
// /////////////////////////////////////
await checkDocumentLockStatus({
// ///////////////////////////////////////////////
// Update document, runs all document level hooks
// ///////////////////////////////////////////////
const updatedDoc = await updateDocument({
id,
collectionSlug: collectionConfig.slug,
lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,
overrideLock,
req,
})
const originalDoc = await afterRead({
collection: collectionConfig,
context: req.context,
depth: 0,
doc,
draft: draftArg,
fallbackLocale,
global: null,
locale,
overrideAccess: true,
req,
showHiddenFields: true,
})
await deleteAssociatedFiles({
accessResults: accessResult,
autosave: false,
collectionConfig,
config,
doc,
files: filesToUpload,
overrideDelete: false,
req,
})
if (args.collection.config.auth) {
ensureUsernameOrEmail<TSlug>({
authOptions: args.collection.config.auth,
collectionSlug: args.collection.config.slug,
data: args.data,
operation: 'update',
originalDoc,
req: args.req,
})
}
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
data = await beforeValidate<DeepPartial<DataFromCollectionSlug<TSlug>>>({
id,
collection: collectionConfig,
context: req.context,
data,
doc: originalDoc,
global: null,
operation: 'update',
overrideAccess,
req,
})
// /////////////////////////////////////
// beforeValidate - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
await priorHook
data =
(await hook({
collection: collectionConfig,
context: req.context,
data,
operation: 'update',
originalDoc,
req,
})) || data
}, Promise.resolve())
// /////////////////////////////////////
// Write files to local storage
// /////////////////////////////////////
if (!collectionConfig.upload.disableLocalStorage) {
await uploadFiles(payload, filesToUpload, req)
}
// /////////////////////////////////////
// beforeChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
await priorHook
data =
(await hook({
collection: collectionConfig,
context: req.context,
data,
operation: 'update',
originalDoc,
req,
})) || data
}, Promise.resolve())
// /////////////////////////////////////
// beforeChange - Fields
// /////////////////////////////////////
let result = await beforeChange({
id,
collection: collectionConfig,
context: req.context,
data,
doc: originalDoc,
docWithLocales: doc,
global: null,
operation: 'update',
req,
skipValidation:
shouldSaveDraft &&
collectionConfig.versions.drafts &&
!collectionConfig.versions.drafts.validate &&
data._status !== 'published',
})
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft || data._status === 'published') {
result = await req.payload.db.updateOne({
id,
collection: collectionConfig.slug,
data: result,
locale,
req,
select,
})
}
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
id,
collection: collectionConfig,
docWithLocales: result,
payload,
req,
select,
})
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
collection: collectionConfig,
context: req.context,
depth,
doc: result,
draft: draftArg,
fallbackLocale: null,
global: null,
docWithLocales,
draftArg,
fallbackLocale,
filesToUpload,
locale,
overrideAccess,
overrideLock,
payload,
populate,
publishSpecificLocale,
req,
select,
showHiddenFields,
})
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook
result =
(await hook({
collection: collectionConfig,
context: req.context,
doc: result,
req,
})) || result
}, Promise.resolve())
// /////////////////////////////////////
// afterChange - Fields
// /////////////////////////////////////
result = await afterChange({
collection: collectionConfig,
context: req.context,
data,
doc: result,
global: null,
operation: 'update',
previousDoc: originalDoc,
req,
})
// /////////////////////////////////////
// afterChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
await priorHook
result =
(await hook({
collection: collectionConfig,
context: req.context,
doc: result,
operation: 'update',
previousDoc: originalDoc,
req,
})) || result
}, Promise.resolve())
await unlinkTempFiles({
collectionConfig,
config,
req,
})
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
return result
return updatedDoc
} catch (error) {
errors.push({
id,
@@ -438,6 +218,12 @@ export const updateOperation = async <
return null
})
await unlinkTempFiles({
collectionConfig,
config,
req,
})
const awaitedDocs = await Promise.all(promises)
let result = {

View File

@@ -3,7 +3,6 @@ import type { DeepPartial } from 'ts-essentials'
import httpStatus from 'http-status'
import type { FindOneArgs } from '../../database/types.js'
import type { Args } from '../../fields/hooks/beforeChange/index.js'
import type { CollectionSlug } from '../../index.js'
import type {
PayloadRequest,
@@ -13,31 +12,21 @@ import type {
} from '../../types/index.js'
import type {
Collection,
DataFromCollectionSlug,
RequiredDataFromCollectionSlug,
SelectFromCollectionSlug,
} from '../config/types.js'
import { ensureUsernameOrEmail } from '../../auth/ensureUsernameOrEmail.js'
import executeAccess from '../../auth/executeAccess.js'
import { generatePasswordSaltHash } from '../../auth/strategies/local/generatePasswordSaltHash.js'
import { hasWhereAccessResult } from '../../auth/types.js'
import { combineQueries } from '../../database/combineQueries.js'
import { APIError, Forbidden, NotFound } from '../../errors/index.js'
import { afterChange } from '../../fields/hooks/afterChange/index.js'
import { afterRead } from '../../fields/hooks/afterRead/index.js'
import { beforeChange } from '../../fields/hooks/beforeChange/index.js'
import { beforeValidate } from '../../fields/hooks/beforeValidate/index.js'
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles.js'
import { generateFileData } from '../../uploads/generateFileData.js'
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles.js'
import { uploadFiles } from '../../uploads/uploadFiles.js'
import { checkDocumentLockStatus } from '../../utilities/checkDocumentLockStatus.js'
import { commitTransaction } from '../../utilities/commitTransaction.js'
import { initTransaction } from '../../utilities/initTransaction.js'
import { killTransaction } from '../../utilities/killTransaction.js'
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion.js'
import { saveVersion } from '../../versions/saveVersion.js'
import { updateDocument } from './utilities/update.js'
import { buildAfterOperation } from './utils.js'
export type Arguments<TSlug extends CollectionSlug> = {
@@ -118,10 +107,7 @@ export const updateByIDOperation = async <
throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST)
}
let { data } = args
const password = data?.password
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts)
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft)
const { data } = args
// /////////////////////////////////////
// Access
@@ -158,43 +144,6 @@ export const updateByIDOperation = async <
throw new Forbidden(req.t)
}
// /////////////////////////////////////
// Handle potentially locked documents
// /////////////////////////////////////
await checkDocumentLockStatus({
id,
collectionSlug: collectionConfig.slug,
lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,
overrideLock,
req,
})
const originalDoc = await afterRead({
collection: collectionConfig,
context: req.context,
depth: 0,
doc: docWithLocales,
draft: draftArg,
fallbackLocale: null,
global: null,
locale,
overrideAccess: true,
req,
showHiddenFields: true,
})
if (args.collection.config.auth) {
ensureUsernameOrEmail<TSlug>({
authOptions: args.collection.config.auth,
collectionSlug: args.collection.config.slug,
data: args.data,
operation: 'update',
originalDoc,
req: args.req,
})
}
// /////////////////////////////////////
// Generate data for all files and sizes
// /////////////////////////////////////
@@ -209,266 +158,50 @@ export const updateByIDOperation = async <
throwOnMissingFile: false,
})
data = newFileData
// ///////////////////////////////////////////////
// Update document, runs all document level hooks
// ///////////////////////////////////////////////
// /////////////////////////////////////
// Delete any associated files
// /////////////////////////////////////
await deleteAssociatedFiles({
let result = await updateDocument<TSlug, TSelect>({
id,
accessResults,
autosave,
collectionConfig,
config,
doc: docWithLocales,
files: filesToUpload,
overrideDelete: false,
req,
})
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
data = await beforeValidate<DeepPartial<DataFromCollectionSlug<TSlug>>>({
id,
collection: collectionConfig,
context: req.context,
data,
doc: originalDoc,
global: null,
operation: 'update',
overrideAccess,
req,
})
// /////////////////////////////////////
// beforeValidate - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
await priorHook
data =
(await hook({
collection: collectionConfig,
context: req.context,
data,
operation: 'update',
originalDoc,
req,
})) || data
}, Promise.resolve())
// /////////////////////////////////////
// Write files to local storage
// /////////////////////////////////////
if (!collectionConfig.upload.disableLocalStorage) {
await uploadFiles(payload, filesToUpload, req)
}
// /////////////////////////////////////
// beforeChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
await priorHook
data =
(await hook({
collection: collectionConfig,
context: req.context,
data,
operation: 'update',
originalDoc,
req,
})) || data
}, Promise.resolve())
// /////////////////////////////////////
// beforeChange - Fields
// /////////////////////////////////////
let publishedDocWithLocales = docWithLocales
let versionSnapshotResult
const beforeChangeArgs: Args<DataFromCollectionSlug<TSlug>> = {
id,
collection: collectionConfig,
context: req.context,
data: { ...data, id },
doc: originalDoc,
docWithLocales: undefined,
global: null,
operation: 'update',
req,
skipValidation:
shouldSaveDraft &&
collectionConfig.versions.drafts &&
!collectionConfig.versions.drafts.validate &&
data._status !== 'published',
}
if (publishSpecificLocale) {
versionSnapshotResult = await beforeChange({
...beforeChangeArgs,
data: newFileData,
depth,
docWithLocales,
})
const lastPublished = await getLatestCollectionVersion({
id,
config: collectionConfig,
payload,
published: true,
query: findOneArgs,
req,
})
publishedDocWithLocales = lastPublished ? lastPublished : {}
}
let result = await beforeChange({
...beforeChangeArgs,
docWithLocales: publishedDocWithLocales,
})
// /////////////////////////////////////
// Handle potential password update
// /////////////////////////////////////
const dataToUpdate: Record<string, unknown> = { ...result }
if (shouldSavePassword && typeof password === 'string') {
const { hash, salt } = await generatePasswordSaltHash({
collection: collectionConfig,
password,
req,
})
dataToUpdate.salt = salt
dataToUpdate.hash = hash
delete dataToUpdate.password
delete data.password
}
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft || data._status === 'published') {
result = await req.payload.db.updateOne({
id,
collection: collectionConfig.slug,
data: dataToUpdate,
draftArg,
fallbackLocale,
filesToUpload,
locale,
req,
select,
})
}
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
id,
autosave,
collection: collectionConfig,
docWithLocales: result,
draft: shouldSaveDraft,
overrideAccess,
overrideLock,
payload,
populate,
publishSpecificLocale,
req,
select,
snapshot: versionSnapshotResult,
})
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
collection: collectionConfig,
context: req.context,
depth,
doc: result,
draft: draftArg,
fallbackLocale,
global: null,
locale,
overrideAccess,
populate,
req,
select,
showHiddenFields,
})
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook
result =
(await hook({
collection: collectionConfig,
context: req.context,
doc: result,
req,
})) || result
}, Promise.resolve())
// /////////////////////////////////////
// afterChange - Fields
// /////////////////////////////////////
result = await afterChange({
collection: collectionConfig,
context: req.context,
data,
doc: result,
global: null,
operation: 'update',
previousDoc: originalDoc,
req,
})
// /////////////////////////////////////
// afterChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
await priorHook
result =
(await hook({
collection: collectionConfig,
context: req.context,
doc: result,
operation: 'update',
previousDoc: originalDoc,
req,
})) || result
}, Promise.resolve())
// /////////////////////////////////////
// afterOperation - Collection
// /////////////////////////////////////
result = await buildAfterOperation({
args,
collection: collectionConfig,
operation: 'updateByID',
result,
})
await unlinkTempFiles({
collectionConfig,
config,
req,
})
// /////////////////////////////////////
// afterOperation - Collection
// /////////////////////////////////////
result = (await buildAfterOperation({
args,
collection: collectionConfig,
operation: 'updateByID',
result,
})) as TransformCollectionWithSelect<TSlug, TSelect>
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
@@ -477,7 +210,7 @@ export const updateByIDOperation = async <
await commitTransaction(req)
}
return result as TransformCollectionWithSelect<TSlug, TSelect>
return result
} catch (error: unknown) {
await killTransaction(args.req)
throw error

View File

@@ -0,0 +1,380 @@
import type { DeepPartial } from 'ts-essentials'
import type { Args } from '../../../fields/hooks/beforeChange/index.js'
import type { AccessResult, CollectionSlug, FileToSave, SanitizedConfig } from '../../../index.js'
import type {
Payload,
PayloadRequest,
PopulateType,
SelectType,
TransformCollectionWithSelect,
} from '../../../types/index.js'
import type {
DataFromCollectionSlug,
SanitizedCollectionConfig,
SelectFromCollectionSlug,
} from '../../config/types.js'
import { ensureUsernameOrEmail } from '../../../auth/ensureUsernameOrEmail.js'
import { generatePasswordSaltHash } from '../../../auth/strategies/local/generatePasswordSaltHash.js'
import { combineQueries } from '../../../database/combineQueries.js'
import { afterChange } from '../../../fields/hooks/afterChange/index.js'
import { afterRead } from '../../../fields/hooks/afterRead/index.js'
import { beforeChange } from '../../../fields/hooks/beforeChange/index.js'
import { beforeValidate } from '../../../fields/hooks/beforeValidate/index.js'
import { deleteAssociatedFiles } from '../../../uploads/deleteAssociatedFiles.js'
import { uploadFiles } from '../../../uploads/uploadFiles.js'
import { checkDocumentLockStatus } from '../../../utilities/checkDocumentLockStatus.js'
import { getLatestCollectionVersion } from '../../../versions/getLatestCollectionVersion.js'
import { saveVersion } from '../../../versions/saveVersion.js'
export type SharedUpdateDocumentArgs<TSlug extends CollectionSlug> = {
accessResults: AccessResult
autosave: boolean
collectionConfig: SanitizedCollectionConfig
config: SanitizedConfig
data: DeepPartial<DataFromCollectionSlug<TSlug>>
depth: number
docWithLocales: any
draftArg: boolean
fallbackLocale: string
filesToUpload: FileToSave[]
id: number | string
locale: string
overrideAccess: boolean
overrideLock: boolean
payload: Payload
populate?: PopulateType
publishSpecificLocale?: string
req: PayloadRequest
select: SelectType
showHiddenFields: boolean
}
/**
* This function is used to update a document in the DB and return the result.
*
* It runs the following hooks in order:
* - beforeValidate - Fields
* - beforeValidate - Collection
* - beforeChange - Collection
* - beforeChange - Fields
* - afterRead - Fields
* - afterRead - Collection
* - afterChange - Fields
* - afterChange - Collection
*/
export const updateDocument = async <
TSlug extends CollectionSlug,
TSelect extends SelectFromCollectionSlug<TSlug> = SelectType,
>({
id,
accessResults,
autosave,
collectionConfig,
config,
data,
depth,
docWithLocales,
draftArg,
fallbackLocale,
filesToUpload,
locale,
overrideAccess,
overrideLock,
payload,
populate,
publishSpecificLocale,
req,
select,
showHiddenFields,
}: SharedUpdateDocumentArgs<TSlug>): Promise<TransformCollectionWithSelect<TSlug, TSelect>> => {
const password = data?.password
const shouldSaveDraft =
Boolean(draftArg && collectionConfig.versions.drafts) && data._status !== 'published'
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft)
// /////////////////////////////////////
// Handle potentially locked documents
// /////////////////////////////////////
await checkDocumentLockStatus({
id,
collectionSlug: collectionConfig.slug,
lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,
overrideLock,
req,
})
const originalDoc = await afterRead({
collection: collectionConfig,
context: req.context,
depth: 0,
doc: docWithLocales,
draft: draftArg,
fallbackLocale: id ? null : fallbackLocale,
global: null,
locale,
overrideAccess: true,
req,
showHiddenFields: true,
})
if (collectionConfig.auth) {
ensureUsernameOrEmail<TSlug>({
authOptions: collectionConfig.auth,
collectionSlug: collectionConfig.slug,
data,
operation: 'update',
originalDoc,
req,
})
}
// /////////////////////////////////////
// Delete any associated files
// /////////////////////////////////////
await deleteAssociatedFiles({
collectionConfig,
config,
doc: docWithLocales,
files: filesToUpload,
overrideDelete: false,
req,
})
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
data = await beforeValidate<DeepPartial<DataFromCollectionSlug<TSlug>>>({
id,
collection: collectionConfig,
context: req.context,
data,
doc: originalDoc,
global: null,
operation: 'update',
overrideAccess,
req,
})
// /////////////////////////////////////
// beforeValidate - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
await priorHook
data =
(await hook({
collection: collectionConfig,
context: req.context,
data,
operation: 'update',
originalDoc,
req,
})) || data
}, Promise.resolve())
// /////////////////////////////////////
// Write files to local storage
// /////////////////////////////////////
if (!collectionConfig.upload.disableLocalStorage) {
await uploadFiles(payload, filesToUpload, req)
}
// /////////////////////////////////////
// beforeChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
await priorHook
data =
(await hook({
collection: collectionConfig,
context: req.context,
data,
operation: 'update',
originalDoc,
req,
})) || data
}, Promise.resolve())
// /////////////////////////////////////
// beforeChange - Fields
// /////////////////////////////////////
let publishedDocWithLocales = docWithLocales
let versionSnapshotResult
const beforeChangeArgs: Args<DataFromCollectionSlug<TSlug>> = {
id,
collection: collectionConfig,
context: req.context,
data: { ...data, id },
doc: originalDoc,
docWithLocales: undefined,
global: null,
operation: 'update',
req,
skipValidation:
shouldSaveDraft &&
collectionConfig.versions.drafts &&
!collectionConfig.versions.drafts.validate,
}
if (publishSpecificLocale) {
versionSnapshotResult = await beforeChange({
...beforeChangeArgs,
docWithLocales,
})
const lastPublished = await getLatestCollectionVersion({
id,
config: collectionConfig,
payload,
published: true,
query: {
collection: collectionConfig.slug,
locale,
req,
where: combineQueries({ id: { equals: id } }, accessResults),
},
req,
})
publishedDocWithLocales = lastPublished ? lastPublished : {}
}
let result = await beforeChange({
...beforeChangeArgs,
docWithLocales: publishedDocWithLocales,
})
// /////////////////////////////////////
// Handle potential password update
// /////////////////////////////////////
const dataToUpdate: Record<string, unknown> = { ...result }
if (shouldSavePassword && typeof password === 'string') {
const { hash, salt } = await generatePasswordSaltHash({
collection: collectionConfig,
password,
req,
})
dataToUpdate.salt = salt
dataToUpdate.hash = hash
delete dataToUpdate.password
delete data.password
}
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft) {
result = await req.payload.db.updateOne({
id,
collection: collectionConfig.slug,
data: dataToUpdate,
locale,
req,
select,
})
}
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
id,
autosave,
collection: collectionConfig,
docWithLocales: result,
draft: shouldSaveDraft,
payload,
publishSpecificLocale,
req,
select,
snapshot: versionSnapshotResult,
})
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
collection: collectionConfig,
context: req.context,
depth,
doc: result,
draft: draftArg,
fallbackLocale,
global: null,
locale,
overrideAccess,
populate,
req,
select,
showHiddenFields,
})
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook
result =
(await hook({
collection: collectionConfig,
context: req.context,
doc: result,
req,
})) || result
}, Promise.resolve())
// /////////////////////////////////////
// afterChange - Fields
// /////////////////////////////////////
result = await afterChange({
collection: collectionConfig,
context: req.context,
data,
doc: result,
global: null,
operation: 'update',
previousDoc: originalDoc,
req,
})
// /////////////////////////////////////
// afterChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
await priorHook
result =
(await hook({
collection: collectionConfig,
context: req.context,
doc: result,
operation: 'update',
previousDoc: originalDoc,
req,
})) || result
}, Promise.resolve())
return result as TransformCollectionWithSelect<TSlug, TSelect>
}