From 526e5357639d7a018f04dfa74ffe6a5167b7d2eb Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Wed, 26 Feb 2025 17:05:50 +0200 Subject: [PATCH] fix: ensure custom IDs are returned to the result when `select` query exists (#11400) Previously, behavior with custom IDs and `select` query was incorrect. By default, the `id` field is guaranteed to be selected, even if it doesn't exist in the `select` query, this wasn't true for custom IDs. --- .../src/fields/hooks/afterRead/promise.ts | 2 +- test/select/collections/CustomID/index.ts | 15 +++++ test/select/config.ts | 2 + test/select/int.spec.ts | 59 +++++++++++++++++++ test/select/payload-types.ts | 26 ++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 test/select/collections/CustomID/index.ts diff --git a/packages/payload/src/fields/hooks/afterRead/promise.ts b/packages/payload/src/fields/hooks/afterRead/promise.ts index bbc2787ee0..11abfa4398 100644 --- a/packages/payload/src/fields/hooks/afterRead/promise.ts +++ b/packages/payload/src/fields/hooks/afterRead/promise.ts @@ -123,7 +123,7 @@ export const promise = async ({ } // Strip unselected fields - if (fieldAffectsData(field) && select && selectMode) { + if (fieldAffectsData(field) && select && selectMode && path !== 'id') { if (selectMode === 'include') { if (!select[field.name]) { delete siblingDoc[field.name] diff --git a/test/select/collections/CustomID/index.ts b/test/select/collections/CustomID/index.ts new file mode 100644 index 0000000000..07e08b5221 --- /dev/null +++ b/test/select/collections/CustomID/index.ts @@ -0,0 +1,15 @@ +import type { CollectionConfig } from 'payload' + +export const CustomID: CollectionConfig = { + slug: 'custom-ids', + fields: [ + { + name: 'id', + type: 'number', + }, + { + name: 'text', + type: 'text', + }, + ], +} diff --git a/test/select/config.ts b/test/select/config.ts index 19a6a38f42..f85c16f792 100644 --- a/test/select/config.ts +++ b/test/select/config.ts @@ -4,6 +4,7 @@ import path from 'path' import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' import { devUser } from '../credentials.js' +import { CustomID } from './collections/CustomID/index.js' import { DeepPostsCollection } from './collections/DeepPosts/index.js' import { LocalizedPostsCollection } from './collections/LocalizedPosts/index.js' import { Pages } from './collections/Pages/index.js' @@ -34,6 +35,7 @@ export default buildConfigWithDefaults({ slug: 'rels', fields: [], }, + CustomID, ], globals: [ { diff --git a/test/select/int.spec.ts b/test/select/int.spec.ts index dd8cf4f2c1..d58239672b 100644 --- a/test/select/int.spec.ts +++ b/test/select/int.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'crypto' import path from 'path' import { deepCopyObject, type Payload } from 'payload' import { assert } from 'ts-essentials' @@ -75,6 +76,21 @@ describe('Select', () => { }) }) + it('customID - should select only id as default', async () => { + const { id } = await createCustomID() + + const res = await payload.findByID({ + collection: 'custom-ids', + id, + select: {}, + depth: 0, + }) + + expect(res).toStrictEqual({ + id, + }) + }) + it('should select only number', async () => { const res = await payload.findByID({ collection: 'posts', @@ -91,6 +107,24 @@ describe('Select', () => { }) }) + it('customID - should select only text', async () => { + const { id, text } = await createCustomID() + + const res = await payload.findByID({ + collection: 'custom-ids', + id, + select: { + text: true, + }, + depth: 0, + }) + + expect(res).toStrictEqual({ + id, + text, + }) + }) + it('should select only select', async () => { const res = await payload.findByID({ collection: 'posts', @@ -446,6 +480,25 @@ describe('Select', () => { expect(res).toStrictEqual(expected) }) + it('customID - should exclude text', async () => { + const { id, createdAt, updatedAt } = await createCustomID() + + const res = await payload.findByID({ + collection: 'custom-ids', + id, + select: { + text: false, + }, + depth: 0, + }) + + expect(res).toStrictEqual({ + id, + createdAt, + updatedAt, + }) + }) + it('should exclude number', async () => { const res = await payload.findByID({ collection: 'posts', @@ -2428,3 +2481,9 @@ function createVersionedPost() { function createPoint() { return payload.create({ collection: 'points', data: { text: 'some', point: [10, 20] } }) } + +let id = 1 + +function createCustomID() { + return payload.create({ collection: 'custom-ids', data: { id: id++, text: randomUUID() } }) +} diff --git a/test/select/payload-types.ts b/test/select/payload-types.ts index 7e028f1ee8..adc1d169b3 100644 --- a/test/select/payload-types.ts +++ b/test/select/payload-types.ts @@ -74,6 +74,7 @@ export interface Config { points: Point; upload: Upload; rels: Rel; + 'custom-ids': CustomId; users: User; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -89,6 +90,7 @@ export interface Config { points: PointsSelect | PointsSelect; upload: UploadSelect | UploadSelect; rels: RelsSelect | RelsSelect; + 'custom-ids': CustomIdsSelect | CustomIdsSelect; users: UsersSelect | UsersSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -443,6 +445,16 @@ export interface Point { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "custom-ids". + */ +export interface CustomId { + id: number; + text?: string | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -499,6 +511,10 @@ export interface PayloadLockedDocument { relationTo: 'rels'; value: string | Rel; } | null) + | ({ + relationTo: 'custom-ids'; + value: number | CustomId; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -844,6 +860,16 @@ export interface RelsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "custom-ids_select". + */ +export interface CustomIdsSelect { + id?: T; + text?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select".