UNPKG

@r1tsu/payload

Version:

257 lines (256 loc) 9.66 kB
import httpStatus from 'http-status'; import executeAccess from '../../auth/executeAccess.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 { 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 { buildAfterOperation } from './utils.js'; export const duplicateOperation = async (incomingArgs)=>{ let args = incomingArgs; const operation = 'create'; 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, req: args.req }) || args; }, Promise.resolve()); const { id, collection: { config: collectionConfig }, depth, draft: draftArg = true, overrideAccess, req: { fallbackLocale, locale: localeArg, payload }, req, showHiddenFields } = args; if (!id) { throw new APIError('Missing ID of document to duplicate.', httpStatus.BAD_REQUEST); } const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts); // ///////////////////////////////////// // Read Access // ///////////////////////////////////// const accessResults = !overrideAccess ? await executeAccess({ id, req }, collectionConfig.access.read) : true; const hasWherePolicy = hasWhereAccessResult(accessResults); // ///////////////////////////////////// // Retrieve document // ///////////////////////////////////// const findOneArgs = { collection: collectionConfig.slug, locale: req.locale, req, where: combineQueries({ id: { equals: id } }, accessResults) }; const docWithLocales = await getLatestCollectionVersion({ id, config: collectionConfig, payload, query: findOneArgs, req }); if (!docWithLocales && !hasWherePolicy) throw new NotFound(req.t); if (!docWithLocales && hasWherePolicy) throw new Forbidden(req.t); // remove the createdAt timestamp and id to rely on the db to set the default it delete docWithLocales.createdAt; delete docWithLocales.id; // for version enabled collections, override the current status with draft, unless draft is explicitly set to false if (shouldSaveDraft) { docWithLocales._status = 'draft'; } let result; const originalDoc = await afterRead({ collection: collectionConfig, context: req.context, depth: 0, doc: docWithLocales, fallbackLocale: null, global: null, locale: req.locale, overrideAccess: true, req, showHiddenFields: true }); // ///////////////////////////////////// // Create Access // ///////////////////////////////////// if (!overrideAccess) { await executeAccess({ data: originalDoc, req }, collectionConfig.access.create); } // ///////////////////////////////////// // beforeValidate - Fields // ///////////////////////////////////// let data = await beforeValidate({ id, collection: collectionConfig, context: req.context, data: originalDoc, doc: originalDoc, duplicate: true, global: null, operation, overrideAccess, req }); // ///////////////////////////////////// // beforeValidate - Collection // ///////////////////////////////////// await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook)=>{ await priorHook; data = await hook({ collection: collectionConfig, context: req.context, data, operation, originalDoc, req }) || result; }, Promise.resolve()); // ///////////////////////////////////// // beforeChange - Collection // ///////////////////////////////////// await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook)=>{ await priorHook; data = await hook({ collection: collectionConfig, context: req.context, data, operation, originalDoc: result, req }) || result; }, Promise.resolve()); // ///////////////////////////////////// // beforeChange - Fields // ///////////////////////////////////// result = await beforeChange({ id, collection: collectionConfig, context: req.context, data, doc: originalDoc, docWithLocales, duplicate: true, global: null, operation, req, skipValidation: shouldSaveDraft }); // set req.locale back to the original locale req.locale = localeArg; // ///////////////////////////////////// // Create / Update // ///////////////////////////////////// const versionDoc = await payload.db.create({ collection: collectionConfig.slug, data: result, req }); // ///////////////////////////////////// // Create version // ///////////////////////////////////// if (collectionConfig.versions) { result = await saveVersion({ id: versionDoc.id, collection: collectionConfig, docWithLocales: { ...versionDoc, createdAt: result.createdAt }, draft: shouldSaveDraft, payload, req }); } // ///////////////////////////////////// // afterRead - Fields // ///////////////////////////////////// result = await afterRead({ collection: collectionConfig, context: req.context, depth, doc: versionDoc, fallbackLocale, global: null, locale: localeArg, 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: versionDoc, doc: result, global: null, operation, previousDoc: {}, req }); // ///////////////////////////////////// // afterChange - Collection // ///////////////////////////////////// await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook)=>{ await priorHook; result = await hook({ collection: collectionConfig, context: req.context, doc: result, operation, previousDoc: {}, req }) || result; }, Promise.resolve()); // ///////////////////////////////////// // afterOperation - Collection // ///////////////////////////////////// result = await buildAfterOperation({ args, collection: collectionConfig, operation, result }); // ///////////////////////////////////// // Return results // ///////////////////////////////////// if (shouldCommit) await commitTransaction(req); return result; } catch (error) { await killTransaction(args.req); throw error; } }; //# sourceMappingURL=duplicate.js.map