Compare commits

...

1 Commits

Author SHA1 Message Date
Jarrod Flesch
1b0afee70e fix: cascade draft arg when querying globals with graphql 2024-06-06 10:35:23 -04:00
7 changed files with 146 additions and 20 deletions

View File

@@ -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<PayloadRequest>(req, 'locale')
req = isolateObjectProperty<PayloadRequest>(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<PayloadRequest>(req, 'transactionID'),
}
const result = await findOneOperation(options)

View File

@@ -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<PayloadRequest>(req, 'locale')
req = isolateObjectProperty<PayloadRequest>(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<PayloadRequest>(req, 'transactionID'),
}
const result = await findVersionByIDOperationGlobal(options)

View File

@@ -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<PayloadRequest>(context.req, 'transactionID'),
}
const result = await restoreVersionOperationGlobal(options)

View File

@@ -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<TSlug extends keyof GeneratedTypes['globa
globalConfig: SanitizedGlobalConfig,
): Resolver<TSlug> {
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<PayloadRequest>(req, 'locale')
req = isolateObjectProperty<PayloadRequest>(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<PayloadRequest>(req, 'transactionID'),
}
const result = await updateOperationGlobal<TSlug>(options)

View File

@@ -1,7 +1,7 @@
/**
* Creates a proxy for the given object that has its own property
*/
export default function isolateObjectProperty<T>(object: T, key): T {
export default function isolateObjectProperty<T>(object: T, key: keyof T): T {
const delegate = {}
const handler = {
deleteProperty(target, p): boolean {

View File

@@ -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 {

View File

@@ -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 {