diff --git a/packages/payload/src/database/getLocalizedPaths.ts b/packages/payload/src/database/getLocalizedPaths.ts index 4df08731e96..f66168a3eae 100644 --- a/packages/payload/src/database/getLocalizedPaths.ts +++ b/packages/payload/src/database/getLocalizedPaths.ts @@ -45,13 +45,32 @@ export function getLocalizedPaths({ let fieldsToSearch: FlattenedField[] - if (lastIncompletePath?.field && 'flattenedFields' in lastIncompletePath.field) { - fieldsToSearch = lastIncompletePath.field.flattenedFields + let matchedField: FlattenedField + + if (lastIncompletePath?.field?.type === 'blocks') { + if (segment === 'blockType') { + matchedField = { + name: 'blockType', + type: 'text', + } + } else { + for (const block of lastIncompletePath.field.blocks) { + matchedField = block.flattenedFields.find((field) => field.name === segment) + if (matchedField) { + break + } + } + } } else { - fieldsToSearch = lastIncompletePath.fields + if (lastIncompletePath?.field && 'flattenedFields' in lastIncompletePath.field) { + fieldsToSearch = lastIncompletePath.field.flattenedFields + } else { + fieldsToSearch = lastIncompletePath.fields + } + + matchedField = fieldsToSearch.find((field) => field.name === segment) } - const matchedField = fieldsToSearch.find((field) => field.name === segment) lastIncompletePath.field = matchedField if (currentPath === 'globalType' && globalSlug) { @@ -94,7 +113,6 @@ export function getLocalizedPaths({ } switch (matchedField.type) { - case 'blocks': case 'json': case 'richText': { const upcomingSegments = pathSegments.slice(i + 1).join('.') diff --git a/test/relationships/config.ts b/test/relationships/config.ts index aad779663b5..71573c538be 100644 --- a/test/relationships/config.ts +++ b/test/relationships/config.ts @@ -387,6 +387,47 @@ export default buildConfigWithDefaults({ }, ], }, + { + slug: 'deep-nested', + fields: [ + { + type: 'tabs', + tabs: [ + { + name: 'content', + fields: [ + { + type: 'blocks', + name: 'blocks', + blocks: [ + { + slug: 'testBlock', + fields: [ + { + type: 'tabs', + tabs: [ + { + name: 'meta', + fields: [ + { + type: 'relationship', + relationTo: 'movies', + name: 'movie', + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, ], onInit: async (payload) => { await payload.create({ diff --git a/test/relationships/int.spec.ts b/test/relationships/int.spec.ts index 43b9ec429d1..feb05f71b2e 100644 --- a/test/relationships/int.spec.ts +++ b/test/relationships/int.spec.ts @@ -363,6 +363,38 @@ describe('Relationships', () => { expect(docs[0].id).toBe(doc.id) }) + it('should allow querying within tabs-blocks-tabs', async () => { + const movie = await payload.create({ collection: 'movies', data: { name: 'Pulp Fiction' } }) + + const { id } = await payload.create({ + collection: 'deep-nested', + data: { + content: { + blocks: [ + { + blockType: 'testBlock', + meta: { + movie: movie.id, + }, + }, + ], + }, + }, + }) + + const result = await payload.find({ + collection: 'deep-nested', + where: { + 'content.blocks.meta.movie': { + equals: movie.id, + }, + }, + }) + + expect(result.totalDocs).toBe(1) + expect(result.docs[0].id).toBe(id) + }) + describe('Custom ID', () => { it('should query a custom id relation', async () => { const { customIdRelation } = await restClient diff --git a/test/relationships/payload-types.ts b/test/relationships/payload-types.ts index 6cc5ab11efb..e5d08b420e1 100644 --- a/test/relationships/payload-types.ts +++ b/test/relationships/payload-types.ts @@ -28,6 +28,7 @@ export interface Config { 'rels-to-pages': RelsToPage; 'rels-to-pages-and-custom-text-ids': RelsToPagesAndCustomTextId; 'object-writes': ObjectWrite; + 'deep-nested': DeepNested; users: User; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -52,6 +53,7 @@ export interface Config { 'rels-to-pages': RelsToPagesSelect | RelsToPagesSelect; 'rels-to-pages-and-custom-text-ids': RelsToPagesAndCustomTextIdsSelect | RelsToPagesAndCustomTextIdsSelect; 'object-writes': ObjectWritesSelect | ObjectWritesSelect; + 'deep-nested': DeepNestedSelect | DeepNestedSelect; users: UsersSelect | UsersSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -350,6 +352,27 @@ export interface ObjectWrite { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "deep-nested". + */ +export interface DeepNested { + id: string; + content?: { + blocks?: + | { + meta?: { + movie?: (string | null) | Movie; + }; + id?: string | null; + blockName?: string | null; + blockType: 'testBlock'; + }[] + | null; + }; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -425,6 +448,10 @@ export interface PayloadLockedDocument { relationTo: 'object-writes'; value: string | ObjectWrite; } | null) + | ({ + relationTo: 'deep-nested'; + value: string | DeepNested; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -667,6 +694,33 @@ export interface ObjectWritesSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "deep-nested_select". + */ +export interface DeepNestedSelect { + content?: + | T + | { + blocks?: + | T + | { + testBlock?: + | T + | { + meta?: + | T + | { + movie?: T; + }; + id?: T; + blockName?: T; + }; + }; + }; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select".