Fixes #13756 The findByID endpoint, by default, expects the data for localized fields to be an object, values mapped to the locale. This is not the case for client-side live preview, as we send already-flattened data to the findByID endpoint. For localized fields where the value is an object (richText/json/group), the afterRead hook handler would attempt to flatten the field value, even though it was already flattened. ## Solution The solution is to expose a `flattenLocales` arg to the findByID endpoint (default: true) and pass `flattenLocales: false` from the client-side live preview request handler. --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1211334752795627
124 lines
4.3 KiB
TypeScript
124 lines
4.3 KiB
TypeScript
import type { GlobalSlug, Payload, RequestContext, TypedLocale } from '../../../index.js'
|
|
import type {
|
|
Document,
|
|
PayloadRequest,
|
|
PopulateType,
|
|
SelectType,
|
|
TransformGlobalWithSelect,
|
|
} from '../../../types/index.js'
|
|
import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js'
|
|
import type { SelectFromGlobalSlug } from '../../config/types.js'
|
|
|
|
import { APIError } from '../../../errors/index.js'
|
|
import { createLocalReq } from '../../../utilities/createLocalReq.js'
|
|
import { findOneOperation, type GlobalFindOneArgs } from '../findOne.js'
|
|
|
|
export type Options<TSlug extends GlobalSlug, TSelect extends SelectType> = {
|
|
/**
|
|
* [Context](https://payloadcms.com/docs/hooks/context), which will then be passed to `context` and `req.context`,
|
|
* which can be read by hooks. Useful if you want to pass additional information to the hooks which
|
|
* shouldn't be necessarily part of the document, for example a `triggerBeforeChange` option which can be read by the BeforeChange hook
|
|
* to determine if it should run or not.
|
|
*/
|
|
context?: RequestContext
|
|
/**
|
|
* You may pass the document data directly which will skip the `db.findOne` database query.
|
|
* This is useful if you want to use this endpoint solely for running hooks and populating data.
|
|
*/
|
|
data?: Record<string, unknown>
|
|
/**
|
|
* [Control auto-population](https://payloadcms.com/docs/queries/depth) of nested relationship and upload fields.
|
|
*/
|
|
depth?: number
|
|
/**
|
|
* Whether the document should be queried from the versions table/collection or not. [More](https://payloadcms.com/docs/versions/drafts#draft-api)
|
|
*/
|
|
draft?: boolean
|
|
/**
|
|
* Specify a [fallback locale](https://payloadcms.com/docs/configuration/localization) to use for any returned documents.
|
|
*/
|
|
fallbackLocale?: false | TypedLocale
|
|
/**
|
|
* Include info about the lock status to the result with fields: `_isLocked` and `_userEditing`
|
|
*/
|
|
includeLockStatus?: boolean
|
|
/**
|
|
* Specify [locale](https://payloadcms.com/docs/configuration/localization) for any returned documents.
|
|
*/
|
|
locale?: 'all' | TypedLocale
|
|
/**
|
|
* Skip access control.
|
|
* Set to `false` if you want to respect Access Control for the operation, for example when fetching data for the front-end.
|
|
* @default true
|
|
*/
|
|
overrideAccess?: boolean
|
|
/**
|
|
* Specify [populate](https://payloadcms.com/docs/queries/select#populate) to control which fields to include to the result from populated documents.
|
|
*/
|
|
populate?: PopulateType
|
|
/**
|
|
* The `PayloadRequest` object. You can pass it to thread the current [transaction](https://payloadcms.com/docs/database/transactions), user and locale to the operation.
|
|
* Recommended to pass when using the Local API from hooks, as usually you want to execute the operation within the current transaction.
|
|
*/
|
|
req?: Partial<PayloadRequest>
|
|
/**
|
|
* Specify [select](https://payloadcms.com/docs/queries/select) to control which fields to include to the result.
|
|
*/
|
|
select?: TSelect
|
|
/**
|
|
* Opt-in to receiving hidden fields. By default, they are hidden from returned documents in accordance to your config.
|
|
* @default false
|
|
*/
|
|
showHiddenFields?: boolean
|
|
/**
|
|
* the Global slug to operate against.
|
|
*/
|
|
slug: TSlug
|
|
/**
|
|
* If you set `overrideAccess` to `false`, you can pass a user to use against the access control checks.
|
|
*/
|
|
user?: Document
|
|
} & Pick<GlobalFindOneArgs, 'flattenLocales'>
|
|
|
|
export async function findOneGlobalLocal<
|
|
TSlug extends GlobalSlug,
|
|
TSelect extends SelectFromGlobalSlug<TSlug>,
|
|
>(
|
|
payload: Payload,
|
|
options: Options<TSlug, TSelect>,
|
|
): Promise<TransformGlobalWithSelect<TSlug, TSelect>> {
|
|
const {
|
|
slug: globalSlug,
|
|
data,
|
|
depth,
|
|
draft = false,
|
|
flattenLocales,
|
|
includeLockStatus,
|
|
overrideAccess = true,
|
|
populate,
|
|
select,
|
|
showHiddenFields,
|
|
} = options
|
|
|
|
const globalConfig = payload.globals.config.find((config) => config.slug === globalSlug)
|
|
|
|
if (!globalConfig) {
|
|
throw new APIError(`The global with slug ${String(globalSlug)} can't be found.`)
|
|
}
|
|
|
|
return findOneOperation({
|
|
slug: globalSlug as string,
|
|
data,
|
|
depth,
|
|
draft,
|
|
flattenLocales,
|
|
globalConfig,
|
|
includeLockStatus,
|
|
overrideAccess,
|
|
populate,
|
|
req: await createLocalReq(options as CreateLocalReqOptions, payload),
|
|
select,
|
|
showHiddenFields,
|
|
})
|
|
}
|