diff --git a/packages/graphql/src/resolvers/globals/findOne.ts b/packages/graphql/src/resolvers/globals/findOne.ts index c5d499e4fa..4156e2b5c5 100644 --- a/packages/graphql/src/resolvers/globals/findOne.ts +++ b/packages/graphql/src/resolvers/globals/findOne.ts @@ -1,23 +1,39 @@ -import type { Document, SanitizedGlobalConfig } from 'payload/types' +import type { PayloadRequest } from 'payload/types' import { findOneOperation } from 'payload/operations' +import { type Document, type SanitizedGlobalConfig } from 'payload/types' import { isolateObjectProperty } from 'payload/utilities' import type { Context } from '../types.js' export default function findOneResolver(globalConfig: SanitizedGlobalConfig): Document { return async function resolver(_, args, context: Context) { - if (args.locale) context.req.locale = args.locale - if (args.fallbackLocale) context.req.fallbackLocale = args.fallbackLocale + let { req } = context + const locale = req.locale + const fallbackLocale = req.fallbackLocale + req = isolateObjectProperty(req, 'locale') + req = isolateObjectProperty(req, 'fallbackLocale') + req.locale = args.locale || locale + req.fallbackLocale = args.fallbackLocale || fallbackLocale - const { slug } = globalConfig + if (!req.query) req.query = {} + + const draft: boolean = + args.draft ?? req.query?.draft === 'false' + ? false + : req.query?.draft === 'true' + ? true + : undefined + if (typeof draft === 'boolean') req.query.draft = String(draft) + + context.req = req const options = { - slug, + slug: globalConfig.slug, depth: 0, draft: args.draft, globalConfig, - req: isolateObjectProperty(context.req, 'transactionID'), + req: isolateObjectProperty(req, 'transactionID'), } const result = await findOneOperation(options) diff --git a/packages/graphql/src/resolvers/globals/findVersionByID.ts b/packages/graphql/src/resolvers/globals/findVersionByID.ts index be6a072e14..d794726439 100644 --- a/packages/graphql/src/resolvers/globals/findVersionByID.ts +++ b/packages/graphql/src/resolvers/globals/findVersionByID.ts @@ -1,6 +1,11 @@ -import type { Document, PayloadRequestWithData, SanitizedGlobalConfig } from 'payload/types' +import type { PayloadRequest } from 'payload/types' import { findVersionByIDOperationGlobal } from 'payload/operations' +import { + type Document, + type PayloadRequestWithData, + type SanitizedGlobalConfig, +} from 'payload/types' import { isolateObjectProperty } from 'payload/utilities' import type { Context } from '../types.js' @@ -20,15 +25,21 @@ export type Resolver = ( export default function findVersionByIDResolver(globalConfig: SanitizedGlobalConfig): Resolver { return async function resolver(_, args, context: Context) { - if (args.locale) context.req.locale = args.locale - if (args.fallbackLocale) context.req.fallbackLocale = args.fallbackLocale + let { req } = context + const locale = req.locale + const fallbackLocale = req.fallbackLocale + req = isolateObjectProperty(req, 'locale') + req = isolateObjectProperty(req, 'fallbackLocale') + req.locale = args.locale || locale + req.fallbackLocale = args.fallbackLocale || fallbackLocale + + context.req = req const options = { id: args.id, depth: 0, - draft: args.draft, globalConfig, - req: isolateObjectProperty(context.req, 'transactionID'), + req: isolateObjectProperty(req, 'transactionID'), } const result = await findVersionByIDOperationGlobal(options) diff --git a/packages/graphql/src/resolvers/globals/restoreVersion.ts b/packages/graphql/src/resolvers/globals/restoreVersion.ts index f8eb61dcee..c7584f28e8 100644 --- a/packages/graphql/src/resolvers/globals/restoreVersion.ts +++ b/packages/graphql/src/resolvers/globals/restoreVersion.ts @@ -1,4 +1,9 @@ -import type { Document, PayloadRequestWithData, SanitizedGlobalConfig } from 'payload/types' +import type { + Document, + PayloadRequest, + PayloadRequestWithData, + SanitizedGlobalConfig, +} from 'payload/types' import { restoreVersionOperationGlobal } from 'payload/operations' import { isolateObjectProperty } from 'payload/utilities' @@ -20,7 +25,7 @@ export default function restoreVersionResolver(globalConfig: SanitizedGlobalConf id: args.id, depth: 0, globalConfig, - req: isolateObjectProperty(context.req, 'transactionID'), + req: isolateObjectProperty(context.req, 'transactionID'), } const result = await restoreVersionOperationGlobal(options) diff --git a/packages/graphql/src/resolvers/globals/update.ts b/packages/graphql/src/resolvers/globals/update.ts index 3b574af920..69982b67f6 100644 --- a/packages/graphql/src/resolvers/globals/update.ts +++ b/packages/graphql/src/resolvers/globals/update.ts @@ -1,5 +1,5 @@ import type { GeneratedTypes } from 'payload' -import type { PayloadRequestWithData, SanitizedGlobalConfig } from 'payload/types' +import type { PayloadRequest, PayloadRequestWithData, SanitizedGlobalConfig } from 'payload/types' import type { DeepPartial } from 'ts-essentials' import { updateOperationGlobal } from 'payload/operations' @@ -24,18 +24,32 @@ export default function updateResolver { return async function resolver(_, args, context: Context) { - if (args.locale) context.req.locale = args.locale - if (args.fallbackLocale) context.req.fallbackLocale = args.fallbackLocale + let { req } = context + const locale = req.locale + const fallbackLocale = req.fallbackLocale + req = isolateObjectProperty(req, 'locale') + req = isolateObjectProperty(req, 'fallbackLocale') + req.locale = args.locale || locale + req.fallbackLocale = args.fallbackLocale || fallbackLocale + if (!req.query) req.query = {} - const { slug } = globalConfig + const draft: boolean = + args.draft ?? req.query?.draft === 'false' + ? false + : req.query?.draft === 'true' + ? true + : undefined + if (typeof draft === 'boolean') req.query.draft = String(draft) + + context.req = req const options = { - slug, + slug: globalConfig.slug, data: args.data, depth: 0, draft: args.draft, globalConfig, - req: isolateObjectProperty(context.req, 'transactionID'), + req: isolateObjectProperty(req, 'transactionID'), } const result = await updateOperationGlobal(options) diff --git a/packages/payload/src/utilities/isolateObjectProperty.ts b/packages/payload/src/utilities/isolateObjectProperty.ts index 83b481f0c8..9e077d40f3 100644 --- a/packages/payload/src/utilities/isolateObjectProperty.ts +++ b/packages/payload/src/utilities/isolateObjectProperty.ts @@ -1,7 +1,7 @@ /** * Creates a proxy for the given object that has its own property */ -export default function isolateObjectProperty(object: T, key): T { +export default function isolateObjectProperty(object: T, key: keyof T): T { const delegate = {} const handler = { deleteProperty(target, p): boolean { diff --git a/test/collections-graphql/config.ts b/test/collections-graphql/config.ts index 7e791593b4..238be52268 100644 --- a/test/collections-graphql/config.ts +++ b/test/collections-graphql/config.ts @@ -373,6 +373,29 @@ export default buildConfigWithDefaults({ ], }, ], + globals: [ + { + slug: 'global-1', + access: { + read: openAccess.read, + update: openAccess.update, + }, + fields: [ + { + type: 'text', + name: 'title', + }, + { + name: 'relationship', + type: 'relationship', + relationTo: 'cyclical-relationship', + }, + ], + versions: { + drafts: true, + }, + }, + ], graphQL: { queries: (GraphQL) => { return { diff --git a/test/collections-graphql/int.spec.ts b/test/collections-graphql/int.spec.ts index cbba179d90..f6f7055f63 100644 --- a/test/collections-graphql/int.spec.ts +++ b/test/collections-graphql/int.spec.ts @@ -1117,6 +1117,63 @@ describe('collections-graphql', () => { expect(queriedDoc.media.title).toEqual('example') }) + it('should cascade draft arg with globals', async () => { + // publish relationship doc + const newDoc = await payload.create({ + collection: 'cyclical-relationship', + draft: false, + data: { + title: 'published relationship', + }, + }) + + // save draft version relationship doc + await payload.update({ + collection: 'cyclical-relationship', + id: newDoc.id, + draft: true, + data: { + title: 'draft relationship', + }, + }) + + // update global (published data) + await payload.updateGlobal({ + slug: 'global-1', + data: { + title: 'published title', + relationship: newDoc.id, + }, + }) + + // update global (draft data) + await payload.updateGlobal({ + slug: 'global-1', + draft: true, + data: { + title: 'draft title', + }, + }) + + const query = `{ + Global1(draft: true) { + title + relationship { + title + } + } + }` + const res1 = await restClient + .GRAPHQL_POST({ + body: JSON.stringify({ query }), + }) + .then((res) => res.json()) + + const queriedGlobal = res1.data.Global1 + expect(queriedGlobal.title).toEqual('draft title') + expect(queriedGlobal.relationship.title).toEqual('draft relationship') + }) + describe('Error Handler', () => { it('should return have an array of errors when making a bad request', async () => { const query = `query {