feat(db-mongodb,drizzle): add atomic array operations for relationship fields (#13891)

### What?
This PR adds atomic array operations ($append and $remove) for
relationship fields with `hasMany: true` across all database adapters.
These operations allow developers to add or remove specific items from
relationship arrays without replacing the entire array.

New API:
```
// Append relationships (prevents duplicates)
await payload.db.updateOne({
  collection: 'posts',
  id: 'post123',
  data: {
    categories: { $append: ['featured', 'trending'] }
  }
})

// Remove specific relationships
await payload.db.updateOne({
  collection: 'posts', 
  id: 'post123',
  data: {
    tags: { $remove: ['draft', 'private'] }
  }
})

// Works with polymorphic relationships
await payload.db.updateOne({
  collection: 'posts',
  id: 'post123', 
  data: {
    relatedItems: {
      $append: [
        { relationTo: 'categories', value: 'category-id' },
        { relationTo: 'tags', value: 'tag-id' }
      ]
    }
  }
})
```

### Why?
Currently, updating relationship arrays requires replacing the entire
array which requires fetching existing data before updates. Requiring
more implementation effort and potential for errors when using the API,
in particular for bulk updates.

### How?

#### Cross-Adapter Features:
- Polymorphic relationships: Full support for relationTo:
['collection1', 'collection2']
- Localized relationships: Proper locale handling when fields are
localized
- Duplicate prevention: Ensures `$append` doesn't create duplicates
- Order preservation: Appends to end of array maintaining order
- Bulk operations: Works with `updateMany` for bulk updates

#### MongoDB Implementation:
- Converts `$append` to native `$addToSet` (prevents duplicates in
contrast to `$push`)
- Converts `$remove` to native `$pull` (targeted removal)

#### Drizzle Implementation (Postgres/SQLite):
- Uses optimized batch `INSERT` with duplicate checking for `$append`
- Uses targeted `DELETE` queries for `$remove`
- Implements timestamp-based ordering for performance
- Handles locale columns conditionally based on schema

### Limitations
The current implementation is only on database-adapter level and not
(yet) for the local API. Implementation in the localAPI will be done
separately.
This commit is contained in:
Tobias Odendahl
2025-09-30 19:58:09 +02:00
committed by GitHub
parent 7601835438
commit 7eacd396b1
16 changed files with 1722 additions and 71 deletions

View File

@@ -84,7 +84,7 @@ export interface Config {
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: string;
defaultIDType: number;
};
globals: {
menu: Menu;
@@ -124,13 +124,13 @@ export interface UserAuthOperations {
* via the `definition` "posts".
*/
export interface Post {
id: string;
id: number;
title?: string | null;
content?: {
root: {
type: string;
children: {
type: string;
type: any;
version: number;
[k: string]: unknown;
}[];
@@ -149,7 +149,7 @@ export interface Post {
* via the `definition` "media".
*/
export interface Media {
id: string;
id: number;
updatedAt: string;
createdAt: string;
url?: string | null;
@@ -193,7 +193,7 @@ export interface Media {
* via the `definition` "users".
*/
export interface User {
id: string;
id: number;
updatedAt: string;
createdAt: string;
email: string;
@@ -217,24 +217,24 @@ export interface User {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: string;
id: number;
document?:
| ({
relationTo: 'posts';
value: string | Post;
value: number | Post;
} | null)
| ({
relationTo: 'media';
value: string | Media;
value: number | Media;
} | null)
| ({
relationTo: 'users';
value: string | User;
value: number | User;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
updatedAt: string;
createdAt: string;
@@ -244,10 +244,10 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string;
id: number;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
key?: string | null;
value?:
@@ -267,7 +267,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string;
id: number;
name?: string | null;
batch?: number | null;
updatedAt: string;
@@ -393,7 +393,7 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
* via the `definition` "menu".
*/
export interface Menu {
id: string;
id: number;
globalText?: string | null;
updatedAt?: string | null;
createdAt?: string | null;

View File

@@ -148,6 +148,19 @@ export const getConfig: () => Partial<Config> = () => ({
relationTo: 'categories-custom-id',
name: 'categoryCustomID',
},
{
type: 'relationship',
relationTo: ['categories', 'simple'],
hasMany: true,
name: 'polymorphicRelations',
},
{
type: 'relationship',
relationTo: ['categories', 'simple'],
hasMany: true,
localized: true,
name: 'localizedPolymorphicRelations',
},
{
name: 'localized',
type: 'text',
@@ -188,6 +201,32 @@ export const getConfig: () => Partial<Config> = () => ({
},
],
},
{
type: 'group',
name: 'testNestedGroup',
fields: [
{
name: 'nestedLocalizedPolymorphicRelation',
type: 'relationship',
relationTo: ['categories', 'simple'],
hasMany: true,
localized: true,
},
{
name: 'nestedLocalizedText',
type: 'text',
localized: true,
},
{
name: 'nestedText1',
type: 'text',
},
{
name: 'nestedText2',
type: 'text',
},
],
},
{
type: 'tabs',
tabs: [

View File

@@ -3831,12 +3831,14 @@ describe('database', () => {
// Locales used => no optimized row update => need to pass full data, incuding title
title: 'post',
arrayWithIDsLocalized: {
$push: {
en: {
en: {
$push: {
text: 'some text 2',
id: new mongoose.Types.ObjectId().toHexString(),
},
es: {
},
es: {
$push: {
text: 'some text 2 es',
id: new mongoose.Types.ObjectId().toHexString(),
},
@@ -3845,7 +3847,7 @@ describe('database', () => {
},
collection: 'posts',
id: post.id,
})) as unknown as any
})) as unknown as Post
expect(res.arrayWithIDsLocalized?.en).toHaveLength(2)
expect(res.arrayWithIDsLocalized?.en?.[0]?.text).toBe('some text')
@@ -3972,12 +3974,14 @@ describe('database', () => {
// Locales used => no optimized row update => need to pass full data, incuding title
title: 'post',
arrayWithIDsLocalized: {
$push: {
en: {
en: {
$push: {
text: 'some text 2',
id: new mongoose.Types.ObjectId().toHexString(),
},
es: [
},
es: {
$push: [
{
text: 'some text 2 es',
id: new mongoose.Types.ObjectId().toHexString(),
@@ -4004,6 +4008,781 @@ describe('database', () => {
})
})
describe('relationship $push', () => {
it('should allow appending relationships using $push with single value', async () => {
// First create some category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
// Create a post with initial relationship
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
categories: [cat1.id],
},
depth: 0,
})
expect(post.categories).toHaveLength(1)
expect(post.categories?.[0]).toBe(cat1.id)
// Append another relationship using $push
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
categories: {
$push: cat2.id,
},
},
})) as unknown as Post
expect(result.categories).toHaveLength(2)
// Handle both populated and non-populated relationships
const resultIds = result.categories?.map((cat) => cat as string)
expect(resultIds).toContain(cat1.id)
expect(resultIds).toContain(cat2.id)
})
it('should allow appending relationships using $push with array', async () => {
// Create category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
const cat3 = await payload.create({
collection: 'categories',
data: { title: 'Category 3' },
})
// Create post with initial relationship
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
categories: [cat1.id],
},
})
// Append multiple relationships using $push
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
categories: {
$push: [cat2.id, cat3.id],
},
},
})) as unknown as Post
expect(result.categories).toHaveLength(3)
// Handle both populated and non-populated relationships
const resultIds = result.categories?.map((cat) => cat as string)
expect(resultIds).toContain(cat1.id)
expect(resultIds).toContain(cat2.id)
expect(resultIds).toContain(cat3.id)
})
it('should prevent duplicates when using $push', async () => {
// Create category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
// Create post with initial relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
categories: [cat1.id, cat2.id],
},
})
// Try to append existing relationship - should not create duplicates
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
categories: {
$push: [cat1.id, cat2.id], // Appending existing items
},
},
})) as unknown as Post
expect(result.categories).toHaveLength(2) // Should still be 2, no duplicates
// Handle both populated and non-populated relationships
const resultIds = result.categories?.map((cat) => cat as string)
expect(resultIds).toContain(cat1.id)
expect(resultIds).toContain(cat2.id)
})
it('should work with updateMany for bulk append operations', async () => {
// Create category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
// Create multiple posts with initial relationships
const post1 = await payload.create({
collection: 'posts',
data: {
title: 'Post 1',
categories: [cat1.id],
},
})
const post2 = await payload.create({
collection: 'posts',
data: {
title: 'Post 2',
categories: [cat1.id],
},
})
// Append cat2 to all posts using updateMany
const result = (await payload.db.updateMany({
collection: 'posts',
where: {
id: { in: [post1.id, post2.id] },
},
data: {
categories: {
$push: cat2.id,
},
},
})) as unknown as Post[]
expect(result).toHaveLength(2)
result.forEach((post) => {
expect(post.categories).toHaveLength(2)
const categoryIds = post.categories?.map((cat) => cat as string)
expect(categoryIds).toContain(cat1.id)
expect(categoryIds).toContain(cat2.id)
})
})
it('should append polymorphic relationships using $push', async () => {
// Create a category and simple document for the polymorphic relationship
const category = await payload.create({
collection: 'categories',
data: { title: 'Test Category' },
})
const simple = await payload.create({
collection: 'simple',
data: { text: 'Test Simple' },
})
// Create post with initial polymorphic relationship
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
polymorphicRelations: [
{
relationTo: 'categories',
value: category.id,
},
],
},
depth: 0, // Don't populate relationships
})
expect(post.polymorphicRelations).toHaveLength(1)
expect(post.polymorphicRelations?.[0]).toEqual({
relationTo: 'categories',
value: category.id,
})
// Append another polymorphic relationship using $push
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
polymorphicRelations: {
$push: [
{
relationTo: 'simple',
value: simple.id,
},
],
},
},
})) as unknown as Post
expect(result.polymorphicRelations).toHaveLength(2)
expect(result.polymorphicRelations).toContainEqual({
relationTo: 'categories',
value: category.id,
})
expect(result.polymorphicRelations).toContainEqual({
relationTo: 'simple',
value: simple.id,
})
})
it('should prevent duplicates in polymorphic relationships with $push', async () => {
// Create a category
const category = await payload.create({
collection: 'categories',
data: { title: 'Test Category' },
})
// Create post with polymorphic relationship
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
polymorphicRelations: [
{
relationTo: 'categories',
value: category.id,
},
],
},
depth: 0,
})
// Try to append the same relationship - should not create duplicates
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
polymorphicRelations: {
$push: [
{
relationTo: 'categories',
value: category.id, // Same relationship
},
],
},
},
})) as unknown as Post
expect(result.polymorphicRelations).toHaveLength(1) // Should still be 1, no duplicates
expect(result.polymorphicRelations?.[0]).toEqual({
relationTo: 'categories',
value: category.id,
})
})
it('should handle localized polymorphic relationships with $push', async () => {
// Create documents for testing
const category1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const category2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
// Create post with localized polymorphic relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
localizedPolymorphicRelations: [
{
relationTo: 'categories',
value: category1.id,
},
],
},
depth: 0,
locale: 'en',
})
// Append relationship using $push with correct localized structure
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
localizedPolymorphicRelations: {
en: {
$push: [
{
relationTo: 'categories',
value: category2.id,
},
],
},
},
},
})) as unknown as Post
expect(result.localizedPolymorphicRelations?.en).toHaveLength(2)
expect(result.localizedPolymorphicRelations?.en).toContainEqual({
relationTo: 'categories',
value: category1.id,
})
expect(result.localizedPolymorphicRelations?.en).toContainEqual({
relationTo: 'categories',
value: category2.id,
})
})
it('should handle nested localized polymorphic relationships with $push', async () => {
// Create documents for the polymorphic relationship
const category1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const category2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
// Create a post with nested localized polymorphic relationship
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Nested $push',
testNestedGroup: {
nestedLocalizedPolymorphicRelation: [
{
relationTo: 'categories',
value: category1.id,
},
],
},
},
locale: 'en',
})
// Use low-level API to push new items
await payload.db.updateOne({
collection: 'posts',
where: { id: { equals: post.id } },
data: {
'testNestedGroup.nestedLocalizedPolymorphicRelation': {
en: {
$push: [
{
relationTo: 'categories',
value: category2.id,
},
],
},
},
},
})
// Verify the operation worked
const result = await payload.findByID({
collection: 'posts',
id: post.id,
locale: 'en',
depth: 0,
})
expect(result.testNestedGroup?.nestedLocalizedPolymorphicRelation).toHaveLength(2)
expect(result.testNestedGroup?.nestedLocalizedPolymorphicRelation).toContainEqual({
relationTo: 'categories',
value: category1.id,
})
expect(result.testNestedGroup?.nestedLocalizedPolymorphicRelation).toContainEqual({
relationTo: 'categories',
value: category2.id,
})
})
})
describe('relationship $remove', () => {
it('should allow removing relationships using $remove with single value', async () => {
// Create category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
// Create post with relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
categories: [cat1.id, cat2.id],
},
})
expect(post.categories).toHaveLength(2)
// Remove one relationship using $remove
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
categories: {
$remove: cat1.id,
},
},
})) as unknown as Post
expect(result.categories).toHaveLength(1)
expect(result.categories?.[0]).toBe(cat2.id)
})
it('should allow removing relationships using $remove with array', async () => {
// Create category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
const cat3 = await payload.create({
collection: 'categories',
data: { title: 'Category 3' },
})
// Create post with relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
categories: [cat1.id, cat2.id, cat3.id],
},
})
expect(post.categories).toHaveLength(3)
// Remove multiple relationships using $remove
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
categories: {
$remove: [cat1.id, cat3.id],
},
},
})) as unknown as Post
expect(result.categories).toHaveLength(1)
expect(result.categories?.[0]).toBe(cat2.id)
})
it('should work with updateMany for bulk remove operations', async () => {
// Create category documents
const cat1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const cat2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
const cat3 = await payload.create({
collection: 'categories',
data: { title: 'Category 3' },
})
// Create multiple posts with relationships
const post1 = await payload.create({
collection: 'posts',
data: {
title: 'Post 1',
categories: [cat1.id, cat2.id, cat3.id],
},
})
const post2 = await payload.create({
collection: 'posts',
data: {
title: 'Post 2',
categories: [cat1.id, cat2.id, cat3.id],
},
})
// Remove cat1 and cat3 from all posts using updateMany
const result = (await payload.db.updateMany({
collection: 'posts',
where: {
id: { in: [post1.id, post2.id] },
},
data: {
categories: {
$remove: [cat1.id, cat3.id],
},
},
})) as unknown as Post[]
expect(result).toHaveLength(2)
result.forEach((post) => {
expect(post.categories).toHaveLength(1)
const categoryIds = post.categories?.map((cat) => cat as string)
expect(categoryIds).toContain(cat2.id)
expect(categoryIds).not.toContain(cat1.id)
expect(categoryIds).not.toContain(cat3.id)
})
})
it('should remove polymorphic relationships using $remove', async () => {
// Create documents
const category1 = await payload.create({
collection: 'categories',
data: { title: 'Test Category 1' },
})
const category2 = await payload.create({
collection: 'categories',
data: { title: 'Test Category 2' },
})
// Create post with multiple polymorphic relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
polymorphicRelations: [
{
relationTo: 'categories',
value: category1.id,
},
{
relationTo: 'categories',
value: category2.id,
},
],
},
depth: 0,
})
expect(post.polymorphicRelations).toHaveLength(2)
// Remove one polymorphic relationship using $remove
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
polymorphicRelations: {
$remove: [
{
relationTo: 'categories',
value: category1.id,
},
],
},
},
})) as unknown as Post
expect(result.polymorphicRelations).toHaveLength(1)
expect(result.polymorphicRelations?.[0]).toEqual({
relationTo: 'categories',
value: category2.id,
})
})
it('should remove multiple polymorphic relationships using $remove', async () => {
// Create documents
const category1 = await payload.create({
collection: 'categories',
data: { title: 'Test Category 1' },
})
const category2 = await payload.create({
collection: 'categories',
data: { title: 'Test Category 2' },
})
const simple = await payload.create({
collection: 'simple',
data: { text: 'Test Simple' },
})
// Create post with multiple polymorphic relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
polymorphicRelations: [
{ relationTo: 'categories', value: category1.id },
{ relationTo: 'categories', value: category2.id },
{ relationTo: 'simple', value: simple.id },
],
},
depth: 0,
})
expect(post.polymorphicRelations).toHaveLength(3)
// Remove multiple polymorphic relationships using $remove
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
polymorphicRelations: {
$remove: [
{ relationTo: 'categories', value: category1.id },
{ relationTo: 'simple', value: simple.id },
],
},
},
})) as unknown as Post
expect(result.polymorphicRelations).toHaveLength(1)
expect(result.polymorphicRelations?.[0]).toEqual({
relationTo: 'categories',
value: category2.id,
})
})
it('should handle localized polymorphic relationships with $remove', async () => {
// Create documents for testing
const category1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const category2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
const category3 = await payload.create({
collection: 'categories',
data: { title: 'Category 3' },
})
// Create post with multiple localized polymorphic relationships
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Post',
localizedPolymorphicRelations: [
{ relationTo: 'categories', value: category1.id },
{ relationTo: 'categories', value: category2.id },
{ relationTo: 'categories', value: category3.id },
],
},
depth: 0,
locale: 'en',
})
// Remove relationships using $remove with correct localized structure
const result = (await payload.db.updateOne({
collection: 'posts',
id: post.id,
data: {
localizedPolymorphicRelations: {
en: {
$remove: [
{ relationTo: 'categories', value: category1.id },
{ relationTo: 'categories', value: category3.id },
],
},
},
},
})) as unknown as Post
expect(result.localizedPolymorphicRelations?.en).toHaveLength(1)
expect(result.localizedPolymorphicRelations?.en).toContainEqual({
relationTo: 'categories',
value: category2.id,
})
expect(result.localizedPolymorphicRelations?.en).not.toContainEqual({
relationTo: 'categories',
value: category1.id,
})
expect(result.localizedPolymorphicRelations?.en).not.toContainEqual({
relationTo: 'categories',
value: category3.id,
})
})
it('should handle nested localized polymorphic relationships with $remove', async () => {
// Create documents for the polymorphic relationship
const category1 = await payload.create({
collection: 'categories',
data: { title: 'Category 1' },
})
const category2 = await payload.create({
collection: 'categories',
data: { title: 'Category 2' },
})
const simple1 = await payload.create({
collection: 'simple',
data: { text: 'Simple 1' },
})
// Create a post with multiple items in nested localized polymorphic relationship
const post = await payload.create({
collection: 'posts',
data: {
title: 'Test Nested $remove',
testNestedGroup: {
nestedLocalizedPolymorphicRelation: [
{
relationTo: 'categories',
value: category1.id,
},
{
relationTo: 'categories',
value: category2.id,
},
{
relationTo: 'simple',
value: simple1.id,
},
],
},
},
locale: 'en',
})
// Use low-level API to remove items
await payload.db.updateOne({
collection: 'posts',
where: { id: { equals: post.id } },
data: {
'testNestedGroup.nestedLocalizedPolymorphicRelation': {
en: {
$remove: [
{ relationTo: 'categories', value: category1.id },
{ relationTo: 'simple', value: simple1.id },
],
},
},
},
})
// Verify the operation worked
const result = await payload.findByID({
collection: 'posts',
id: post.id,
locale: 'en',
depth: 0,
})
expect(result.testNestedGroup?.nestedLocalizedPolymorphicRelation).toHaveLength(1)
expect(result.testNestedGroup?.nestedLocalizedPolymorphicRelation?.[0]).toEqual({
relationTo: 'categories',
value: category2.id,
})
})
})
it('should support x3 nesting blocks', async () => {
const res = await payload.create({
collection: 'posts',

View File

@@ -209,6 +209,24 @@ export interface Post {
}[]
| null;
categoryCustomID?: (number | null) | CategoriesCustomId;
polymorphicRelations?:
| ({
relationTo: 'categories';
value: string | Category;
} | {
relationTo: 'simple';
value: string | Simple;
})[]
| null;
localizedPolymorphicRelations?:
| ({
relationTo: 'categories';
value: string | Category;
} | {
relationTo: 'simple';
value: string | Simple;
})[]
| null;
localized?: string | null;
text?: string | null;
number?: number | null;
@@ -234,6 +252,20 @@ export interface Post {
};
};
};
testNestedGroup?: {
nestedLocalizedPolymorphicRelation?:
| ({
relationTo: 'categories';
value: string | Category;
} | {
relationTo: 'simple';
value: string | Simple;
})[]
| null;
nestedLocalizedText?: string | null;
nestedText1?: string | null;
nestedText2?: string | null;
};
hasTransaction?: boolean | null;
throwAfterChange?: boolean | null;
arrayWithIDs?:
@@ -840,6 +872,8 @@ export interface PostsSelect<T extends boolean = true> {
categoryPoly?: T;
categoryPolyMany?: T;
categoryCustomID?: T;
polymorphicRelations?: T;
localizedPolymorphicRelations?: T;
localized?: T;
text?: T;
number?: T;
@@ -1421,6 +1455,6 @@ export interface Auth {
declare module 'payload' {
// @ts-ignore
// @ts-ignore
export interface GeneratedTypes extends Config {}
}
}