@r1tsu/payload
Version:
314 lines (313 loc) • 13 kB
JavaScript
import httpStatus from 'http-status';
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 { 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 { buildAfterOperation } from './utils.js';
export const updateOperation = async (incomingArgs)=>{
let args = incomingArgs;
try {
const shouldCommit = await initTransaction(args.req);
// /////////////////////////////////////
// beforeOperation - Collection
// /////////////////////////////////////
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook)=>{
await priorHook;
args = await hook({
args,
collection: args.collection.config,
context: args.req.context,
operation: 'update',
req: args.req
}) || args;
}, Promise.resolve());
const { collection: { config: collectionConfig }, collection, depth, draft: draftArg = false, overrideAccess, overwriteExistingFiles = false, req: { fallbackLocale, locale, payload: { config }, payload }, req, showHiddenFields, where } = args;
if (!where) {
throw new APIError("Missing 'where' query of documents to update.", httpStatus.BAD_REQUEST);
}
const { data: bulkUpdateData } = args;
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts);
// /////////////////////////////////////
// Access
// /////////////////////////////////////
let accessResult;
if (!overrideAccess) {
accessResult = await executeAccess({
req
}, collectionConfig.access.update);
}
await validateQueryPaths({
collectionConfig,
overrideAccess,
req,
where
});
// /////////////////////////////////////
// Retrieve documents
// /////////////////////////////////////
const fullWhere = combineQueries(where, accessResult);
let docs;
if (collectionConfig.versions?.drafts && shouldSaveDraft) {
const versionsWhere = appendVersionToQueryKey(fullWhere);
await validateQueryPaths({
collectionConfig: collection.config,
overrideAccess,
req,
versionFields: buildVersionCollectionFields(collection.config),
where: versionsWhere
});
const query = await payload.db.queryDrafts({
collection: collectionConfig.slug,
locale,
pagination: false,
req,
where: versionsWhere
});
docs = query.docs;
} else {
const query = await payload.db.find({
collection: collectionConfig.slug,
limit: 0,
locale,
pagination: false,
req,
where: fullWhere
});
docs = query.docs;
}
// /////////////////////////////////////
// Generate data for all files and sizes
// /////////////////////////////////////
const { data: newFileData, files: filesToUpload } = await generateFileData({
collection,
config,
data: bulkUpdateData,
overwriteExistingFiles,
req,
throwOnMissingFile: false
});
const errors = [];
const promises = docs.map(async (doc)=>{
const { id } = doc;
let data = {
...newFileData,
...bulkUpdateData
};
try {
const originalDoc = await afterRead({
collection: collectionConfig,
context: req.context,
depth: 0,
doc,
fallbackLocale,
global: null,
locale,
overrideAccess: true,
req,
showHiddenFields: true
});
await deleteAssociatedFiles({
collectionConfig,
config,
doc,
files: filesToUpload,
overrideDelete: false,
req
});
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
data = await beforeValidate({
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: Boolean(collectionConfig.versions?.drafts) && data._status !== 'published'
});
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft || data._status === 'published') {
result = await req.payload.db.updateOne({
id,
collection: collectionConfig.slug,
data: result,
locale,
req
});
}
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
id,
collection: collectionConfig,
docWithLocales: {
...result,
createdAt: doc.createdAt
},
payload,
req
});
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
collection: collectionConfig,
context: req.context,
depth,
doc: result,
fallbackLocale: null,
global: null,
locale,
overrideAccess,
req,
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;
} catch (error) {
errors.push({
id,
message: error.message
});
}
return null;
});
const awaitedDocs = await Promise.all(promises);
let result = {
docs: awaitedDocs.filter(Boolean),
errors
};
// /////////////////////////////////////
// afterOperation - Collection
// /////////////////////////////////////
result = await buildAfterOperation({
args,
collection: collectionConfig,
operation: 'update',
result
});
if (shouldCommit) await commitTransaction(req);
return result;
} catch (error) {
await killTransaction(args.req);
throw error;
}
};
//# sourceMappingURL=update.js.map