fix: respect draft: true when querying docs for the join field (#11763)

Previously, if you were querying a collection that has a join field with
`draft: true`, and the join field's collection also has
`versions.drafts: true` our db adapter would still query the original
SQL table / mongodb collection instead of the versions one which isn't
quite right since we respect `draft: true` when populating relationships
This commit is contained in:
Sasha
2025-03-24 15:49:30 +02:00
committed by GitHub
parent 5f6bb92501
commit 1b2b6a1b15
17 changed files with 165 additions and 29 deletions

View File

@@ -18,6 +18,7 @@ export const find: Find = async function find(
this: MongooseAdapter, this: MongooseAdapter,
{ {
collection: collectionSlug, collection: collectionSlug,
draftsEnabled,
joins = {}, joins = {},
limit = 0, limit = 0,
locale, locale,
@@ -128,6 +129,7 @@ export const find: Find = async function find(
adapter: this, adapter: this,
collection: collectionSlug, collection: collectionSlug,
collectionConfig, collectionConfig,
draftsEnabled,
joins, joins,
locale, locale,
query, query,

View File

@@ -14,7 +14,7 @@ import { transform } from './utilities/transform.js'
export const findOne: FindOne = async function findOne( export const findOne: FindOne = async function findOne(
this: MongooseAdapter, this: MongooseAdapter,
{ collection: collectionSlug, joins, locale, req, select, where = {} }, { collection: collectionSlug, draftsEnabled, joins, locale, req, select, where = {} },
) { ) {
const { collectionConfig, Model } = getCollection({ adapter: this, collectionSlug }) const { collectionConfig, Model } = getCollection({ adapter: this, collectionSlug })
@@ -42,6 +42,7 @@ export const findOne: FindOne = async function findOne(
adapter: this, adapter: this,
collection: collectionSlug, collection: collectionSlug,
collectionConfig, collectionConfig,
draftsEnabled,
joins, joins,
locale, locale,
projection, projection,

View File

@@ -2,14 +2,19 @@ import type { PipelineStage } from 'mongoose'
import { import {
APIError, APIError,
appendVersionToQueryKey,
buildVersionCollectionFields,
type CollectionSlug, type CollectionSlug,
combineQueries,
type FlattenedField, type FlattenedField,
getQueryDraftsSort,
type JoinQuery, type JoinQuery,
type SanitizedCollectionConfig, type SanitizedCollectionConfig,
} from 'payload' } from 'payload'
import { fieldShouldBeLocalized } from 'payload/shared' import { fieldShouldBeLocalized } from 'payload/shared'
import type { MongooseAdapter } from '../index.js' import type { MongooseAdapter } from '../index.js'
import type { CollectionModel } from '../types.js'
import { buildQuery } from '../queries/buildQuery.js' import { buildQuery } from '../queries/buildQuery.js'
import { buildSortParam } from '../queries/buildSortParam.js' import { buildSortParam } from '../queries/buildSortParam.js'
@@ -19,6 +24,7 @@ type BuildJoinAggregationArgs = {
adapter: MongooseAdapter adapter: MongooseAdapter
collection: CollectionSlug collection: CollectionSlug
collectionConfig: SanitizedCollectionConfig collectionConfig: SanitizedCollectionConfig
draftsEnabled?: boolean
joins?: JoinQuery joins?: JoinQuery
locale?: string locale?: string
projection?: Record<string, true> projection?: Record<string, true>
@@ -32,6 +38,7 @@ export const buildJoinAggregation = async ({
adapter, adapter,
collection, collection,
collectionConfig, collectionConfig,
draftsEnabled,
joins, joins,
locale, locale,
projection, projection,
@@ -262,10 +269,27 @@ export const buildJoinAggregation = async ({
continue continue
} }
const { collectionConfig, Model: JoinModel } = getCollection({ const collectionConfig = adapter.payload.collections[join.field.collection as string]?.config
adapter,
collectionSlug: join.field.collection as string, if (!collectionConfig) {
}) throw new APIError(
`Collection config for ${join.field.collection.toString()} was not found`,
)
}
let JoinModel: CollectionModel | undefined
const useDrafts = (draftsEnabled || versions) && Boolean(collectionConfig.versions.drafts)
if (useDrafts) {
JoinModel = adapter.versions[collectionConfig.slug]
} else {
JoinModel = adapter.collections[collectionConfig.slug]
}
if (!JoinModel) {
throw new APIError(`Join Model was not found for ${collectionConfig.slug}`)
}
const { const {
count, count,
@@ -279,12 +303,16 @@ export const buildJoinAggregation = async ({
throw new Error('Unreachable') throw new Error('Unreachable')
} }
const fields = useDrafts
? buildVersionCollectionFields(adapter.payload.config, collectionConfig, true)
: collectionConfig.flattenedFields
const sort = buildSortParam({ const sort = buildSortParam({
adapter, adapter,
config: adapter.payload.config, config: adapter.payload.config,
fields: collectionConfig.flattenedFields, fields,
locale, locale,
sort: sortJoin, sort: useDrafts ? getQueryDraftsSort({ collectionConfig, sort: sortJoin }) : sortJoin,
timestamps: true, timestamps: true,
}) })
const sortProperty = Object.keys(sort)[0]! const sortProperty = Object.keys(sort)[0]!
@@ -293,7 +321,13 @@ export const buildJoinAggregation = async ({
const $match = await JoinModel.buildQuery({ const $match = await JoinModel.buildQuery({
locale, locale,
payload: adapter.payload, payload: adapter.payload,
where: whereJoin, where: useDrafts
? combineQueries(appendVersionToQueryKey(whereJoin), {
latest: {
equals: true,
},
})
: whereJoin,
}) })
const pipeline: Exclude<PipelineStage, PipelineStage.Merge | PipelineStage.Out>[] = [ const pipeline: Exclude<PipelineStage, PipelineStage.Merge | PipelineStage.Out>[] = [
@@ -345,6 +379,12 @@ export const buildJoinAggregation = async ({
}, },
) )
let foreignFieldPrefix = ''
if (useDrafts) {
foreignFieldPrefix = 'version.'
}
if (adapter.payload.config.localization && locale === 'all') { if (adapter.payload.config.localization && locale === 'all') {
adapter.payload.config.localization.localeCodes.forEach((code) => { adapter.payload.config.localization.localeCodes.forEach((code) => {
const as = `${versions ? `version.${join.joinPath}` : join.joinPath}${code}` const as = `${versions ? `version.${join.joinPath}` : join.joinPath}${code}`
@@ -353,7 +393,7 @@ export const buildJoinAggregation = async ({
{ {
$lookup: { $lookup: {
as: `${as}.docs`, as: `${as}.docs`,
foreignField: `${join.field.on}${code}${polymorphicSuffix}`, foreignField: `${foreignFieldPrefix}${join.field.on}${code}${polymorphicSuffix}`,
from: JoinModel.collection.name, from: JoinModel.collection.name,
localField: versions ? 'parent' : '_id', localField: versions ? 'parent' : '_id',
pipeline, pipeline,
@@ -364,7 +404,7 @@ export const buildJoinAggregation = async ({
[`${as}.docs`]: { [`${as}.docs`]: {
$map: { $map: {
as: 'doc', as: 'doc',
in: '$$doc._id', in: useDrafts ? `$$doc.parent` : '$$doc._id',
input: `$${as}.docs`, input: `$${as}.docs`,
}, },
}, // Slicing the docs to match the limit }, // Slicing the docs to match the limit
@@ -387,7 +427,10 @@ export const buildJoinAggregation = async ({
} }
if (count) { if (count) {
addTotalDocsAggregation(as, `${join.field.on}${code}${polymorphicSuffix}`) addTotalDocsAggregation(
as,
`${foreignFieldPrefix}${join.field.on}${code}${polymorphicSuffix}`,
)
} }
}) })
} else { } else {
@@ -414,7 +457,7 @@ export const buildJoinAggregation = async ({
{ {
$lookup: { $lookup: {
as: `${as}.docs`, as: `${as}.docs`,
foreignField, foreignField: `${foreignFieldPrefix}${foreignField}`,
from: JoinModel.collection.name, from: JoinModel.collection.name,
localField: versions ? 'parent' : '_id', localField: versions ? 'parent' : '_id',
pipeline, pipeline,
@@ -425,7 +468,7 @@ export const buildJoinAggregation = async ({
[`${as}.docs`]: { [`${as}.docs`]: {
$map: { $map: {
as: 'doc', as: 'doc',
in: '$$doc._id', in: useDrafts ? `$$doc.parent` : '$$doc._id',
input: `$${as}.docs`, input: `$${as}.docs`,
}, },
}, // Slicing the docs to match the limit }, // Slicing the docs to match the limit
@@ -437,7 +480,7 @@ export const buildJoinAggregation = async ({
) )
if (count) { if (count) {
addTotalDocsAggregation(as, foreignField) addTotalDocsAggregation(as, `${foreignFieldPrefix}${foreignField}`)
} }
if (limitJoin > 0) { if (limitJoin > 0) {

View File

@@ -8,7 +8,19 @@ import { findMany } from './find/findMany.js'
export const find: Find = async function find( export const find: Find = async function find(
this: DrizzleAdapter, this: DrizzleAdapter,
{ collection, joins, limit, locale, page = 1, pagination, req, select, sort: sortArg, where }, {
collection,
draftsEnabled,
joins,
limit,
locale,
page = 1,
pagination,
req,
select,
sort: sortArg,
where,
},
) { ) {
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
const sort = sortArg !== undefined && sortArg !== null ? sortArg : collectionConfig.defaultSort const sort = sortArg !== undefined && sortArg !== null ? sortArg : collectionConfig.defaultSort
@@ -18,6 +30,7 @@ export const find: Find = async function find(
return findMany({ return findMany({
adapter: this, adapter: this,
collectionSlug: collectionConfig.slug, collectionSlug: collectionConfig.slug,
draftsEnabled,
fields: collectionConfig.flattenedFields, fields: collectionConfig.flattenedFields,
joins, joins,
limit, limit,

View File

@@ -11,6 +11,7 @@ type BuildFindQueryArgs = {
adapter: DrizzleAdapter adapter: DrizzleAdapter
collectionSlug?: string collectionSlug?: string
depth: number depth: number
draftsEnabled?: boolean
fields: FlattenedField[] fields: FlattenedField[]
joinQuery?: JoinQuery joinQuery?: JoinQuery
/** /**
@@ -35,6 +36,7 @@ export const buildFindManyArgs = ({
adapter, adapter,
collectionSlug, collectionSlug,
depth, depth,
draftsEnabled,
fields, fields,
joinQuery, joinQuery,
joins = [], joins = [],
@@ -80,6 +82,7 @@ export const buildFindManyArgs = ({
currentArgs: result, currentArgs: result,
currentTableName: tableName, currentTableName: tableName,
depth, depth,
draftsEnabled,
fields, fields,
joinQuery, joinQuery,
joins, joins,

View File

@@ -22,6 +22,7 @@ type Args = {
export const findMany = async function find({ export const findMany = async function find({
adapter, adapter,
collectionSlug, collectionSlug,
draftsEnabled,
fields, fields,
joins: joinQuery, joins: joinQuery,
limit: limitArg, limit: limitArg,
@@ -74,6 +75,7 @@ export const findMany = async function find({
adapter, adapter,
collectionSlug, collectionSlug,
depth: 0, depth: 0,
draftsEnabled,
fields, fields,
joinQuery, joinQuery,
joins, joins,

View File

@@ -1,8 +1,18 @@
import type { LibSQLDatabase } from 'drizzle-orm/libsql' import type { LibSQLDatabase } from 'drizzle-orm/libsql'
import type { SQLiteSelectBase } from 'drizzle-orm/sqlite-core' import type { SQLiteSelectBase } from 'drizzle-orm/sqlite-core'
import type { FlattenedField, JoinQuery, SelectMode, SelectType, Where } from 'payload'
import { and, asc, count, desc, eq, or, sql } from 'drizzle-orm' import { and, asc, count, desc, eq, or, sql } from 'drizzle-orm'
import {
appendVersionToQueryKey,
buildVersionCollectionFields,
combineQueries,
type FlattenedField,
getQueryDraftsSort,
type JoinQuery,
type SelectMode,
type SelectType,
type Where,
} from 'payload'
import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared' import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared'
import toSnakeCase from 'to-snake-case' import toSnakeCase from 'to-snake-case'
@@ -61,6 +71,7 @@ type TraverseFieldArgs = {
currentArgs: Result currentArgs: Result
currentTableName: string currentTableName: string
depth?: number depth?: number
draftsEnabled?: boolean
fields: FlattenedField[] fields: FlattenedField[]
joinQuery: JoinQuery joinQuery: JoinQuery
joins?: BuildQueryJoinAliases joins?: BuildQueryJoinAliases
@@ -88,6 +99,7 @@ export const traverseFields = ({
currentArgs, currentArgs,
currentTableName, currentTableName,
depth, depth,
draftsEnabled,
fields, fields,
joinQuery = {}, joinQuery = {},
joins, joins,
@@ -193,6 +205,7 @@ export const traverseFields = ({
currentArgs: withArray, currentArgs: withArray,
currentTableName: arrayTableName, currentTableName: arrayTableName,
depth, depth,
draftsEnabled,
fields: field.flattenedFields, fields: field.flattenedFields,
joinQuery, joinQuery,
locale, locale,
@@ -304,6 +317,7 @@ export const traverseFields = ({
currentArgs: withBlock, currentArgs: withBlock,
currentTableName: tableName, currentTableName: tableName,
depth, depth,
draftsEnabled,
fields: block.flattenedFields, fields: block.flattenedFields,
joinQuery, joinQuery,
locale, locale,
@@ -345,6 +359,7 @@ export const traverseFields = ({
currentArgs, currentArgs,
currentTableName, currentTableName,
depth, depth,
draftsEnabled,
fields: field.flattenedFields, fields: field.flattenedFields,
joinQuery, joinQuery,
joins, joins,
@@ -511,9 +526,23 @@ export const traverseFields = ({
.from(sql`${currentQuery.as(subQueryAlias)}`) .from(sql`${currentQuery.as(subQueryAlias)}`)
.where(sqlWhere)}`.as(columnName) .where(sqlWhere)}`.as(columnName)
} else { } else {
const fields = adapter.payload.collections[field.collection].config.flattenedFields const useDrafts =
(versions || draftsEnabled) &&
Boolean(adapter.payload.collections[field.collection].config.versions.drafts)
const joinCollectionTableName = adapter.tableNameMap.get(toSnakeCase(field.collection)) const fields = useDrafts
? buildVersionCollectionFields(
adapter.payload.config,
adapter.payload.collections[field.collection].config,
true,
)
: adapter.payload.collections[field.collection].config.flattenedFields
const joinCollectionTableName = adapter.tableNameMap.get(
useDrafts
? `_${toSnakeCase(field.collection)}${adapter.versionsSuffix}`
: toSnakeCase(field.collection),
)
const joins: BuildQueryJoinAliases = [] const joins: BuildQueryJoinAliases = []
@@ -546,6 +575,12 @@ export const traverseFields = ({
} }
} }
if (useDrafts) {
joinQueryWhere = combineQueries(appendVersionToQueryKey(joinQueryWhere), {
latest: { equals: true },
})
}
const columnName = `${path.replaceAll('.', '_')}${field.name}` const columnName = `${path.replaceAll('.', '_')}${field.name}`
const subQueryAlias = `${columnName}_alias` const subQueryAlias = `${columnName}_alias`
@@ -567,7 +602,12 @@ export const traverseFields = ({
locale, locale,
parentIsLocalized, parentIsLocalized,
selectLocale: true, selectLocale: true,
sort, sort: useDrafts
? getQueryDraftsSort({
collectionConfig: adapter.payload.collections[field.collection].config,
sort,
})
: sort,
tableName: joinCollectionTableName, tableName: joinCollectionTableName,
where: joinQueryWhere, where: joinQueryWhere,
}) })
@@ -610,6 +650,10 @@ export const traverseFields = ({
} }
} }
if (useDrafts) {
selectFields.parent = newAliasTable.parent
}
const subQuery = chainMethods({ const subQuery = chainMethods({
methods: chainedMethods, methods: chainedMethods,
query: db query: db
@@ -636,7 +680,7 @@ export const traverseFields = ({
currentArgs.extras[columnName] = sql`${db currentArgs.extras[columnName] = sql`${db
.select({ .select({
result: jsonAggBuildObject(adapter, { result: jsonAggBuildObject(adapter, {
id: sql.raw(`"${subQueryAlias}".id`), id: sql.raw(`"${subQueryAlias}".${useDrafts ? 'parent_id' : 'id'}`),
...(selectFields._locale && { ...(selectFields._locale && {
locale: sql.raw(`"${subQueryAlias}".${selectFields._locale.name}`), locale: sql.raw(`"${subQueryAlias}".${selectFields._locale.name}`),
}), }),

View File

@@ -8,7 +8,7 @@ import { findMany } from './find/findMany.js'
export async function findOne<T extends TypeWithID>( export async function findOne<T extends TypeWithID>(
this: DrizzleAdapter, this: DrizzleAdapter,
{ collection, joins, locale, req, select, where }: FindOneArgs, { collection, draftsEnabled, joins, locale, req, select, where }: FindOneArgs,
): Promise<T> { ): Promise<T> {
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
@@ -17,6 +17,7 @@ export async function findOne<T extends TypeWithID>(
const { docs } = await findMany({ const { docs } = await findMany({
adapter: this, adapter: this,
collectionSlug: collection, collectionSlug: collection,
draftsEnabled,
fields: collectionConfig.flattenedFields, fields: collectionConfig.flattenedFields,
joins, joins,
limit: 1, limit: 1,

View File

@@ -1,7 +1,6 @@
import type { FlattenedBlock, FlattenedField, JoinQuery, SanitizedConfig } from 'payload' import type { FlattenedBlock, FlattenedField, JoinQuery, SanitizedConfig } from 'payload'
import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared' import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared'
import toSnakeCase from 'to-snake-case'
import type { DrizzleAdapter } from '../../types.js' import type { DrizzleAdapter } from '../../types.js'
import type { BlocksMap } from '../../utilities/createBlocksMap.js' import type { BlocksMap } from '../../utilities/createBlocksMap.js'

View File

@@ -23,15 +23,15 @@ export const metadata = {
export const RootLayout = async ({ export const RootLayout = async ({
children, children,
config: configPromise, config: configPromise,
htmlProps = {},
importMap, importMap,
serverFunction, serverFunction,
htmlProps = {},
}: { }: {
readonly children: React.ReactNode readonly children: React.ReactNode
readonly config: Promise<SanitizedConfig> readonly config: Promise<SanitizedConfig>
readonly htmlProps?: React.HtmlHTMLAttributes<HTMLHtmlElement>
readonly importMap: ImportMap readonly importMap: ImportMap
readonly serverFunction: ServerFunctionClient readonly serverFunction: ServerFunctionClient
readonly htmlProps?: React.HtmlHTMLAttributes<HTMLHtmlElement>
}) => { }) => {
checkDependencies() checkDependencies()

View File

@@ -183,6 +183,7 @@ export const findOperation = async <
result = await payload.db.find<DataFromCollectionSlug<TSlug>>({ result = await payload.db.find<DataFromCollectionSlug<TSlug>>({
collection: collectionConfig.slug, collection: collectionConfig.slug,
draftsEnabled,
joins: req.payloadAPI === 'GraphQL' ? false : sanitizedJoins, joins: req.payloadAPI === 'GraphQL' ? false : sanitizedJoins,
limit: sanitizedLimit, limit: sanitizedLimit,
locale, locale,

View File

@@ -117,6 +117,7 @@ export const findByIDOperation = async <
const findOneArgs: FindOneArgs = { const findOneArgs: FindOneArgs = {
collection: collectionConfig.slug, collection: collectionConfig.slug,
draftsEnabled: draftEnabled,
joins: req.payloadAPI === 'GraphQL' ? false : sanitizedJoins, joins: req.payloadAPI === 'GraphQL' ? false : sanitizedJoins,
locale, locale,
req: { req: {

View File

@@ -206,6 +206,7 @@ export type QueryDrafts = <T = TypeWithID>(args: QueryDraftsArgs) => Promise<Pag
export type FindOneArgs = { export type FindOneArgs = {
collection: CollectionSlug collection: CollectionSlug
draftsEnabled?: boolean
joins?: JoinQuery joins?: JoinQuery
locale?: string locale?: string
req?: Partial<PayloadRequest> req?: Partial<PayloadRequest>
@@ -217,6 +218,7 @@ export type FindOne = <T extends TypeWithID>(args: FindOneArgs) => Promise<null
export type FindArgs = { export type FindArgs = {
collection: CollectionSlug collection: CollectionSlug
draftsEnabled?: boolean
joins?: JoinQuery joins?: JoinQuery
/** Setting limit to 1 is equal to the previous Model.findOne(). Setting limit to 0 disables the limit */ /** Setting limit to 1 is equal to the previous Model.findOne(). Setting limit to 0 disables the limit */
limit?: number limit?: number

View File

@@ -1008,12 +1008,10 @@ export type {
User, User,
VerifyConfig, VerifyConfig,
} from './auth/types.js' } from './auth/types.js'
export { generateImportMap } from './bin/generateImportMap/index.js' export { generateImportMap } from './bin/generateImportMap/index.js'
export type { ImportMap } from './bin/generateImportMap/index.js' export type { ImportMap } from './bin/generateImportMap/index.js'
export { genImportMapIterateFields } from './bin/generateImportMap/iterateFields.js' export { genImportMapIterateFields } from './bin/generateImportMap/iterateFields.js'
export { export {
type ClientCollectionConfig, type ClientCollectionConfig,
createClientCollectionConfig, createClientCollectionConfig,
@@ -1060,6 +1058,7 @@ export type {
} from './collections/config/types.js' } from './collections/config/types.js'
export type { CompoundIndex } from './collections/config/types.js' export type { CompoundIndex } from './collections/config/types.js'
export type { SanitizedCompoundIndex } from './collections/config/types.js' export type { SanitizedCompoundIndex } from './collections/config/types.js'
export { createDataloaderCacheKey, getDataLoader } from './collections/dataloader.js' export { createDataloaderCacheKey, getDataLoader } from './collections/dataloader.js'
export { countOperation } from './collections/operations/count.js' export { countOperation } from './collections/operations/count.js'
@@ -1084,6 +1083,7 @@ export {
serverOnlyConfigProperties, serverOnlyConfigProperties,
type UnsanitizedClientConfig, type UnsanitizedClientConfig,
} from './config/client.js' } from './config/client.js'
export { defaults } from './config/defaults.js' export { defaults } from './config/defaults.js'
export { sanitizeConfig } from './config/sanitize.js' export { sanitizeConfig } from './config/sanitize.js'
export type * from './config/types.js' export type * from './config/types.js'
@@ -1313,6 +1313,7 @@ export type {
} from './fields/config/types.js' } from './fields/config/types.js'
export { getDefaultValue } from './fields/getDefaultValue.js' export { getDefaultValue } from './fields/getDefaultValue.js'
export { traverseFields as afterChangeTraverseFields } from './fields/hooks/afterChange/traverseFields.js' export { traverseFields as afterChangeTraverseFields } from './fields/hooks/afterChange/traverseFields.js'
export { promise as afterReadPromise } from './fields/hooks/afterRead/promise.js' export { promise as afterReadPromise } from './fields/hooks/afterRead/promise.js'
export { traverseFields as afterReadTraverseFields } from './fields/hooks/afterRead/traverseFields.js' export { traverseFields as afterReadTraverseFields } from './fields/hooks/afterRead/traverseFields.js'
@@ -1352,7 +1353,6 @@ export type {
UploadFieldValidation, UploadFieldValidation,
UsernameFieldValidation, UsernameFieldValidation,
} from './fields/validations.js' } from './fields/validations.js'
export { export {
type ClientGlobalConfig, type ClientGlobalConfig,
createClientGlobalConfig, createClientGlobalConfig,
@@ -1374,6 +1374,7 @@ export type {
} from './globals/config/types.js' } from './globals/config/types.js'
export { docAccessOperation as docAccessOperationGlobal } from './globals/operations/docAccess.js' export { docAccessOperation as docAccessOperationGlobal } from './globals/operations/docAccess.js'
export { findOneOperation } from './globals/operations/findOne.js' export { findOneOperation } from './globals/operations/findOne.js'
export { findVersionByIDOperation as findVersionByIDOperationGlobal } from './globals/operations/findVersionByID.js' export { findVersionByIDOperation as findVersionByIDOperationGlobal } from './globals/operations/findVersionByID.js'
export { findVersionsOperation as findVersionsOperationGlobal } from './globals/operations/findVersions.js' export { findVersionsOperation as findVersionsOperationGlobal } from './globals/operations/findVersions.js'
@@ -1423,6 +1424,7 @@ export { getFileByPath } from './uploads/getFileByPath.js'
export type * from './uploads/types.js' export type * from './uploads/types.js'
export { addDataAndFileToRequest } from './utilities/addDataAndFileToRequest.js' export { addDataAndFileToRequest } from './utilities/addDataAndFileToRequest.js'
export { addLocalesToRequestFromData, sanitizeLocales } from './utilities/addLocalesToRequest.js' export { addLocalesToRequestFromData, sanitizeLocales } from './utilities/addLocalesToRequest.js'
export { commitTransaction } from './utilities/commitTransaction.js' export { commitTransaction } from './utilities/commitTransaction.js'
export { export {
@@ -1490,6 +1492,8 @@ export { buildVersionGlobalFields } from './versions/buildGlobalFields.js'
export { buildVersionCompoundIndexes } from './versions/buildVersionCompoundIndexes.js' export { buildVersionCompoundIndexes } from './versions/buildVersionCompoundIndexes.js'
export { versionDefaults } from './versions/defaults.js' export { versionDefaults } from './versions/defaults.js'
export { deleteCollectionVersions } from './versions/deleteCollectionVersions.js' export { deleteCollectionVersions } from './versions/deleteCollectionVersions.js'
export { appendVersionToQueryKey } from './versions/drafts/appendVersionToQueryKey.js'
export { getQueryDraftsSort } from './versions/drafts/getQueryDraftsSort.js'
export { enforceMaxVersions } from './versions/enforceMaxVersions.js' export { enforceMaxVersions } from './versions/enforceMaxVersions.js'
export { getLatestCollectionVersion } from './versions/getLatestCollectionVersion.js' export { getLatestCollectionVersion } from './versions/getLatestCollectionVersion.js'
export { getLatestGlobalVersion } from './versions/getLatestGlobalVersion.js' export { getLatestGlobalVersion } from './versions/getLatestGlobalVersion.js'

View File

@@ -8,7 +8,6 @@ import type { PayloadRequest, SelectType, Where } from '../../types/index.js'
import { hasWhereAccessResult } from '../../auth/index.js' import { hasWhereAccessResult } from '../../auth/index.js'
import { combineQueries } from '../../database/combineQueries.js' import { combineQueries } from '../../database/combineQueries.js'
import { docHasTimestamps } from '../../types/index.js' import { docHasTimestamps } from '../../types/index.js'
import { deepCopyObjectSimple } from '../../utilities/deepCopyObject.js'
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields.js' import sanitizeInternalFields from '../../utilities/sanitizeInternalFields.js'
import { appendVersionToQueryKey } from './appendVersionToQueryKey.js' import { appendVersionToQueryKey } from './appendVersionToQueryKey.js'
import { getQueryDraftsSelect } from './getQueryDraftsSelect.js' import { getQueryDraftsSelect } from './getQueryDraftsSelect.js'

View File

@@ -190,7 +190,7 @@ export function UploadInput(props: UploadInputProps) {
const populateDocs = React.useCallback<PopulateDocs>( const populateDocs = React.useCallback<PopulateDocs>(
async (ids, relatedCollectionSlug) => { async (ids, relatedCollectionSlug) => {
if (!ids.length) { if (!ids.length) {
return; return
} }
const query: { const query: {

View File

@@ -606,6 +606,27 @@ describe('Joins Field', () => {
expect(res.docs[0].relatedVersions.docs[0].id).toBe(version.id) expect(res.docs[0].relatedVersions.docs[0].id).toBe(version.id)
}) })
it('should populate joins with hasMany when on both sides documents are in draft', async () => {
const category = await payload.create({
collection: 'categories-versions',
data: { _status: 'draft' },
draft: true,
})
const version = await payload.create({
collection: 'versions',
data: { _status: 'draft', categoryVersion: category.id },
draft: true,
})
const res = await payload.find({
collection: 'categories-versions',
draft: true,
})
expect(res.docs[0].relatedVersions.docs[0].id).toBe(version.id)
})
it('should populate joins when versions on both sides draft true payload.db.queryDrafts', async () => { it('should populate joins when versions on both sides draft true payload.db.queryDrafts', async () => {
const category = await payload.create({ collection: 'categories-versions', data: {} }) const category = await payload.create({ collection: 'categories-versions', data: {} })