feat: join field with polymorphic relationships (#9990)
### What? The join field had a limitation imposed that prevents it from targeting polymorphic relationship fields. With this change we can support any relationship fields. ### Why? Improves the functionality of join field. ### How? Extended the database adapters and removed the config sanitization that would throw an error when polymorphic relationships were used. Fixes #
This commit is contained in:
@@ -81,6 +81,11 @@ export const buildJoinAggregation = async ({
|
||||
})
|
||||
}
|
||||
|
||||
let polymorphicSuffix = ''
|
||||
if (Array.isArray(join.targetField.relationTo)) {
|
||||
polymorphicSuffix = '.value'
|
||||
}
|
||||
|
||||
if (adapter.payload.config.localization && locale === 'all') {
|
||||
adapter.payload.config.localization.localeCodes.forEach((code) => {
|
||||
const as = `${versions ? `version.${join.joinPath}` : join.joinPath}${code}`
|
||||
@@ -89,7 +94,7 @@ export const buildJoinAggregation = async ({
|
||||
{
|
||||
$lookup: {
|
||||
as: `${as}.docs`,
|
||||
foreignField: `${join.field.on}${code}`,
|
||||
foreignField: `${join.field.on}${code}${polymorphicSuffix}`,
|
||||
from: adapter.collections[slug].collection.name,
|
||||
localField: versions ? 'parent' : '_id',
|
||||
pipeline,
|
||||
@@ -130,7 +135,7 @@ export const buildJoinAggregation = async ({
|
||||
{
|
||||
$lookup: {
|
||||
as: `${as}.docs`,
|
||||
foreignField: `${join.field.on}${localeSuffix}`,
|
||||
foreignField: `${join.field.on}${localeSuffix}${polymorphicSuffix}`,
|
||||
from: adapter.collections[slug].collection.name,
|
||||
localField: versions ? 'parent' : '_id',
|
||||
pipeline,
|
||||
|
||||
@@ -17,6 +17,7 @@ export const find: Find = async function find(
|
||||
|
||||
return findMany({
|
||||
adapter: this,
|
||||
collectionSlug: collectionConfig.slug,
|
||||
fields: collectionConfig.flattenedFields,
|
||||
joins,
|
||||
limit,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { traverseFields } from './traverseFields.js'
|
||||
|
||||
type BuildFindQueryArgs = {
|
||||
adapter: DrizzleAdapter
|
||||
collectionSlug?: string
|
||||
depth: number
|
||||
fields: FlattenedField[]
|
||||
joinQuery?: JoinQuery
|
||||
@@ -32,6 +33,7 @@ export type Result = {
|
||||
// a collection field structure
|
||||
export const buildFindManyArgs = ({
|
||||
adapter,
|
||||
collectionSlug,
|
||||
depth,
|
||||
fields,
|
||||
joinQuery,
|
||||
@@ -74,6 +76,7 @@ export const buildFindManyArgs = ({
|
||||
traverseFields({
|
||||
_locales,
|
||||
adapter,
|
||||
collectionSlug,
|
||||
currentArgs: result,
|
||||
currentTableName: tableName,
|
||||
depth,
|
||||
|
||||
@@ -13,6 +13,7 @@ import { buildFindManyArgs } from './buildFindManyArgs.js'
|
||||
|
||||
type Args = {
|
||||
adapter: DrizzleAdapter
|
||||
collectionSlug?: string
|
||||
fields: FlattenedField[]
|
||||
tableName: string
|
||||
versions?: boolean
|
||||
@@ -20,6 +21,7 @@ type Args = {
|
||||
|
||||
export const findMany = async function find({
|
||||
adapter,
|
||||
collectionSlug,
|
||||
fields,
|
||||
joins: joinQuery,
|
||||
limit: limitArg,
|
||||
@@ -70,6 +72,7 @@ export const findMany = async function find({
|
||||
|
||||
const findManyArgs = buildFindManyArgs({
|
||||
adapter,
|
||||
collectionSlug,
|
||||
depth: 0,
|
||||
fields,
|
||||
joinQuery,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { chainMethods } from './chainMethods.js'
|
||||
type TraverseFieldArgs = {
|
||||
_locales: Result
|
||||
adapter: DrizzleAdapter
|
||||
collectionSlug?: string
|
||||
currentArgs: Result
|
||||
currentTableName: string
|
||||
depth?: number
|
||||
@@ -42,6 +43,7 @@ type TraverseFieldArgs = {
|
||||
export const traverseFields = ({
|
||||
_locales,
|
||||
adapter,
|
||||
collectionSlug,
|
||||
currentArgs,
|
||||
currentTableName,
|
||||
depth,
|
||||
@@ -292,6 +294,7 @@ export const traverseFields = ({
|
||||
traverseFields({
|
||||
_locales,
|
||||
adapter,
|
||||
collectionSlug,
|
||||
currentArgs,
|
||||
currentTableName,
|
||||
depth,
|
||||
@@ -357,13 +360,26 @@ export const traverseFields = ({
|
||||
? adapter.tables[currentTableName].parent
|
||||
: adapter.tables[currentTableName].id
|
||||
|
||||
let joinQueryWhere: Where = {
|
||||
[field.on]: {
|
||||
equals: rawConstraint(currentIDColumn),
|
||||
},
|
||||
let joinQueryWhere: Where
|
||||
|
||||
if (Array.isArray(field.targetField.relationTo)) {
|
||||
joinQueryWhere = {
|
||||
[field.on]: {
|
||||
equals: {
|
||||
relationTo: collectionSlug,
|
||||
value: rawConstraint(currentIDColumn),
|
||||
},
|
||||
},
|
||||
}
|
||||
} else {
|
||||
joinQueryWhere = {
|
||||
[field.on]: {
|
||||
equals: rawConstraint(currentIDColumn),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (where) {
|
||||
if (where && Object.keys(where).length) {
|
||||
joinQueryWhere = {
|
||||
and: [joinQueryWhere, where],
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export async function findOne<T extends TypeWithID>(
|
||||
|
||||
const { docs } = await findMany({
|
||||
adapter: this,
|
||||
collectionSlug: collection,
|
||||
fields: collectionConfig.flattenedFields,
|
||||
joins,
|
||||
limit: 1,
|
||||
|
||||
@@ -142,6 +142,12 @@ export const sanitizeQueryValue = ({
|
||||
collection: adapter.payload.collections[val.relationTo],
|
||||
})
|
||||
|
||||
if (isRawConstraint(val.value)) {
|
||||
return {
|
||||
operator,
|
||||
value: val.value.value,
|
||||
}
|
||||
}
|
||||
return {
|
||||
operator,
|
||||
value: idType === 'number' ? Number(val.value) : String(val.value),
|
||||
|
||||
@@ -21,6 +21,7 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
|
||||
|
||||
const result = await findMany({
|
||||
adapter: this,
|
||||
collectionSlug: collection,
|
||||
fields,
|
||||
joins,
|
||||
limit,
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
ClientField,
|
||||
Field,
|
||||
FieldBase,
|
||||
JoinFieldClient,
|
||||
LabelsClient,
|
||||
RadioFieldClient,
|
||||
RowFieldClient,
|
||||
@@ -229,6 +230,16 @@ export const createClientField = ({
|
||||
break
|
||||
}
|
||||
|
||||
case 'join': {
|
||||
const field = clientField as JoinFieldClient
|
||||
|
||||
field.targetField = {
|
||||
relationTo: field.targetField.relationTo,
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'radio':
|
||||
// falls through
|
||||
case 'select': {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SanitizedJoin, SanitizedJoins } from '../../collections/config/types.js'
|
||||
import type { Config } from '../../config/types.js'
|
||||
import type { JoinField, RelationshipField, UploadField } from './types.js'
|
||||
import type { FlattenedJoinField, JoinField, RelationshipField, UploadField } from './types.js'
|
||||
|
||||
import { APIError } from '../../errors/index.js'
|
||||
import { InvalidFieldJoin } from '../../errors/InvalidFieldJoin.js'
|
||||
@@ -12,7 +12,7 @@ export const sanitizeJoinField = ({
|
||||
joins,
|
||||
}: {
|
||||
config: Config
|
||||
field: JoinField
|
||||
field: FlattenedJoinField | JoinField
|
||||
joinPath?: string
|
||||
joins?: SanitizedJoins
|
||||
}) => {
|
||||
@@ -74,9 +74,6 @@ export const sanitizeJoinField = ({
|
||||
if (!joinRelationship) {
|
||||
throw new InvalidFieldJoin(join.field)
|
||||
}
|
||||
if (Array.isArray(joinRelationship.relationTo)) {
|
||||
throw new APIError('Join fields cannot be used with polymorphic relationships.')
|
||||
}
|
||||
|
||||
join.targetField = joinRelationship
|
||||
|
||||
@@ -85,6 +82,9 @@ export const sanitizeJoinField = ({
|
||||
// override the join field hasMany property to use whatever the relationship field has
|
||||
field.hasMany = joinRelationship.hasMany
|
||||
|
||||
// @ts-expect-error converting JoinField to FlattenedJoinField to track targetField
|
||||
field.targetField = join.targetField
|
||||
|
||||
if (!joins[field.collection]) {
|
||||
joins[field.collection] = [join]
|
||||
} else {
|
||||
|
||||
@@ -1425,7 +1425,7 @@ export type JoinField = {
|
||||
export type JoinFieldClient = {
|
||||
admin?: AdminClient &
|
||||
Pick<JoinField['admin'], 'allowCreate' | 'defaultColumns' | 'disableBulkEdit' | 'readOnly'>
|
||||
} & FieldBaseClient &
|
||||
} & { targetField: Pick<RelationshipFieldClient, 'relationTo'> } & FieldBaseClient &
|
||||
Pick<
|
||||
JoinField,
|
||||
'collection' | 'defaultLimit' | 'defaultSort' | 'index' | 'maxDepth' | 'on' | 'type' | 'where'
|
||||
@@ -1451,6 +1451,10 @@ export type FlattenedTabAsField = {
|
||||
flattenedFields: FlattenedField[]
|
||||
} & MarkRequired<TabAsField, 'name'>
|
||||
|
||||
export type FlattenedJoinField = {
|
||||
targetField: RelationshipField | UploadField
|
||||
} & JoinField
|
||||
|
||||
export type FlattenedField =
|
||||
| CheckboxField
|
||||
| CodeField
|
||||
@@ -1459,8 +1463,8 @@ export type FlattenedField =
|
||||
| FlattenedArrayField
|
||||
| FlattenedBlocksField
|
||||
| FlattenedGroupField
|
||||
| FlattenedJoinField
|
||||
| FlattenedTabAsField
|
||||
| JoinField
|
||||
| JSONField
|
||||
| NumberField
|
||||
| PointField
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Field, FlattenedField } from '../fields/config/types.js'
|
||||
import type { Field, FlattenedField, FlattenedJoinField } from '../fields/config/types.js'
|
||||
|
||||
import { tabHasName } from '../fields/config/types.js'
|
||||
|
||||
@@ -36,6 +36,11 @@ export const flattenAllFields = ({ fields }: { fields: Field[] }): FlattenedFiel
|
||||
break
|
||||
}
|
||||
|
||||
case 'join': {
|
||||
result.push(field as FlattenedJoinField)
|
||||
break
|
||||
}
|
||||
|
||||
case 'tabs': {
|
||||
for (const tab of field.tabs) {
|
||||
if (!tabHasName(tab)) {
|
||||
|
||||
@@ -61,7 +61,6 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
|
||||
relationTo,
|
||||
} = props
|
||||
const [Table, setTable] = useState<React.ReactNode>(null)
|
||||
|
||||
const { getEntityConfig } = useConfig()
|
||||
|
||||
const { permissions } = useAuth()
|
||||
|
||||
@@ -29,10 +29,12 @@ const ObjectId = (ObjectIdImport.default ||
|
||||
* Recursively builds the default data for joined collection
|
||||
*/
|
||||
const getInitialDrawerData = ({
|
||||
collectionSlug,
|
||||
docID,
|
||||
fields,
|
||||
segments,
|
||||
}: {
|
||||
collectionSlug: string
|
||||
docID: number | string
|
||||
fields: ClientField[]
|
||||
segments: string[]
|
||||
@@ -48,9 +50,15 @@ const getInitialDrawerData = ({
|
||||
}
|
||||
|
||||
if (field.type === 'relationship' || field.type === 'upload') {
|
||||
let value: { relationTo: string; value: number | string } | number | string = docID
|
||||
if (Array.isArray(field.relationTo)) {
|
||||
value = {
|
||||
relationTo: collectionSlug,
|
||||
value: docID,
|
||||
}
|
||||
}
|
||||
return {
|
||||
// TODO: Handle polymorphic https://github.com/payloadcms/payload/pull/9990
|
||||
[field.name]: field.hasMany ? [docID] : docID,
|
||||
[field.name]: field.hasMany ? [value] : value,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +66,18 @@ const getInitialDrawerData = ({
|
||||
|
||||
if (field.type === 'tab' || field.type === 'group') {
|
||||
return {
|
||||
[field.name]: getInitialDrawerData({ docID, fields: field.fields, segments: nextSegments }),
|
||||
[field.name]: getInitialDrawerData({
|
||||
collectionSlug,
|
||||
docID,
|
||||
fields: field.fields,
|
||||
segments: nextSegments,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'array') {
|
||||
const initialData = getInitialDrawerData({
|
||||
collectionSlug,
|
||||
docID,
|
||||
fields: field.fields,
|
||||
segments: nextSegments,
|
||||
@@ -79,6 +93,7 @@ const getInitialDrawerData = ({
|
||||
if (field.type === 'blocks') {
|
||||
for (const block of field.blocks) {
|
||||
const blockInitialData = getInitialDrawerData({
|
||||
collectionSlug,
|
||||
docID,
|
||||
fields: block.fields,
|
||||
segments: nextSegments,
|
||||
@@ -110,7 +125,7 @@ const JoinFieldComponent: JoinFieldClientComponent = (props) => {
|
||||
path,
|
||||
} = props
|
||||
|
||||
const { id: docID } = useDocumentInfo()
|
||||
const { id: docID, docConfig } = useDocumentInfo()
|
||||
|
||||
const {
|
||||
config: { collections },
|
||||
@@ -126,9 +141,18 @@ const JoinFieldComponent: JoinFieldClientComponent = (props) => {
|
||||
return null
|
||||
}
|
||||
|
||||
let value: { relationTo: string; value: number | string } | number | string = docID
|
||||
|
||||
if (Array.isArray(field.targetField.relationTo)) {
|
||||
value = {
|
||||
relationTo: docConfig.slug,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
const where = {
|
||||
[on]: {
|
||||
equals: docID,
|
||||
equals: value,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -139,17 +163,18 @@ const JoinFieldComponent: JoinFieldClientComponent = (props) => {
|
||||
}
|
||||
|
||||
return where
|
||||
}, [docID, on, field.where])
|
||||
}, [docID, field.targetField.relationTo, field.where, on, docConfig.slug])
|
||||
|
||||
const initialDrawerData = useMemo(() => {
|
||||
const relatedCollection = collections.find((collection) => collection.slug === field.collection)
|
||||
|
||||
return getInitialDrawerData({
|
||||
collectionSlug: docConfig.slug,
|
||||
docID,
|
||||
fields: relatedCollection.fields,
|
||||
segments: field.on.split('.'),
|
||||
})
|
||||
}, [collections, field.on, docID, field.collection])
|
||||
}, [collections, field.on, field.collection, docConfig.slug, docID])
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -115,6 +115,30 @@ export const Categories: CollectionConfig = {
|
||||
collection: 'posts',
|
||||
on: 'blocks.category',
|
||||
},
|
||||
{
|
||||
name: 'polymorphic',
|
||||
type: 'join',
|
||||
collection: postsSlug,
|
||||
on: 'polymorphic',
|
||||
},
|
||||
{
|
||||
name: 'polymorphics',
|
||||
type: 'join',
|
||||
collection: postsSlug,
|
||||
on: 'polymorphics',
|
||||
},
|
||||
{
|
||||
name: 'localizedPolymorphic',
|
||||
type: 'join',
|
||||
collection: postsSlug,
|
||||
on: 'localizedPolymorphic',
|
||||
},
|
||||
{
|
||||
name: 'localizedPolymorphics',
|
||||
type: 'join',
|
||||
collection: postsSlug,
|
||||
on: 'localizedPolymorphics',
|
||||
},
|
||||
{
|
||||
name: 'singulars',
|
||||
type: 'join',
|
||||
|
||||
@@ -53,6 +53,30 @@ export const Posts: CollectionConfig = {
|
||||
hasMany: true,
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'polymorphic',
|
||||
type: 'relationship',
|
||||
relationTo: ['categories', 'users'],
|
||||
},
|
||||
{
|
||||
name: 'polymorphics',
|
||||
type: 'relationship',
|
||||
relationTo: ['categories', 'users'],
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'localizedPolymorphic',
|
||||
type: 'relationship',
|
||||
relationTo: ['categories', 'users'],
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'localizedPolymorphics',
|
||||
type: 'relationship',
|
||||
relationTo: ['categories', 'users'],
|
||||
hasMany: true,
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'group',
|
||||
type: 'group',
|
||||
|
||||
@@ -291,6 +291,67 @@ test.describe('Join Field', () => {
|
||||
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 1 Updated')
|
||||
})
|
||||
|
||||
test('should create join collection from polymorphic relationships', async () => {
|
||||
await page.goto(categoriesURL.edit(categoryID))
|
||||
const joinField = page.locator('#field-polymorphic.field-type.join')
|
||||
await expect(joinField).toBeVisible()
|
||||
await joinField.locator('.relationship-table__add-new').click()
|
||||
const drawer = page.locator('[id^=doc-drawer_posts_1_]')
|
||||
await expect(drawer).toBeVisible()
|
||||
const titleField = drawer.locator('#field-title')
|
||||
await expect(titleField).toBeVisible()
|
||||
await titleField.fill('Test polymorphic Post')
|
||||
await expect(drawer.locator('#field-polymorphic')).toContainText('example')
|
||||
await drawer.locator('button[id="action-save"]').click()
|
||||
await expect(drawer).toBeHidden()
|
||||
await expect(joinField.locator('tbody .row-1')).toContainText('Test polymorphic Post')
|
||||
})
|
||||
test('should create join collection from polymorphic, hasMany relationships', async () => {
|
||||
await page.goto(categoriesURL.edit(categoryID))
|
||||
const joinField = page.locator('#field-polymorphics.field-type.join')
|
||||
await expect(joinField).toBeVisible()
|
||||
await joinField.locator('.relationship-table__add-new').click()
|
||||
const drawer = page.locator('[id^=doc-drawer_posts_1_]')
|
||||
await expect(drawer).toBeVisible()
|
||||
const titleField = drawer.locator('#field-title')
|
||||
await expect(titleField).toBeVisible()
|
||||
await titleField.fill('Test polymorphic Post')
|
||||
await expect(drawer.locator('#field-polymorphics')).toContainText('example')
|
||||
await drawer.locator('button[id="action-save"]').click()
|
||||
await expect(drawer).toBeHidden()
|
||||
await expect(joinField.locator('tbody .row-1')).toContainText('Test polymorphic Post')
|
||||
})
|
||||
test('should create join collection from polymorphic localized relationships', async () => {
|
||||
await page.goto(categoriesURL.edit(categoryID))
|
||||
const joinField = page.locator('#field-localizedPolymorphic.field-type.join')
|
||||
await expect(joinField).toBeVisible()
|
||||
await joinField.locator('.relationship-table__add-new').click()
|
||||
const drawer = page.locator('[id^=doc-drawer_posts_1_]')
|
||||
await expect(drawer).toBeVisible()
|
||||
const titleField = drawer.locator('#field-title')
|
||||
await expect(titleField).toBeVisible()
|
||||
await titleField.fill('Test polymorphic Post')
|
||||
await expect(drawer.locator('#field-localizedPolymorphic')).toContainText('example')
|
||||
await drawer.locator('button[id="action-save"]').click()
|
||||
await expect(drawer).toBeHidden()
|
||||
await expect(joinField.locator('tbody .row-1')).toContainText('Test polymorphic Post')
|
||||
})
|
||||
test('should create join collection from polymorphic, hasMany, localized relationships', async () => {
|
||||
await page.goto(categoriesURL.edit(categoryID))
|
||||
const joinField = page.locator('#field-localizedPolymorphics.field-type.join')
|
||||
await expect(joinField).toBeVisible()
|
||||
await joinField.locator('.relationship-table__add-new').click()
|
||||
const drawer = page.locator('[id^=doc-drawer_posts_1_]')
|
||||
await expect(drawer).toBeVisible()
|
||||
const titleField = drawer.locator('#field-title')
|
||||
await expect(titleField).toBeVisible()
|
||||
await titleField.fill('Test polymorphic Post')
|
||||
await expect(drawer.locator('#field-localizedPolymorphics')).toContainText('example')
|
||||
await drawer.locator('button[id="action-save"]').click()
|
||||
await expect(drawer).toBeHidden()
|
||||
await expect(joinField.locator('tbody .row-1')).toContainText('Test polymorphic Post')
|
||||
})
|
||||
|
||||
test('should render empty relationship table when creating new document', async () => {
|
||||
await page.goto(categoriesURL.create)
|
||||
const joinField = page.locator('#field-relatedPosts.field-type.join')
|
||||
|
||||
@@ -90,6 +90,26 @@ describe('Joins Field', () => {
|
||||
upload: uploadedImage,
|
||||
categories,
|
||||
categoriesLocalized: categories,
|
||||
polymorphic: {
|
||||
relationTo: 'categories',
|
||||
value: category.id,
|
||||
},
|
||||
polymorphics: [
|
||||
{
|
||||
relationTo: 'categories',
|
||||
value: category.id,
|
||||
},
|
||||
],
|
||||
localizedPolymorphic: {
|
||||
relationTo: 'categories',
|
||||
value: category.id,
|
||||
},
|
||||
localizedPolymorphics: [
|
||||
{
|
||||
relationTo: 'categories',
|
||||
value: category.id,
|
||||
},
|
||||
],
|
||||
group: {
|
||||
category: category.id,
|
||||
camelCaseCategory: category.id,
|
||||
@@ -216,6 +236,17 @@ describe('Joins Field', () => {
|
||||
expect(docs[0].upload.relatedPosts.docs).toHaveLength(10)
|
||||
})
|
||||
|
||||
it('should join on polymorphic relationships', async () => {
|
||||
const categoryWithPosts = await payload.findByID({
|
||||
collection: categoriesSlug,
|
||||
id: category.id,
|
||||
})
|
||||
expect(categoryWithPosts.polymorphic.docs[0]).toHaveProperty('id')
|
||||
expect(categoryWithPosts.polymorphics.docs[0]).toHaveProperty('id')
|
||||
expect(categoryWithPosts.localizedPolymorphic.docs[0]).toHaveProperty('id')
|
||||
expect(categoryWithPosts.localizedPolymorphics.docs[0]).toHaveProperty('id')
|
||||
})
|
||||
|
||||
it('should filter joins using where query', async () => {
|
||||
const categoryWithPosts = await payload.findByID({
|
||||
id: category.id,
|
||||
|
||||
@@ -38,6 +38,10 @@ export interface Config {
|
||||
'group.camelCasePosts': 'posts';
|
||||
arrayPosts: 'posts';
|
||||
blocksPosts: 'posts';
|
||||
polymorphic: 'posts';
|
||||
polymorphics: 'posts';
|
||||
localizedPolymorphic: 'posts';
|
||||
localizedPolymorphics: 'posts';
|
||||
filtered: 'posts';
|
||||
hiddenPosts: 'hidden-posts';
|
||||
singulars: 'singular';
|
||||
@@ -123,6 +127,48 @@ export interface Post {
|
||||
category?: (string | null) | Category;
|
||||
categories?: (string | Category)[] | null;
|
||||
categoriesLocalized?: (string | Category)[] | null;
|
||||
polymorphic?:
|
||||
| ({
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null);
|
||||
polymorphics?:
|
||||
| (
|
||||
| {
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
}
|
||||
| {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
}
|
||||
)[]
|
||||
| null;
|
||||
localizedPolymorphic?:
|
||||
| ({
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null);
|
||||
localizedPolymorphics?:
|
||||
| (
|
||||
| {
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
}
|
||||
| {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
}
|
||||
)[]
|
||||
| null;
|
||||
group?: {
|
||||
category?: (string | null) | Category;
|
||||
camelCaseCategory?: (string | null) | Category;
|
||||
@@ -207,6 +253,22 @@ export interface Category {
|
||||
docs?: (string | Post)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
polymorphic?: {
|
||||
docs?: (string | Post)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
polymorphics?: {
|
||||
docs?: (string | Post)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
localizedPolymorphic?: {
|
||||
docs?: (string | Post)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
localizedPolymorphics?: {
|
||||
docs?: (string | Post)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
singulars?: {
|
||||
docs?: (string | Singular)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
@@ -239,6 +301,23 @@ export interface Singular {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
resetPasswordToken?: string | null;
|
||||
resetPasswordExpiration?: string | null;
|
||||
salt?: string | null;
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "versions".
|
||||
@@ -347,23 +426,6 @@ export interface RestrictedPost {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
resetPasswordToken?: string | null;
|
||||
resetPasswordExpiration?: string | null;
|
||||
salt?: string | null;
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
@@ -481,6 +543,10 @@ export interface PostsSelect<T extends boolean = true> {
|
||||
category?: T;
|
||||
categories?: T;
|
||||
categoriesLocalized?: T;
|
||||
polymorphic?: T;
|
||||
polymorphics?: T;
|
||||
localizedPolymorphic?: T;
|
||||
localizedPolymorphics?: T;
|
||||
group?:
|
||||
| T
|
||||
| {
|
||||
@@ -525,6 +591,10 @@ export interface CategoriesSelect<T extends boolean = true> {
|
||||
};
|
||||
arrayPosts?: T;
|
||||
blocksPosts?: T;
|
||||
polymorphic?: T;
|
||||
polymorphics?: T;
|
||||
localizedPolymorphic?: T;
|
||||
localizedPolymorphics?: T;
|
||||
singulars?: T;
|
||||
filtered?: T;
|
||||
updatedAt?: T;
|
||||
|
||||
Reference in New Issue
Block a user