payload
Version:
Node, React, Headless CMS and Application Framework built on Next.js
230 lines (229 loc) • 9.4 kB
JavaScript
// @ts-strict-ignore
import { status as 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 { afterRead } from '../../fields/hooks/afterRead/index.js';
import { deleteUserPreferences } from '../../preferences/deleteUserPreferences.js';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles.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 { sanitizeSelect } from '../../utilities/sanitizeSelect.js';
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions.js';
import { deleteScheduledPublishJobs } from '../../versions/deleteScheduledPublishJobs.js';
import { buildAfterOperation } from './utils.js';
export const deleteOperation = async (incomingArgs)=>{
let args = incomingArgs;
try {
const shouldCommit = !args.disableTransaction && await initTransaction(args.req);
// /////////////////////////////////////
// beforeOperation - Collection
// /////////////////////////////////////
if (args.collection.config.hooks?.beforeOperation?.length) {
for (const hook of args.collection.config.hooks.beforeOperation){
args = await hook({
args,
collection: args.collection.config,
context: args.req.context,
operation: 'delete',
req: args.req
}) || args;
}
}
const { collection: { config: collectionConfig }, depth, overrideAccess, overrideLock, populate, req: { fallbackLocale, locale, payload: { config }, payload }, req, select: incomingSelect, showHiddenFields, where } = args;
if (!where) {
throw new APIError("Missing 'where' query of documents to delete.", httpStatus.BAD_REQUEST);
}
// /////////////////////////////////////
// Access
// /////////////////////////////////////
let accessResult;
if (!overrideAccess) {
accessResult = await executeAccess({
req
}, collectionConfig.access.delete);
}
await validateQueryPaths({
collectionConfig,
overrideAccess,
req,
where
});
const fullWhere = combineQueries(where, accessResult);
const select = sanitizeSelect({
forceSelect: collectionConfig.forceSelect,
select: incomingSelect
});
// /////////////////////////////////////
// Retrieve documents
// /////////////////////////////////////
const { docs } = await payload.db.find({
collection: collectionConfig.slug,
locale,
req,
select,
where: fullWhere
});
const errors = [];
const promises = docs.map(async (doc)=>{
let result;
const { id } = doc;
try {
// /////////////////////////////////////
// Handle potentially locked documents
// /////////////////////////////////////
await checkDocumentLockStatus({
id,
collectionSlug: collectionConfig.slug,
lockErrorMessage: `Document with ID ${id} is currently locked and cannot be deleted.`,
overrideLock,
req
});
// /////////////////////////////////////
// beforeDelete - Collection
// /////////////////////////////////////
if (collectionConfig.hooks?.beforeDelete?.length) {
for (const hook of collectionConfig.hooks.beforeDelete){
await hook({
id,
collection: collectionConfig,
context: req.context,
req
});
}
}
await deleteAssociatedFiles({
collectionConfig,
config,
doc,
overrideDelete: true,
req
});
// /////////////////////////////////////
// Delete versions
// /////////////////////////////////////
if (collectionConfig.versions) {
await deleteCollectionVersions({
id,
slug: collectionConfig.slug,
payload,
req
});
}
// /////////////////////////////////////
// Delete scheduled posts
// /////////////////////////////////////
if (collectionConfig.versions?.drafts && collectionConfig.versions.drafts.schedulePublish) {
await deleteScheduledPublishJobs({
id,
slug: collectionConfig.slug,
payload,
req
});
}
// /////////////////////////////////////
// Delete document
// /////////////////////////////////////
await payload.db.deleteOne({
collection: collectionConfig.slug,
req,
returning: false,
where: {
id: {
equals: id
}
}
});
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
collection: collectionConfig,
context: req.context,
depth,
doc: result || doc,
draft: undefined,
fallbackLocale,
global: null,
locale,
overrideAccess,
populate,
req,
select,
showHiddenFields
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
if (collectionConfig.hooks?.afterRead?.length) {
for (const hook of collectionConfig.hooks.afterRead){
result = await hook({
collection: collectionConfig,
context: req.context,
doc: result || doc,
req
}) || result;
}
}
// /////////////////////////////////////
// afterDelete - Collection
// /////////////////////////////////////
if (collectionConfig.hooks?.afterDelete?.length) {
for (const hook of collectionConfig.hooks.afterDelete){
result = await hook({
id,
collection: collectionConfig,
context: req.context,
doc: result,
req
}) || result;
}
}
// /////////////////////////////////////
// 8. Return results
// /////////////////////////////////////
return result;
} catch (error) {
errors.push({
id: doc.id,
message: error.message
});
}
return null;
});
const awaitedDocs = await Promise.all(promises);
// /////////////////////////////////////
// Delete Preferences
// /////////////////////////////////////
await deleteUserPreferences({
collectionConfig,
ids: docs.map(({ id })=>id),
payload,
req
});
let result = {
docs: awaitedDocs.filter(Boolean),
errors
};
// /////////////////////////////////////
// afterOperation - Collection
// /////////////////////////////////////
result = await buildAfterOperation({
args,
collection: collectionConfig,
operation: 'delete',
result
});
if (shouldCommit) {
await commitTransaction(req);
}
return result;
} catch (error) {
await killTransaction(args.req);
throw error;
}
};
//# sourceMappingURL=delete.js.map