Ability to get the "previous" state in the AfterChange Hook (#1115)
Co-authored-by: Alessio Gravili <alessio@bonfireleads.com> Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This commit is contained in:
@@ -79,6 +79,7 @@ export type BeforeChangeHook<T extends TypeWithID = any> = (args: {
|
||||
export type AfterChangeHook<T extends TypeWithID = any> = (args: {
|
||||
doc: T;
|
||||
req: PayloadRequest;
|
||||
previousDoc: T,
|
||||
/**
|
||||
* Hook operation being performed
|
||||
*/
|
||||
|
||||
@@ -252,6 +252,7 @@ async function create(incomingArgs: Arguments): Promise<Document> {
|
||||
result = await afterChange({
|
||||
data,
|
||||
doc: result,
|
||||
previousDoc: {},
|
||||
entityConfig: collectionConfig,
|
||||
operation: 'create',
|
||||
req,
|
||||
@@ -266,6 +267,7 @@ async function create(incomingArgs: Arguments): Promise<Document> {
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
previousDoc: {},
|
||||
req: args.req,
|
||||
operation: 'create',
|
||||
}) || result;
|
||||
|
||||
@@ -94,6 +94,16 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
if (!doc && !hasWherePolicy) throw new NotFound();
|
||||
if (!doc && hasWherePolicy) throw new Forbidden();
|
||||
|
||||
// /////////////////////////////////////
|
||||
// fetch previousDoc
|
||||
// /////////////////////////////////////
|
||||
|
||||
const previousDoc = await payload.findByID({
|
||||
collection: collectionConfig.slug,
|
||||
id: parentDocID,
|
||||
depth,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Update
|
||||
// /////////////////////////////////////
|
||||
@@ -145,6 +155,7 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
result = await afterChange({
|
||||
data: result,
|
||||
doc: result,
|
||||
previousDoc,
|
||||
entityConfig: collectionConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
@@ -160,6 +171,7 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
result = await hook({
|
||||
doc: result,
|
||||
req,
|
||||
previousDoc,
|
||||
operation: 'update',
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
@@ -308,6 +308,7 @@ async function update(incomingArgs: Arguments): Promise<Document> {
|
||||
result = await afterChange({
|
||||
data,
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
@@ -322,6 +323,7 @@ async function update(incomingArgs: Arguments): Promise<Document> {
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
req,
|
||||
operation: 'update',
|
||||
}) || result;
|
||||
|
||||
@@ -16,6 +16,10 @@ export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = {
|
||||
findMany?: boolean
|
||||
/** The full original document in `update` operations. In the `afterChange` hook, this is the resulting document of the operation. */
|
||||
originalDoc?: T,
|
||||
/** The document before changes were applied, only in `afterChange` hooks. */
|
||||
previousDoc?: T,
|
||||
/** The sibling data from the previous document in `afterChange` hook. */
|
||||
previousSiblingDoc?: T,
|
||||
/** A string relating to which operation the field type is currently executing within. Useful within beforeValidate, beforeChange, and afterChange hooks to differentiate between create and update operations. */
|
||||
operation?: 'create' | 'read' | 'update' | 'delete',
|
||||
/** The Express request object. It is mocked for Local API operations. */
|
||||
@@ -24,6 +28,7 @@ export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = {
|
||||
siblingData: Partial<S>
|
||||
/** The value of the field. */
|
||||
value?: P,
|
||||
previousValue?: P,
|
||||
}
|
||||
|
||||
export type FieldHook<T extends TypeWithID = any, P = any, S = any> = (args: FieldHookArgs<T, P, S>) => Promise<P> | P;
|
||||
|
||||
@@ -7,6 +7,7 @@ import deepCopyObject from '../../../utilities/deepCopyObject';
|
||||
type Args = {
|
||||
data: Record<string, unknown>
|
||||
doc: Record<string, unknown>
|
||||
previousDoc: Record<string, unknown>
|
||||
entityConfig: SanitizedCollectionConfig | SanitizedGlobalConfig
|
||||
operation: 'create' | 'update'
|
||||
req: PayloadRequest
|
||||
@@ -15,6 +16,7 @@ type Args = {
|
||||
export const afterChange = async ({
|
||||
data,
|
||||
doc: incomingDoc,
|
||||
previousDoc,
|
||||
entityConfig,
|
||||
operation,
|
||||
req,
|
||||
@@ -24,9 +26,11 @@ export const afterChange = async ({
|
||||
await traverseFields({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
fields: entityConfig.fields,
|
||||
operation,
|
||||
req,
|
||||
previousSiblingDoc: previousDoc,
|
||||
siblingDoc: doc,
|
||||
siblingData: data,
|
||||
});
|
||||
|
||||
@@ -6,6 +6,8 @@ import { traverseFields } from './traverseFields';
|
||||
type Args = {
|
||||
data: Record<string, unknown>
|
||||
doc: Record<string, unknown>
|
||||
previousDoc: Record<string, unknown>
|
||||
previousSiblingDoc: Record<string, unknown>
|
||||
field: Field | TabAsField
|
||||
operation: 'create' | 'update'
|
||||
req: PayloadRequest
|
||||
@@ -19,6 +21,8 @@ type Args = {
|
||||
export const promise = async ({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc,
|
||||
field,
|
||||
operation,
|
||||
req,
|
||||
@@ -34,6 +38,9 @@ export const promise = async ({
|
||||
const hookedValue = await currentHook({
|
||||
value: siblingData[field.name],
|
||||
originalDoc: doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc,
|
||||
previousValue: previousDoc[field.name],
|
||||
data,
|
||||
siblingData,
|
||||
operation,
|
||||
@@ -53,6 +60,8 @@ export const promise = async ({
|
||||
await traverseFields({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: previousDoc[field.name] as Record<string, unknown>,
|
||||
fields: field.fields,
|
||||
operation,
|
||||
req,
|
||||
@@ -72,6 +81,8 @@ export const promise = async ({
|
||||
promises.push(traverseFields({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: previousDoc[field.name]?.[i] || {} as Record<string, unknown>,
|
||||
fields: field.fields,
|
||||
operation,
|
||||
req,
|
||||
@@ -96,6 +107,8 @@ export const promise = async ({
|
||||
promises.push(traverseFields({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: previousDoc[field.name]?.[i] || {} as Record<string, unknown>,
|
||||
fields: block.fields,
|
||||
operation,
|
||||
req,
|
||||
@@ -115,6 +128,8 @@ export const promise = async ({
|
||||
await traverseFields({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: { ...previousSiblingDoc },
|
||||
fields: field.fields,
|
||||
operation,
|
||||
req,
|
||||
@@ -128,10 +143,12 @@ export const promise = async ({
|
||||
case 'tab': {
|
||||
let tabSiblingData = siblingData;
|
||||
let tabSiblingDoc = siblingDoc;
|
||||
let tabPreviousSiblingDoc = siblingDoc;
|
||||
|
||||
if (tabHasName(field)) {
|
||||
tabSiblingData = siblingData[field.name] as Record<string, unknown>;
|
||||
tabSiblingDoc = siblingDoc[field.name] as Record<string, unknown>;
|
||||
tabPreviousSiblingDoc = previousDoc[field.name] as Record<string, unknown>;
|
||||
}
|
||||
|
||||
await traverseFields({
|
||||
@@ -140,6 +157,8 @@ export const promise = async ({
|
||||
fields: field.fields,
|
||||
operation,
|
||||
req,
|
||||
previousSiblingDoc: tabPreviousSiblingDoc,
|
||||
previousDoc,
|
||||
siblingData: tabSiblingData,
|
||||
siblingDoc: tabSiblingDoc,
|
||||
});
|
||||
@@ -151,6 +170,8 @@ export const promise = async ({
|
||||
await traverseFields({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: { ...previousSiblingDoc },
|
||||
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
|
||||
operation,
|
||||
req,
|
||||
|
||||
@@ -5,6 +5,8 @@ import { PayloadRequest } from '../../../express/types';
|
||||
type Args = {
|
||||
data: Record<string, unknown>
|
||||
doc: Record<string, unknown>
|
||||
previousDoc: Record<string, unknown>
|
||||
previousSiblingDoc: Record<string, unknown>
|
||||
fields: (Field | TabAsField)[]
|
||||
operation: 'create' | 'update'
|
||||
req: PayloadRequest
|
||||
@@ -15,6 +17,8 @@ type Args = {
|
||||
export const traverseFields = async ({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc,
|
||||
fields,
|
||||
operation,
|
||||
req,
|
||||
@@ -27,6 +31,8 @@ export const traverseFields = async ({
|
||||
promises.push(promise({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc,
|
||||
field,
|
||||
operation,
|
||||
req,
|
||||
|
||||
@@ -24,6 +24,7 @@ export type BeforeChangeHook = (args: {
|
||||
|
||||
export type AfterChangeHook = (args: {
|
||||
doc: any;
|
||||
previousDoc: any;
|
||||
req: PayloadRequest;
|
||||
}) => any;
|
||||
|
||||
|
||||
@@ -58,6 +58,15 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
|
||||
rawVersion = rawVersion.toJSON({ virtuals: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// fetch previousDoc
|
||||
// /////////////////////////////////////
|
||||
|
||||
const previousDoc = await payload.findGlobal({
|
||||
slug: globalConfig.slug,
|
||||
depth,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Update global
|
||||
// /////////////////////////////////////
|
||||
@@ -118,6 +127,7 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
result = await afterChange({
|
||||
data: result,
|
||||
doc: result,
|
||||
previousDoc,
|
||||
entityConfig: globalConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
@@ -132,6 +142,7 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
previousDoc,
|
||||
req,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
@@ -239,6 +239,7 @@ async function update<T extends TypeWithID = any>(args: Args): Promise<T> {
|
||||
|
||||
global = await hook({
|
||||
doc: global,
|
||||
previousDoc: originalDoc,
|
||||
req,
|
||||
}) || global;
|
||||
}, Promise.resolve());
|
||||
@@ -250,6 +251,7 @@ async function update<T extends TypeWithID = any>(args: Args): Promise<T> {
|
||||
global = await afterChange({
|
||||
data,
|
||||
doc: global,
|
||||
previousDoc: originalDoc,
|
||||
entityConfig: globalConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
@@ -264,6 +266,7 @@ async function update<T extends TypeWithID = any>(args: Args): Promise<T> {
|
||||
|
||||
global = await hook({
|
||||
doc: global,
|
||||
previousDoc: originalDoc,
|
||||
req,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
Reference in New Issue
Block a user