fix: restore missing properties to live preview client config (#12904)

Needed for #12860.

The client config unnecessarily omits the `livePreview.collections` and
`livePreview.globals` properties. This is because the root live preview
config extends the type with these two additional properties without
sharing it elsewhere. To led to the client sanitization function
overlooking these additional properties, as there was no type indication
that they exist.

The `collections` and `globals` properties are now appended to the
client config as expected, and the root live preview is standardized
behind the `RootLivePreviewConfig` type to ensure no properties are
lost.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210628466702823
This commit is contained in:
Jacob Fletcher
2025-06-26 14:05:10 -04:00
committed by GitHub
parent 87c7952558
commit bcb10b52b3
3 changed files with 75 additions and 11 deletions

View File

@@ -122,7 +122,9 @@ export const createClientCollectionConfig = ({
if (!collection.admin) {
break
}
clientCollection.admin = {} as ClientCollectionConfig['admin']
for (const adminKey in collection.admin) {
if (serverOnlyCollectionAdminProperties.includes(adminKey as any)) {
continue
@@ -139,56 +141,72 @@ export const createClientCollectionConfig = ({
}
} else if (typeof collection.admin.description === 'function') {
const description = collection.admin.description({ t: i18n.t as TFunction })
if (description) {
clientCollection.admin.description = description
}
}
break
case 'livePreview':
clientCollection.admin.livePreview =
{} as ClientCollectionConfig['admin']['livePreview']
clientCollection.admin.livePreview = {}
if (collection.admin.livePreview?.breakpoints) {
clientCollection.admin.livePreview!.breakpoints =
clientCollection.admin.livePreview.breakpoints =
collection.admin.livePreview.breakpoints
}
break
case 'preview':
if (collection.admin.preview) {
clientCollection.admin.preview = true
}
break
default:
;(clientCollection as any).admin[adminKey] =
collection.admin[adminKey as keyof SanitizedCollectionConfig['admin']]
}
}
break
case 'auth':
if (!collection.auth) {
break
}
clientCollection.auth = {} as { verify?: true } & SanitizedCollectionConfig['auth']
if (collection.auth.cookies) {
clientCollection.auth.cookies = collection.auth.cookies
}
if (collection.auth.depth !== undefined) {
// Check for undefined as it can be a number (0)
clientCollection.auth.depth = collection.auth.depth
}
if (collection.auth.disableLocalStrategy) {
clientCollection.auth.disableLocalStrategy = collection.auth.disableLocalStrategy
}
if (collection.auth.lockTime !== undefined) {
// Check for undefined as it can be a number (0)
clientCollection.auth.lockTime = collection.auth.lockTime
}
if (collection.auth.loginWithUsername) {
clientCollection.auth.loginWithUsername = collection.auth.loginWithUsername
}
if (collection.auth.maxLoginAttempts !== undefined) {
// Check for undefined as it can be a number (0)
clientCollection.auth.maxLoginAttempts = collection.auth.maxLoginAttempts
}
if (collection.auth.removeTokenFromResponses) {
clientCollection.auth.removeTokenFromResponses = collection.auth.removeTokenFromResponses
}
@@ -196,13 +214,17 @@ export const createClientCollectionConfig = ({
if (collection.auth.useAPIKey) {
clientCollection.auth.useAPIKey = collection.auth.useAPIKey
}
if (collection.auth.tokenExpiration) {
clientCollection.auth.tokenExpiration = collection.auth.tokenExpiration
}
if (collection.auth.verify) {
clientCollection.auth.verify = true
}
break
case 'fields':
clientCollection.fields = createClientFields({
defaultIDType,
@@ -210,7 +232,9 @@ export const createClientCollectionConfig = ({
i18n,
importMap,
})
break
case 'labels':
clientCollection.labels = {
plural:
@@ -222,16 +246,21 @@ export const createClientCollectionConfig = ({
? collection.labels.singular({ i18n, t: i18n.t as TFunction })
: collection.labels.singular,
}
break
case 'upload':
if (!collection.upload) {
break
}
clientCollection.upload = {} as SanitizedUploadConfig
for (const uploadKey in collection.upload) {
if (serverOnlyUploadProperties.includes(uploadKey as any)) {
continue
}
if (uploadKey === 'imageSizes') {
clientCollection.upload.imageSizes = collection.upload.imageSizes?.map((size) => {
const sanitizedSize = { ...size }
@@ -245,6 +274,7 @@ export const createClientCollectionConfig = ({
collection.upload[uploadKey as keyof SanitizedUploadConfig]
}
}
break
default:

View File

@@ -5,7 +5,7 @@ import type { ImportMap } from '../bin/generateImportMap/index.js'
import type { ClientBlock } from '../fields/config/types.js'
import type { BlockSlug } from '../index.js'
import type {
LivePreviewConfig,
RootLivePreviewConfig,
SanitizedConfig,
ServerOnlyLivePreviewProperties,
} from './types.js'
@@ -44,7 +44,7 @@ export type ServerOnlyRootAdminProperties = keyof Pick<SanitizedConfig['admin'],
export type UnsanitizedClientConfig = {
admin: {
livePreview?: Omit<LivePreviewConfig, ServerOnlyLivePreviewProperties>
livePreview?: Omit<RootLivePreviewConfig, ServerOnlyLivePreviewProperties>
} & Omit<SanitizedConfig['admin'], 'components' | 'dependencies' | 'livePreview'>
blocks: ClientBlock[]
collections: ClientCollectionConfig[]
@@ -54,7 +54,7 @@ export type UnsanitizedClientConfig = {
export type ClientConfig = {
admin: {
livePreview?: Omit<LivePreviewConfig, ServerOnlyLivePreviewProperties>
livePreview?: Omit<RootLivePreviewConfig, ServerOnlyLivePreviewProperties>
} & Omit<SanitizedConfig['admin'], 'components' | 'dependencies' | 'livePreview'>
blocks: ClientBlock[]
blocksMap: Record<BlockSlug, ClientBlock>
@@ -103,6 +103,7 @@ export const createClientConfig = ({
if (serverOnlyConfigProperties.includes(key as any)) {
continue
}
switch (key) {
case 'admin':
clientConfig.admin = {
@@ -117,14 +118,25 @@ export const createClientConfig = ({
timezones: config.admin.timezones,
user: config.admin.user,
}
if (config.admin.livePreview) {
clientConfig.admin.livePreview = {}
if (config.admin.livePreview.breakpoints) {
clientConfig.admin.livePreview.breakpoints = config.admin.livePreview.breakpoints
}
if (config.admin.livePreview.collections) {
clientConfig.admin.livePreview.collections = config.admin.livePreview.collections
}
if (config.admin.livePreview.globals) {
clientConfig.admin.livePreview.globals = config.admin.livePreview.globals
}
}
break
case 'blocks': {
;(clientConfig.blocks as ClientBlock[]) = createClientBlocks({
blocks: config.blocks!,
@@ -135,6 +147,7 @@ export const createClientConfig = ({
break
}
case 'collections':
;(clientConfig.collections as ClientCollectionConfig[]) = createClientCollectionConfigs({
collections: config.collections,
@@ -142,7 +155,9 @@ export const createClientConfig = ({
i18n,
importMap,
})
break
case 'folders':
if (config.folders) {
clientConfig.folders = {
@@ -152,6 +167,7 @@ export const createClientConfig = ({
fieldName: config.folders.fieldName,
}
}
break
case 'globals':
@@ -161,49 +177,65 @@ export const createClientConfig = ({
i18n,
importMap,
})
break
case 'localization':
if (typeof config.localization === 'object' && config.localization) {
clientConfig.localization = {}
if (config.localization.defaultLocale) {
clientConfig.localization.defaultLocale = config.localization.defaultLocale
}
if (config.localization.defaultLocalePublishOption) {
clientConfig.localization.defaultLocalePublishOption =
config.localization.defaultLocalePublishOption
}
if (config.localization.fallback) {
clientConfig.localization.fallback = config.localization.fallback
}
if (config.localization.localeCodes) {
clientConfig.localization.localeCodes = config.localization.localeCodes
}
if (config.localization.locales) {
clientConfig.localization.locales = []
for (const locale of config.localization.locales) {
if (locale) {
const clientLocale: Partial<(typeof config.localization.locales)[0]> = {}
if (locale.code) {
clientLocale.code = locale.code
}
if (locale.fallbackLocale) {
clientLocale.fallbackLocale = locale.fallbackLocale
}
if (locale.label) {
clientLocale.label = locale.label
}
if (locale.rtl) {
clientLocale.rtl = locale.rtl
}
clientConfig.localization.locales.push(clientLocale)
}
}
}
}
break
default:
;(clientConfig as any)[key] = config[key as keyof SanitizedConfig]
}
}
return clientConfig as ClientConfig
}

View File

@@ -172,6 +172,11 @@ export type LivePreviewConfig = {
| string
}
export type RootLivePreviewConfig = {
collections?: string[]
globals?: string[]
} & LivePreviewConfig
export type OGImageConfig = {
alt?: string
height?: number | string
@@ -202,7 +207,7 @@ export type MetaConfig = {
titleSuffix?: string
} & DeepClone<Metadata>
export type ServerOnlyLivePreviewProperties = keyof Pick<LivePreviewConfig, 'url'>
export type ServerOnlyLivePreviewProperties = keyof Pick<RootLivePreviewConfig, 'url'>
type GeneratePreviewURLOptions = {
locale: string
@@ -861,10 +866,7 @@ export type Config = {
*/
importMapFile?: string
}
livePreview?: {
collections?: string[]
globals?: string[]
} & LivePreviewConfig
livePreview?: RootLivePreviewConfig
/** Base meta data to use for the Admin Panel. Included properties are titleSuffix, ogImage, and favicon. */
meta?: MetaConfig
routes?: {