Skip to content

Commit c8332e7

Browse files
authored
feat: add missing disableErrors to globals findOne operation (#14913)
### What? This PR introduces the `disableErrors` option into the global `findOne` operation. ### Why? `disableErrors` is handy for certain flows where a user may be unauthorised but you don't need an error to be thrown, instead you would prefer an empty result. Without this, the developer needs to catch the error themselves, leading to inconsistencies as some operations have `disableErrors` and others do not. ### How? Introduced the `disableErrors` option to the global `findOne` operation. ### Additional information - Initial [discord discussion](https://discord.com/channels/967097582721572934/1102950643259424828/1438504179961430059). - A [PR](#6357) was created to address this in mid 2024 but was later closed. - There is opportunity here to include `disableErrors` in a number of operations that seem to be lacking it, especially in the `sdk` package. Originally I included these changes in this PR but have since removed to instead allow for some discussion before we consider introducing them in a separate PR. - There is opportunity to introduce better test coverage in a separate PR for `disableErrors` across existing operations that use it. - In `packages/payload/src/collections/operations/restoreVersion.ts`, `disableErrors` exists in the types but is not actually implemented. I have left this as is for now but wanted to flag it.
1 parent b505e36 commit c8332e7

3 files changed

Lines changed: 31 additions & 3 deletions

File tree

packages/payload/src/globals/operations/findOne.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type GlobalFindOneArgs = {
2828
*/
2929
data?: Record<string, unknown>
3030
depth?: number
31+
disableErrors?: boolean
3132
draft?: boolean
3233
globalConfig: SanitizedGlobalConfig
3334
includeLockStatus?: boolean
@@ -45,6 +46,7 @@ export const findOneOperation = async <T extends Record<string, unknown>>(
4546
const {
4647
slug,
4748
depth,
49+
disableErrors,
4850
draft: replaceWithVersion = false,
4951
flattenLocales,
5052
globalConfig,
@@ -86,11 +88,14 @@ export const findOneOperation = async <T extends Record<string, unknown>>(
8688
let accessResult!: AccessResult
8789

8890
if (!overrideAccess) {
89-
accessResult = await executeAccess({ req }, globalConfig.access.read)
91+
accessResult = await executeAccess({ disableErrors, req }, globalConfig.access.read)
9092
}
9193

9294
if (accessResult === false) {
93-
throw new NotFound(req.t)
95+
if (!disableErrors) {
96+
throw new NotFound(req.t)
97+
}
98+
return null!
9499
}
95100

96101
const select = sanitizeSelect({
@@ -125,7 +130,10 @@ export const findOneOperation = async <T extends Record<string, unknown>>(
125130
const hasDoc = docFromDB && Object.keys(docFromDB).length > 0
126131

127132
if (!hasDoc && !args.data && !overrideAccess && accessResult !== true) {
128-
return {} as any
133+
if (!disableErrors) {
134+
return {} as any
135+
}
136+
return null!
129137
}
130138

131139
let doc = (args.data as any) ?? (hasDoc ? docFromDB : null) ?? {}

packages/payload/src/globals/operations/local/findOne.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ type BaseFindOneOptions<TSlug extends GlobalSlug, TSelect extends SelectType> =
4040
* [Control auto-population](https://payloadcms.com/docs/queries/depth) of nested relationship and upload fields.
4141
*/
4242
depth?: number
43+
/**
44+
* When set to `true`, errors will not be thrown.
45+
*/
46+
disableErrors?: boolean
47+
/**
48+
* Whether the document should be queried from the versions table/collection or not. [More](https://payloadcms.com/docs/versions/drafts#draft-api)
49+
*/
50+
draft?: boolean
4351
/**
4452
* Specify a [fallback locale](https://payloadcms.com/docs/configuration/localization) to use for any returned documents.
4553
*/
@@ -98,6 +106,7 @@ export async function findOneGlobalLocal<
98106
slug: globalSlug,
99107
data,
100108
depth,
109+
disableErrors,
101110
draft = false,
102111
flattenLocales,
103112
includeLockStatus,
@@ -117,6 +126,7 @@ export async function findOneGlobalLocal<
117126
slug: globalSlug as string,
118127
data,
119128
depth,
129+
disableErrors,
120130
draft,
121131
flattenLocales,
122132
globalConfig,

test/globals/int.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,16 @@ describe('globals', () => {
173173
expect(es).toMatchObject(localized.es)
174174
})
175175

176+
it('should return null when user is unauthorised and using findGlobal with disableErrors: true', async () => {
177+
const doc = await payload.findGlobal({
178+
disableErrors: true,
179+
overrideAccess: false,
180+
slug: accessControlSlug,
181+
})
182+
183+
expect(doc).toBeNull()
184+
})
185+
176186
it('should respect valid access query constraint', async () => {
177187
const emptyGlobal = await payload.findGlobal({
178188
overrideAccess: false,

0 commit comments

Comments
 (0)