feat: support hasMany virtual relationship fields (#13879)

This PR adds support for the following configuration:
```ts
const config = {
  collections: [
    {
      slug: 'categories',
      fields: [
        {
          name: 'title',
          type: 'text',
        },
      ],
    },
    {
      slug: 'posts',
      fields: [
        {
          name: 'title',
          type: 'text',
        },
        {
          name: 'categories',
          type: 'relationship',
          relationTo: 'categories',
          hasMany: true,
        },
      ],
    },
    {
      slug: 'examples',
      fields: [
        {
          name: 'postCategoriesTitles',
          type: 'text',
          virtual: 'post.categories.title',
          // hasMany: true - added automatically during the sanitization
        },
        {
          type: 'relationship',
          relationTo: 'posts',
          name: 'post',
        },
        {
          name: 'postsTitles',
          type: 'text',
          virtual: 'posts.title',
          // hasMany: true - added automatically during the sanitization
        },
        {
          type: 'relationship',
          relationTo: 'posts',
          name: 'posts',
          hasMany: true,
        },
      ],
    },
  ],
}
```

In the result:
`postsTitles` - will be always populated with an array of posts titles.
`postCategoriesTitles` - will be always populated with an array of the
categories titles that are related to this post

The virtual `text` field is sanitizated to `hasMany: true`
automatically, but you can specify that manually as well.
This commit is contained in:
Sasha
2025-09-19 21:04:07 +03:00
committed by GitHub
parent 207caa570c
commit 1072171f97
6 changed files with 232 additions and 23 deletions

View File

@@ -607,6 +607,16 @@ export const getConfig: () => Partial<Config> = () => ({
type: 'text',
virtual: 'post.title',
},
{
name: 'postsTitles',
type: 'text',
virtual: 'posts.title',
},
{
name: 'postCategoriesTitles',
type: 'text',
virtual: 'post.categories.title',
},
{
name: 'postTitleHidden',
type: 'text',
@@ -643,6 +653,12 @@ export const getConfig: () => Partial<Config> = () => ({
type: 'relationship',
relationTo: 'posts',
},
{
name: 'posts',
type: 'relationship',
relationTo: 'posts',
hasMany: true,
},
{
name: 'customID',
type: 'relationship',