fix: incorrect value inside beforeValidate field hooks (#11433)

### What?
`value` within the beforeValidate field hook was not correctly falling
back to the document value when no value was passed inside the request
for the field.

### Why?
The fallback logic was running after the beforeValidate field hooks are
called.

### How?
Run the fallback logic before running the beforeValidate field hooks.

Fixes https://github.com/payloadcms/payload/issues/10923
This commit is contained in:
Jarrod Flesch
2025-02-27 16:00:27 -05:00
committed by GitHub
parent c4bc0ae48a
commit b3e7a9d194
5 changed files with 102 additions and 18 deletions

View File

@@ -0,0 +1,34 @@
import type { CollectionConfig } from 'payload'
export const valueHooksSlug = 'value-hooks'
export const ValueCollection: CollectionConfig = {
slug: valueHooksSlug,
fields: [
{
name: 'slug',
type: 'text',
hooks: {
beforeValidate: [
({ value, siblingData }) => {
siblingData.beforeValidate_value = String(value)
return value
},
],
beforeChange: [
({ value, siblingData }) => {
siblingData.beforeChange_value = String(value)
return value
},
],
},
},
{
name: 'beforeValidate_value',
type: 'text',
},
{
name: 'beforeChange_value',
type: 'text',
},
],
}

View File

@@ -19,6 +19,7 @@ import NestedAfterReadHooks from './collections/NestedAfterReadHooks/index.js'
import Relations from './collections/Relations/index.js'
import TransformHooks from './collections/Transform/index.js'
import Users, { seedHooksUsers } from './collections/Users/index.js'
import { ValueCollection } from './collections/Value/index.js'
import { DataHooksGlobal } from './globals/Data/index.js'
export const HooksConfig: Promise<SanitizedConfig> = buildConfigWithDefaults({
@@ -40,6 +41,7 @@ export const HooksConfig: Promise<SanitizedConfig> = buildConfigWithDefaults({
Users,
DataHooks,
FieldPaths,
ValueCollection,
],
globals: [DataHooksGlobal],
endpoints: [

View File

@@ -21,9 +21,10 @@ import {
import { relationsSlug } from './collections/Relations/index.js'
import { transformSlug } from './collections/Transform/index.js'
import { hooksUsersSlug } from './collections/Users/index.js'
import { beforeValidateSlug, fieldPathsSlug } from './shared.js'
import { valueHooksSlug } from './collections/Value/index.js'
import { HooksConfig } from './config.js'
import { dataHooksGlobalSlug } from './globals/Data/index.js'
import { beforeValidateSlug, fieldPathsSlug } from './shared.js'
let restClient: NextRESTClient
let payload: Payload
@@ -612,6 +613,24 @@ describe('Hooks', () => {
}),
})
})
it('should assign value properly when missing in data', async () => {
const doc = await payload.create({
collection: valueHooksSlug,
data: {
slug: 'test',
},
})
const updatedDoc = await payload.update({
id: doc.id,
collection: valueHooksSlug,
data: {},
})
expect(updatedDoc.beforeValidate_value).toEqual('test')
expect(updatedDoc.beforeChange_value).toEqual('test')
})
})
describe('config level after error hook', () => {

View File

@@ -78,6 +78,7 @@ export interface Config {
'hooks-users': HooksUser;
'data-hooks': DataHook;
'field-paths': FieldPath;
'value-hooks': ValueHook;
'payload-locked-documents': PayloadLockedDocument;
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
@@ -96,6 +97,7 @@ export interface Config {
'hooks-users': HooksUsersSelect<false> | HooksUsersSelect<true>;
'data-hooks': DataHooksSelect<false> | DataHooksSelect<true>;
'field-paths': FieldPathsSelect<false> | FieldPathsSelect<true>;
'value-hooks': ValueHooksSelect<false> | ValueHooksSelect<true>;
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
@@ -610,6 +612,18 @@ export interface FieldPath {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "value-hooks".
*/
export interface ValueHook {
id: string;
slug?: string | null;
beforeValidate_value?: string | null;
beforeChange_value?: string | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents".
@@ -664,6 +678,10 @@ export interface PayloadLockedDocument {
| ({
relationTo: 'field-paths';
value: string | FieldPath;
} | null)
| ({
relationTo: 'value-hooks';
value: string | ValueHook;
} | null);
globalSlug?: string | null;
user: {
@@ -910,6 +928,17 @@ export interface FieldPathsSelect<T extends boolean = true> {
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "value-hooks_select".
*/
export interface ValueHooksSelect<T extends boolean = true> {
slug?: T;
beforeValidate_value?: T;
beforeChange_value?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents_select".