fix(db-postgres): joins to self collection (#10182)
### What?
With Postgres, before join to self like:
```ts
import type { CollectionConfig } from 'payload'
export const SelfJoins: CollectionConfig = {
slug: 'self-joins',
fields: [
{
name: 'rel',
type: 'relationship',
relationTo: 'self-joins',
},
{
name: 'joins',
type: 'join',
on: 'rel',
collection: 'self-joins',
},
],
}
```
wasn't possible, even though it's a valid usage.
### How?
Now, to differentiate parent `self_joins` and children `self_joins` we
do additional alias for the nested select -
`"4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"`:
```sql
select
"id",
"rel_id",
"updated_at",
"created_at",
(
select
coalesce(
json_agg(
json_build_object('id', "joins_alias".id)
),
'[]' :: json
)
from
(
select
"created_at",
"rel_id",
"id"
from
"self_joins" "4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"
where
"4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"."rel_id" = "self_joins"."id"
order by
"4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"."created_at" desc
limit
$1
) "joins_alias"
) as "joins_alias"
from
"self_joins"
where
"self_joins"."id" = $2
order by
"self_joins"."created_at" desc
limit
$3
```
Fixes https://github.com/payloadcms/payload/issues/10144
-->
This commit is contained in:
@@ -9,6 +9,8 @@ import type { BuildQueryJoinAliases, ChainedMethods, DrizzleAdapter } from '../t
|
|||||||
import type { Result } from './buildFindManyArgs.js'
|
import type { Result } from './buildFindManyArgs.js'
|
||||||
|
|
||||||
import buildQuery from '../queries/buildQuery.js'
|
import buildQuery from '../queries/buildQuery.js'
|
||||||
|
import { getTableAlias } from '../queries/getTableAlias.js'
|
||||||
|
import { getNameFromDrizzleTable } from '../utilities/getNameFromDrizzleTable.js'
|
||||||
import { jsonAggBuildObject } from '../utilities/json.js'
|
import { jsonAggBuildObject } from '../utilities/json.js'
|
||||||
import { rawConstraint } from '../utilities/rawConstraint.js'
|
import { rawConstraint } from '../utilities/rawConstraint.js'
|
||||||
import { chainMethods } from './chainMethods.js'
|
import { chainMethods } from './chainMethods.js'
|
||||||
@@ -385,12 +387,22 @@ export const traverseFields = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const columnName = `${path.replaceAll('.', '_')}${field.name}`
|
||||||
|
|
||||||
|
const subQueryAlias = `${columnName}_alias`
|
||||||
|
|
||||||
|
const { newAliasTable } = getTableAlias({
|
||||||
|
adapter,
|
||||||
|
tableName: joinCollectionTableName,
|
||||||
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
orderBy,
|
orderBy,
|
||||||
selectFields,
|
selectFields,
|
||||||
where: subQueryWhere,
|
where: subQueryWhere,
|
||||||
} = buildQuery({
|
} = buildQuery({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable: newAliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
@@ -418,15 +430,21 @@ export const traverseFields = ({
|
|||||||
|
|
||||||
const db = adapter.drizzle as LibSQLDatabase
|
const db = adapter.drizzle as LibSQLDatabase
|
||||||
|
|
||||||
const columnName = `${path.replaceAll('.', '_')}${field.name}`
|
for (let key in selectFields) {
|
||||||
|
const val = selectFields[key]
|
||||||
|
|
||||||
const subQueryAlias = `${columnName}_alias`
|
if (val.table && getNameFromDrizzleTable(val.table) === joinCollectionTableName) {
|
||||||
|
delete selectFields[key]
|
||||||
|
key = key.split('.').pop()
|
||||||
|
selectFields[key] = newAliasTable[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const subQuery = chainMethods({
|
const subQuery = chainMethods({
|
||||||
methods: chainedMethods,
|
methods: chainedMethods,
|
||||||
query: db
|
query: db
|
||||||
.select(selectFields as any)
|
.select(selectFields as any)
|
||||||
.from(adapter.tables[joinCollectionTableName])
|
.from(newAliasTable)
|
||||||
.where(subQueryWhere)
|
.where(subQueryWhere)
|
||||||
.orderBy(() => orderBy.map(({ column, order }) => order(column))),
|
.orderBy(() => orderBy.map(({ column, order }) => order(column))),
|
||||||
}).as(subQueryAlias)
|
}).as(subQueryAlias)
|
||||||
@@ -440,7 +458,7 @@ export const traverseFields = ({
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.from(sql`${subQuery}`)}`.as(columnName)
|
.from(sql`${subQuery}`)}`.as(subQueryAlias)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { SQL } from 'drizzle-orm'
|
import type { SQL, Table } from 'drizzle-orm'
|
||||||
import type { FlattenedField, Where } from 'payload'
|
import type { FlattenedField, Where } from 'payload'
|
||||||
|
|
||||||
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
||||||
@@ -8,6 +8,7 @@ import { parseParams } from './parseParams.js'
|
|||||||
|
|
||||||
export function buildAndOrConditions({
|
export function buildAndOrConditions({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
@@ -17,6 +18,7 @@ export function buildAndOrConditions({
|
|||||||
where,
|
where,
|
||||||
}: {
|
}: {
|
||||||
adapter: DrizzleAdapter
|
adapter: DrizzleAdapter
|
||||||
|
aliasTable?: Table
|
||||||
collectionSlug?: string
|
collectionSlug?: string
|
||||||
fields: FlattenedField[]
|
fields: FlattenedField[]
|
||||||
globalSlug?: string
|
globalSlug?: string
|
||||||
@@ -36,6 +38,7 @@ export function buildAndOrConditions({
|
|||||||
if (typeof condition === 'object') {
|
if (typeof condition === 'object') {
|
||||||
const result = parseParams({
|
const result = parseParams({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { Table } from 'drizzle-orm'
|
||||||
import type { FlattenedField, Sort } from 'payload'
|
import type { FlattenedField, Sort } from 'payload'
|
||||||
|
|
||||||
import { asc, desc } from 'drizzle-orm'
|
import { asc, desc } from 'drizzle-orm'
|
||||||
@@ -5,10 +6,12 @@ import { asc, desc } from 'drizzle-orm'
|
|||||||
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
||||||
import type { BuildQueryJoinAliases, BuildQueryResult } from './buildQuery.js'
|
import type { BuildQueryJoinAliases, BuildQueryResult } from './buildQuery.js'
|
||||||
|
|
||||||
|
import { getNameFromDrizzleTable } from '../utilities/getNameFromDrizzleTable.js'
|
||||||
import { getTableColumnFromPath } from './getTableColumnFromPath.js'
|
import { getTableColumnFromPath } from './getTableColumnFromPath.js'
|
||||||
|
|
||||||
type Args = {
|
type Args = {
|
||||||
adapter: DrizzleAdapter
|
adapter: DrizzleAdapter
|
||||||
|
aliasTable?: Table
|
||||||
fields: FlattenedField[]
|
fields: FlattenedField[]
|
||||||
joins: BuildQueryJoinAliases
|
joins: BuildQueryJoinAliases
|
||||||
locale?: string
|
locale?: string
|
||||||
@@ -22,6 +25,7 @@ type Args = {
|
|||||||
*/
|
*/
|
||||||
export const buildOrderBy = ({
|
export const buildOrderBy = ({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
@@ -68,7 +72,10 @@ export const buildOrderBy = ({
|
|||||||
})
|
})
|
||||||
if (sortTable?.[sortTableColumnName]) {
|
if (sortTable?.[sortTableColumnName]) {
|
||||||
orderBy.push({
|
orderBy.push({
|
||||||
column: sortTable[sortTableColumnName],
|
column:
|
||||||
|
aliasTable && tableName === getNameFromDrizzleTable(sortTable)
|
||||||
|
? aliasTable[sortTableColumnName]
|
||||||
|
: sortTable[sortTableColumnName],
|
||||||
order: sortDirection === 'asc' ? asc : desc,
|
order: sortDirection === 'asc' ? asc : desc,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { asc, desc, SQL } from 'drizzle-orm'
|
import type { asc, desc, SQL, Table } from 'drizzle-orm'
|
||||||
import type { PgTableWithColumns } from 'drizzle-orm/pg-core'
|
import type { PgTableWithColumns } from 'drizzle-orm/pg-core'
|
||||||
import type { FlattenedField, Sort, Where } from 'payload'
|
import type { FlattenedField, Sort, Where } from 'payload'
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ export type BuildQueryJoinAliases = {
|
|||||||
|
|
||||||
type BuildQueryArgs = {
|
type BuildQueryArgs = {
|
||||||
adapter: DrizzleAdapter
|
adapter: DrizzleAdapter
|
||||||
|
aliasTable?: Table
|
||||||
fields: FlattenedField[]
|
fields: FlattenedField[]
|
||||||
joins?: BuildQueryJoinAliases
|
joins?: BuildQueryJoinAliases
|
||||||
locale?: string
|
locale?: string
|
||||||
@@ -35,6 +36,7 @@ export type BuildQueryResult = {
|
|||||||
}
|
}
|
||||||
const buildQuery = function buildQuery({
|
const buildQuery = function buildQuery({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins = [],
|
joins = [],
|
||||||
locale,
|
locale,
|
||||||
@@ -49,6 +51,7 @@ const buildQuery = function buildQuery({
|
|||||||
|
|
||||||
const orderBy = buildOrderBy({
|
const orderBy = buildOrderBy({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
@@ -62,6 +65,7 @@ const buildQuery = function buildQuery({
|
|||||||
if (incomingWhere && Object.keys(incomingWhere).length > 0) {
|
if (incomingWhere && Object.keys(incomingWhere).length > 0) {
|
||||||
where = parseParams({
|
where = parseParams({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { SQL } from 'drizzle-orm'
|
import type { SQL, Table } from 'drizzle-orm'
|
||||||
import type { FlattenedField, Operator, Where } from 'payload'
|
import type { FlattenedField, Operator, Where } from 'payload'
|
||||||
|
|
||||||
import { and, isNotNull, isNull, ne, notInArray, or, sql } from 'drizzle-orm'
|
import { and, isNotNull, isNull, ne, notInArray, or, sql } from 'drizzle-orm'
|
||||||
@@ -9,12 +9,14 @@ import { validOperators } from 'payload/shared'
|
|||||||
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
||||||
import type { BuildQueryJoinAliases } from './buildQuery.js'
|
import type { BuildQueryJoinAliases } from './buildQuery.js'
|
||||||
|
|
||||||
|
import { getNameFromDrizzleTable } from '../utilities/getNameFromDrizzleTable.js'
|
||||||
import { buildAndOrConditions } from './buildAndOrConditions.js'
|
import { buildAndOrConditions } from './buildAndOrConditions.js'
|
||||||
import { getTableColumnFromPath } from './getTableColumnFromPath.js'
|
import { getTableColumnFromPath } from './getTableColumnFromPath.js'
|
||||||
import { sanitizeQueryValue } from './sanitizeQueryValue.js'
|
import { sanitizeQueryValue } from './sanitizeQueryValue.js'
|
||||||
|
|
||||||
type Args = {
|
type Args = {
|
||||||
adapter: DrizzleAdapter
|
adapter: DrizzleAdapter
|
||||||
|
aliasTable?: Table
|
||||||
fields: FlattenedField[]
|
fields: FlattenedField[]
|
||||||
joins: BuildQueryJoinAliases
|
joins: BuildQueryJoinAliases
|
||||||
locale: string
|
locale: string
|
||||||
@@ -26,6 +28,7 @@ type Args = {
|
|||||||
|
|
||||||
export function parseParams({
|
export function parseParams({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
@@ -51,6 +54,7 @@ export function parseParams({
|
|||||||
if (Array.isArray(condition)) {
|
if (Array.isArray(condition)) {
|
||||||
const builtConditions = buildAndOrConditions({
|
const builtConditions = buildAndOrConditions({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
locale,
|
locale,
|
||||||
@@ -83,6 +87,7 @@ export function parseParams({
|
|||||||
table,
|
table,
|
||||||
} = getTableColumnFromPath({
|
} = getTableColumnFromPath({
|
||||||
adapter,
|
adapter,
|
||||||
|
aliasTable,
|
||||||
collectionPath: relationOrPath,
|
collectionPath: relationOrPath,
|
||||||
fields,
|
fields,
|
||||||
joins,
|
joins,
|
||||||
@@ -261,12 +266,18 @@ export function parseParams({
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolvedColumn =
|
||||||
|
rawColumn ||
|
||||||
|
(aliasTable && tableName === getNameFromDrizzleTable(table)
|
||||||
|
? aliasTable[columnName]
|
||||||
|
: table[columnName])
|
||||||
|
|
||||||
if (queryOperator === 'not_equals' && queryValue !== null) {
|
if (queryOperator === 'not_equals' && queryValue !== null) {
|
||||||
constraints.push(
|
constraints.push(
|
||||||
or(
|
or(
|
||||||
isNull(rawColumn || table[columnName]),
|
isNull(resolvedColumn),
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
ne<any>(rawColumn || table[columnName], queryValue),
|
ne<any>(resolvedColumn, queryValue),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
@@ -288,12 +299,12 @@ export function parseParams({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (operator === 'equals' && queryValue === null) {
|
if (operator === 'equals' && queryValue === null) {
|
||||||
constraints.push(isNull(rawColumn || table[columnName]))
|
constraints.push(isNull(resolvedColumn))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operator === 'not_equals' && queryValue === null) {
|
if (operator === 'not_equals' && queryValue === null) {
|
||||||
constraints.push(isNotNull(rawColumn || table[columnName]))
|
constraints.push(isNotNull(resolvedColumn))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,9 +341,7 @@ export function parseParams({
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
constraints.push(
|
constraints.push(adapter.operators[queryOperator](resolvedColumn, queryValue))
|
||||||
adapter.operators[queryOperator](rawColumn || table[columnName], queryValue),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
test/joins/collections/SelfJoins.ts
Normal file
18
test/joins/collections/SelfJoins.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
export const SelfJoins: CollectionConfig = {
|
||||||
|
slug: 'self-joins',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'rel',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'self-joins',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'joins',
|
||||||
|
type: 'join',
|
||||||
|
on: 'rel',
|
||||||
|
collection: 'self-joins',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { Categories } from './collections/Categories.js'
|
|||||||
import { CategoriesVersions } from './collections/CategoriesVersions.js'
|
import { CategoriesVersions } from './collections/CategoriesVersions.js'
|
||||||
import { HiddenPosts } from './collections/HiddenPosts.js'
|
import { HiddenPosts } from './collections/HiddenPosts.js'
|
||||||
import { Posts } from './collections/Posts.js'
|
import { Posts } from './collections/Posts.js'
|
||||||
|
import { SelfJoins } from './collections/SelfJoins.js'
|
||||||
import { Singular } from './collections/Singular.js'
|
import { Singular } from './collections/Singular.js'
|
||||||
import { Uploads } from './collections/Uploads.js'
|
import { Uploads } from './collections/Uploads.js'
|
||||||
import { Versions } from './collections/Versions.js'
|
import { Versions } from './collections/Versions.js'
|
||||||
@@ -37,6 +38,7 @@ export default buildConfigWithDefaults({
|
|||||||
Versions,
|
Versions,
|
||||||
CategoriesVersions,
|
CategoriesVersions,
|
||||||
Singular,
|
Singular,
|
||||||
|
SelfJoins,
|
||||||
{
|
{
|
||||||
slug: localizedPostsSlug,
|
slug: localizedPostsSlug,
|
||||||
admin: {
|
admin: {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Payload } from 'payload'
|
import type { Payload, TypeWithID } from 'payload'
|
||||||
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { getFileByPath } from 'payload'
|
import { getFileByPath } from 'payload'
|
||||||
@@ -975,6 +975,15 @@ describe('Joins Field', () => {
|
|||||||
|
|
||||||
await payload.delete({ collection: categoriesSlug, where: { name: { equals: 'totalDocs' } } })
|
await payload.delete({ collection: categoriesSlug, where: { name: { equals: 'totalDocs' } } })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should self join', async () => {
|
||||||
|
const doc_1 = await payload.create({ collection: 'self-joins', data: {} })
|
||||||
|
const doc_2 = await payload.create({ collection: 'self-joins', data: { rel: doc_1 }, depth: 0 })
|
||||||
|
|
||||||
|
const data = await payload.findByID({ collection: 'self-joins', id: doc_1.id, depth: 1 })
|
||||||
|
|
||||||
|
expect((data.joins.docs[0] as TypeWithID).id).toBe(doc_2.id)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function createPost(overrides?: Partial<Post>, locale?: Config['locale']) {
|
async function createPost(overrides?: Partial<Post>, locale?: Config['locale']) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export interface Config {
|
|||||||
versions: Version;
|
versions: Version;
|
||||||
'categories-versions': CategoriesVersion;
|
'categories-versions': CategoriesVersion;
|
||||||
singular: Singular;
|
singular: Singular;
|
||||||
|
'self-joins': SelfJoin;
|
||||||
'localized-posts': LocalizedPost;
|
'localized-posts': LocalizedPost;
|
||||||
'localized-categories': LocalizedCategory;
|
'localized-categories': LocalizedCategory;
|
||||||
'restricted-categories': RestrictedCategory;
|
'restricted-categories': RestrictedCategory;
|
||||||
@@ -53,6 +54,9 @@ export interface Config {
|
|||||||
relatedVersions: 'versions';
|
relatedVersions: 'versions';
|
||||||
relatedVersionsMany: 'versions';
|
relatedVersionsMany: 'versions';
|
||||||
};
|
};
|
||||||
|
'self-joins': {
|
||||||
|
joins: 'self-joins';
|
||||||
|
};
|
||||||
'localized-categories': {
|
'localized-categories': {
|
||||||
relatedPosts: 'localized-posts';
|
relatedPosts: 'localized-posts';
|
||||||
};
|
};
|
||||||
@@ -71,6 +75,7 @@ export interface Config {
|
|||||||
versions: VersionsSelect<false> | VersionsSelect<true>;
|
versions: VersionsSelect<false> | VersionsSelect<true>;
|
||||||
'categories-versions': CategoriesVersionsSelect<false> | CategoriesVersionsSelect<true>;
|
'categories-versions': CategoriesVersionsSelect<false> | CategoriesVersionsSelect<true>;
|
||||||
singular: SingularSelect<false> | SingularSelect<true>;
|
singular: SingularSelect<false> | SingularSelect<true>;
|
||||||
|
'self-joins': SelfJoinsSelect<false> | SelfJoinsSelect<true>;
|
||||||
'localized-posts': LocalizedPostsSelect<false> | LocalizedPostsSelect<true>;
|
'localized-posts': LocalizedPostsSelect<false> | LocalizedPostsSelect<true>;
|
||||||
'localized-categories': LocalizedCategoriesSelect<false> | LocalizedCategoriesSelect<true>;
|
'localized-categories': LocalizedCategoriesSelect<false> | LocalizedCategoriesSelect<true>;
|
||||||
'restricted-categories': RestrictedCategoriesSelect<false> | RestrictedCategoriesSelect<true>;
|
'restricted-categories': RestrictedCategoriesSelect<false> | RestrictedCategoriesSelect<true>;
|
||||||
@@ -355,6 +360,20 @@ export interface CategoriesVersion {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "self-joins".
|
||||||
|
*/
|
||||||
|
export interface SelfJoin {
|
||||||
|
id: string;
|
||||||
|
rel?: (string | null) | SelfJoin;
|
||||||
|
joins?: {
|
||||||
|
docs?: (string | SelfJoin)[] | null;
|
||||||
|
hasNextPage?: boolean | null;
|
||||||
|
} | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "localized-posts".
|
* via the `definition` "localized-posts".
|
||||||
@@ -467,6 +486,10 @@ export interface PayloadLockedDocument {
|
|||||||
relationTo: 'singular';
|
relationTo: 'singular';
|
||||||
value: string | Singular;
|
value: string | Singular;
|
||||||
} | null)
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'self-joins';
|
||||||
|
value: string | SelfJoin;
|
||||||
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'localized-posts';
|
relationTo: 'localized-posts';
|
||||||
value: string | LocalizedPost;
|
value: string | LocalizedPost;
|
||||||
@@ -666,6 +689,16 @@ export interface SingularSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "self-joins_select".
|
||||||
|
*/
|
||||||
|
export interface SelfJoinsSelect<T extends boolean = true> {
|
||||||
|
rel?: T;
|
||||||
|
joins?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "localized-posts_select".
|
* via the `definition` "localized-posts_select".
|
||||||
|
|||||||
Reference in New Issue
Block a user