Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions packages/payload/src/collections/config/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -139,78 +141,100 @@ 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
}

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,
fields: collection.fields,
i18n,
importMap,
})

break

case 'labels':
clientCollection.labels = {
plural:
Expand All @@ -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 }
Expand All @@ -245,6 +274,7 @@ export const createClientCollectionConfig = ({
collection.upload[uploadKey as keyof SanitizedUploadConfig]
}
}

break

default:
Expand Down
38 changes: 35 additions & 3 deletions packages/payload/src/config/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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[]
Expand All @@ -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>
Expand Down Expand Up @@ -103,6 +103,7 @@ export const createClientConfig = ({
if (serverOnlyConfigProperties.includes(key as any)) {
continue
}

switch (key) {
case 'admin':
clientConfig.admin = {
Expand All @@ -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!,
Expand All @@ -135,14 +147,17 @@ export const createClientConfig = ({

break
}

case 'collections':
;(clientConfig.collections as ClientCollectionConfig[]) = createClientCollectionConfigs({
collections: config.collections,
defaultIDType: config.db.defaultIDType,
i18n,
importMap,
})

break

case 'folders':
if (config.folders) {
clientConfig.folders = {
Expand All @@ -152,6 +167,7 @@ export const createClientConfig = ({
fieldName: config.folders.fieldName,
}
}

break

case 'globals':
Expand All @@ -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
}
12 changes: 7 additions & 5 deletions packages/payload/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ export type LivePreviewConfig = {
| string
}

export type RootLivePreviewConfig = {
collections?: string[]
globals?: string[]
} & LivePreviewConfig

export type OGImageConfig = {
alt?: string
height?: number | string
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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?: {
Expand Down
Loading