fix: defaultPopulate and populate with nested to arrays/blocks properties (#9751)
Fixes https://github.com/payloadcms/payload/issues/9718 ### What? `defaultPopulate` and `populate` didn't work properly when defining nested to arrays and blocks properties: ```ts import type { CollectionConfig } from 'payload' export const Pages: CollectionConfig<'pages'> = { slug: 'pages', defaultPopulate: { slug: true, array: { title: true, }, blocks: { some: { title: true, }, }, }, access: { read: () => true }, fields: [ { name: 'slug', type: 'text', required: true, }, { name: 'additional', type: 'text', }, { name: 'array', type: 'array', fields: [ { name: 'title', type: 'text', }, { name: 'other', type: 'text', }, ], }, { name: 'blocks', type: 'blocks', blocks: [ { slug: 'some', fields: [ { name: 'title', type: 'text', }, { name: 'other', type: 'text', }, ], }, ], }, ], } ``` ### Why? This should work ### How? Turns out, it wasn't a great idea to mutate passed `select` directly in `afterRead/promise.ts` to force select some properties `id` , `blockType`. Now we do shallow copies when needed.
This commit is contained in:
@@ -350,10 +350,13 @@ export const promise = async ({
|
||||
case 'array': {
|
||||
const rows = siblingDoc[field.name] as JsonObject
|
||||
|
||||
const arraySelect = select?.[field.name]
|
||||
let arraySelect = select?.[field.name]
|
||||
|
||||
if (selectMode === 'include' && typeof arraySelect === 'object') {
|
||||
arraySelect.id = true
|
||||
arraySelect = {
|
||||
...arraySelect,
|
||||
id: true,
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(rows)) {
|
||||
@@ -427,7 +430,7 @@ export const promise = async ({
|
||||
case 'blocks': {
|
||||
const rows = siblingDoc[field.name]
|
||||
|
||||
const blocksSelect = select?.[field.name]
|
||||
let blocksSelect = select?.[field.name]
|
||||
|
||||
if (Array.isArray(rows)) {
|
||||
rows.forEach((row, i) => {
|
||||
@@ -438,6 +441,10 @@ export const promise = async ({
|
||||
let blockSelectMode = selectMode
|
||||
|
||||
if (typeof blocksSelect === 'object') {
|
||||
blocksSelect = {
|
||||
...blocksSelect,
|
||||
}
|
||||
|
||||
// sanitize blocks: {cta: false} to blocks: {cta: {id: true, blockType: true}}
|
||||
if (selectMode === 'exclude' && blocksSelect[block.slug] === false) {
|
||||
blockSelectMode = 'include'
|
||||
@@ -451,6 +458,10 @@ export const promise = async ({
|
||||
}
|
||||
|
||||
if (typeof blocksSelect[block.slug] === 'object') {
|
||||
blocksSelect[block.slug] = {
|
||||
...(blocksSelect[block.slug] as object),
|
||||
}
|
||||
|
||||
blocksSelect[block.slug]['id'] = true
|
||||
blocksSelect[block.slug]['blockType'] = true
|
||||
}
|
||||
@@ -535,7 +546,6 @@ export const promise = async ({
|
||||
}
|
||||
|
||||
case 'collapsible':
|
||||
|
||||
case 'row': {
|
||||
traverseFields({
|
||||
collection,
|
||||
|
||||
@@ -10,6 +10,14 @@ export const Pages: CollectionConfig<'pages'> = {
|
||||
// I need only slug, NOT the WHOLE CONTENT!
|
||||
defaultPopulate: {
|
||||
slug: true,
|
||||
array: {
|
||||
title: true,
|
||||
},
|
||||
blocks: {
|
||||
some: {
|
||||
title: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
access: { read: () => true },
|
||||
fields: [
|
||||
@@ -85,5 +93,38 @@ export const Pages: CollectionConfig<'pages'> = {
|
||||
name: 'additional',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'array',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'other',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'blocks',
|
||||
type: 'blocks',
|
||||
blocks: [
|
||||
{
|
||||
slug: 'some',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'other',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1781,15 +1781,64 @@ describe('Select', () => {
|
||||
describe('populate / defaultPopulate', () => {
|
||||
let homePage: Page
|
||||
let aboutPage: Page
|
||||
let expectedHomePage: { id: number | string; slug: string }
|
||||
let expectedHomePage: {
|
||||
array: [
|
||||
{
|
||||
id: string
|
||||
title: string
|
||||
},
|
||||
]
|
||||
blocks: [
|
||||
{
|
||||
blockType: string
|
||||
id: string
|
||||
title: string
|
||||
},
|
||||
]
|
||||
id: number | string
|
||||
slug: string
|
||||
}
|
||||
let expectedHomePageOverride: { additional: string; id: number | string }
|
||||
beforeAll(async () => {
|
||||
homePage = await payload.create({
|
||||
depth: 0,
|
||||
collection: 'pages',
|
||||
data: { content: [], slug: 'home', additional: 'additional-data' },
|
||||
data: {
|
||||
content: [],
|
||||
slug: 'home',
|
||||
array: [
|
||||
{
|
||||
title: 'some-title',
|
||||
other: 'other',
|
||||
},
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
blockType: 'some',
|
||||
other: 'other',
|
||||
title: 'some-title',
|
||||
},
|
||||
],
|
||||
additional: 'additional-data',
|
||||
},
|
||||
})
|
||||
expectedHomePage = { id: homePage.id, slug: homePage.slug }
|
||||
expectedHomePage = {
|
||||
id: homePage.id,
|
||||
slug: homePage.slug,
|
||||
array: [
|
||||
{
|
||||
id: homePage.array[0].id,
|
||||
title: homePage.array[0].title,
|
||||
},
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
blockType: homePage.blocks[0].blockType,
|
||||
id: homePage.blocks[0].id,
|
||||
title: homePage.blocks[0].title,
|
||||
},
|
||||
],
|
||||
}
|
||||
expectedHomePageOverride = { id: homePage.id, additional: homePage.additional }
|
||||
aboutPage = await payload.create({
|
||||
depth: 0,
|
||||
|
||||
@@ -309,6 +309,22 @@ export interface Page {
|
||||
| null;
|
||||
slug: string;
|
||||
additional?: string | null;
|
||||
array?:
|
||||
| {
|
||||
title?: string | null;
|
||||
other?: string | null;
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
blocks?:
|
||||
| {
|
||||
title?: string | null;
|
||||
other?: string | null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'some';
|
||||
}[]
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -657,6 +673,25 @@ export interface PagesSelect<T extends boolean = true> {
|
||||
};
|
||||
slug?: T;
|
||||
additional?: T;
|
||||
array?:
|
||||
| T
|
||||
| {
|
||||
title?: T;
|
||||
other?: T;
|
||||
id?: T;
|
||||
};
|
||||
blocks?:
|
||||
| T
|
||||
| {
|
||||
some?:
|
||||
| T
|
||||
| {
|
||||
title?: T;
|
||||
other?: T;
|
||||
id?: T;
|
||||
blockName?: T;
|
||||
};
|
||||
};
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user