From f33f978ef45420a0cce0a77d5317f6cc2ca4d409 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 17 Feb 2026 11:52:40 +0000 Subject: [PATCH] fix: use deepMerge in PublishedAt, fix URLField draft query param, update exports - PublishedAt: replace spread overrides with deepMerge for proper nested merging - URLField: use URL API to correctly append draft param when URL has existing query string - common/index.ts: re-export PublishedAt and URLField from common entry point - Changeset: reword description to match actual PR scope https://claude.ai/code/session_019KQTSWuJGhcoeP1WmXkaLZ --- .changeset/move-fields-directory.md | 2 +- packages/payload-helper/src/common/index.ts | 4 ++++ packages/payload-helper/src/fields/PublishedAt.test.ts | 5 ++++- packages/payload-helper/src/fields/PublishedAt.ts | 6 +++--- packages/payload-helper/src/fields/URLField.test.ts | 10 ++++++++++ packages/payload-helper/src/fields/URLField.ts | 4 +++- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.changeset/move-fields-directory.md b/.changeset/move-fields-directory.md index 5236c093..4f188548 100644 --- a/.changeset/move-fields-directory.md +++ b/.changeset/move-fields-directory.md @@ -2,4 +2,4 @@ '@ainsleydev/payload-helper': patch --- -Add PublishedAt and URLField field helpers, expose via ./fields export path, and fix URLField crash when generate returns undefined +Add PublishedAt and URLField field helpers and expose via ./fields export path diff --git a/packages/payload-helper/src/common/index.ts b/packages/payload-helper/src/common/index.ts index f13e597f..95994eaa 100644 --- a/packages/payload-helper/src/common/index.ts +++ b/packages/payload-helper/src/common/index.ts @@ -1 +1,5 @@ export { SEOFields } from './SEO.js'; +export { PublishedAt } from '../fields/PublishedAt.js'; +export type { PublishedAtArgs } from '../fields/PublishedAt.js'; +export { URLField } from '../fields/URLField.js'; +export type { URLFieldArgs } from '../fields/URLField.js'; diff --git a/packages/payload-helper/src/fields/PublishedAt.test.ts b/packages/payload-helper/src/fields/PublishedAt.test.ts index 373b25eb..b3bc59dd 100644 --- a/packages/payload-helper/src/fields/PublishedAt.test.ts +++ b/packages/payload-helper/src/fields/PublishedAt.test.ts @@ -97,7 +97,7 @@ describe('PublishedAt', () => { }); }); - test('top-level overrides replace admin when admin is overridden', () => { + test('deep merges admin overrides with defaults', () => { const field = PublishedAt({ overrides: { admin: { @@ -110,6 +110,9 @@ describe('PublishedAt', () => { expect((field as DateField).admin).toMatchObject({ position: 'sidebar', description: 'Custom description', + date: { + pickerAppearance: 'dayOnly', + }, }); }); diff --git a/packages/payload-helper/src/fields/PublishedAt.ts b/packages/payload-helper/src/fields/PublishedAt.ts index 68b68e69..448694a9 100644 --- a/packages/payload-helper/src/fields/PublishedAt.ts +++ b/packages/payload-helper/src/fields/PublishedAt.ts @@ -1,4 +1,5 @@ import type { DateField, Field } from 'payload'; +import { deepMerge } from 'payload'; export type PublishedAtArgs = { overrides?: Partial; @@ -13,7 +14,7 @@ export type PublishedAtArgs = { * @param args - Optional arguments to customise the field. */ export const PublishedAt = (args?: PublishedAtArgs): Field => { - return { + const baseField: Field = { name: 'publishedAt', type: 'date', required: true, @@ -23,7 +24,6 @@ export const PublishedAt = (args?: PublishedAtArgs): Field => { date: { pickerAppearance: 'dayOnly', }, - ...args?.overrides?.admin, }, hooks: { beforeChange: [ @@ -35,6 +35,6 @@ export const PublishedAt = (args?: PublishedAtArgs): Field => { }, ], }, - ...args?.overrides, }; + return deepMerge>(baseField, args?.overrides || {}); }; diff --git a/packages/payload-helper/src/fields/URLField.test.ts b/packages/payload-helper/src/fields/URLField.test.ts index 8add605a..0d0f6fde 100644 --- a/packages/payload-helper/src/fields/URLField.test.ts +++ b/packages/payload-helper/src/fields/URLField.test.ts @@ -42,6 +42,16 @@ describe('URLField', () => { expect(result).toBe('https://example.com/page?draft=true'); }); + test('appends draft parameter correctly when URL already has query params', async () => { + const field = URLField({ + generate: () => 'https://example.com/page?foo=bar', + }); + + const hooks = (field as TextField).hooks?.afterRead; + const result = await hooks?.[0]({ draft: true } as unknown as FieldHookArgs); + expect(result).toBe('https://example.com/page?foo=bar&draft=true'); + }); + test('handles async generate function', async () => { const field = URLField({ generate: async () => 'https://example.com/async', diff --git a/packages/payload-helper/src/fields/URLField.ts b/packages/payload-helper/src/fields/URLField.ts index 1b73428f..5921d734 100644 --- a/packages/payload-helper/src/fields/URLField.ts +++ b/packages/payload-helper/src/fields/URLField.ts @@ -30,7 +30,9 @@ export const URLField = ({ generate, overrides }: URLField return url; } if (args.draft) { - return `${url}?draft=true`; + const u = new URL(url); + u.searchParams.set('draft', 'true'); + return u.toString(); } return url; },