Files
payload/test/plugin-import-export/collections/Pages.ts
Patrik 1cdec861cd test: guard against null values in custom toCSV functions (#12938)
### What?

Fixes a crash when exporting documents to CSV if a custom `toCSV`
function tries to access properties on a `null` value.

### Why?

In some cases (especially with Postgres), fields like relationships may
be explicitly `null` if unset. Custom `toCSV` functions that assume the
value is always defined would throw a `TypeError` when attempting to
access nested properties like `value.id`.

### How?

Added a null check in the custom `toCSV` implementation for
`customRelationship`, ensuring the field is an object before accessing
its properties.

This prevents the export from failing and makes custom field transforms
more resilient to missing or optional values.
2025-06-25 11:45:09 -04:00

222 lines
4.7 KiB
TypeScript

import type { CollectionConfig } from 'payload'
import { pagesSlug } from '../shared.js'
export const Pages: CollectionConfig = {
slug: pagesSlug,
labels: {
singular: { en: 'Page', es: 'Página' },
plural: { en: 'Pages', es: 'Páginas' },
},
admin: {
useAsTitle: 'title',
},
versions: {
drafts: true,
},
fields: [
{
name: 'title',
label: { en: 'Title', es: 'Título', de: 'Titel' },
type: 'text',
required: true,
},
{
name: 'localized',
type: 'text',
localized: true,
},
{
name: 'custom',
type: 'text',
defaultValue: 'my custom csv transformer',
custom: {
'plugin-import-export': {
toCSV: ({ value, columnName, row, siblingDoc }) => {
return String(value) + ' toCSV'
},
},
},
},
{
name: 'customRelationship',
type: 'relationship',
relationTo: 'users',
custom: {
'plugin-import-export': {
toCSV: ({ value, columnName, row }) => {
if (value && typeof value === 'object' && 'id' in value && 'email' in value) {
row[`${columnName}_id`] = (value as { id: number | string }).id
row[`${columnName}_email`] = (value as { email: string }).email
}
},
},
},
},
{
name: 'group',
type: 'group',
fields: [
{
name: 'value',
type: 'text',
defaultValue: 'group value',
},
{
name: 'ignore',
type: 'text',
},
{
name: 'array',
type: 'array',
fields: [
{
name: 'field1',
type: 'text',
},
{
name: 'field2',
type: 'text',
},
],
},
{
name: 'custom',
type: 'text',
defaultValue: 'my custom csv transformer',
custom: {
'plugin-import-export': {
toCSV: ({ value, columnName, row, siblingDoc, doc }) => {
return String(value) + ' toCSV'
},
},
},
},
],
},
{
name: 'tabs',
type: 'tabs',
tabs: [
{
label: 'No Name',
fields: [
{
name: 'tabToCSV',
type: 'text',
defaultValue: 'my custom csv transformer',
custom: {
'plugin-import-export': {
toCSV: ({ value, columnName, row, siblingDoc, doc }) => {
return String(value) + ' toCSV'
},
},
},
},
],
},
{
name: 'namedTab',
fields: [
{
name: 'tabToCSV',
type: 'text',
defaultValue: 'my custom csv transformer',
custom: {
'plugin-import-export': {
toCSV: ({ value, columnName, row, siblingDoc, doc }) => {
return String(value) + ' toCSV'
},
},
},
},
],
},
],
},
{
name: 'array',
type: 'array',
fields: [
{
name: 'field1',
type: 'text',
},
{
name: 'field2',
type: 'text',
},
],
},
{
name: 'blocks',
type: 'blocks',
blocks: [
{
slug: 'hero',
fields: [
{
name: 'title',
type: 'text',
},
],
},
{
slug: 'content',
fields: [
{
name: 'richText',
type: 'richText',
},
],
},
],
},
{
name: 'author',
type: 'relationship',
relationTo: 'users',
},
{
name: 'virtualRelationship',
type: 'text',
virtual: 'author.name',
},
{
name: 'virtual',
type: 'text',
virtual: true,
hooks: {
afterRead: [() => 'virtual value'],
},
},
{
name: 'hasManyNumber',
type: 'number',
hasMany: true,
},
{
name: 'relationship',
type: 'relationship',
relationTo: 'users',
},
{
name: 'excerpt',
label: 'Excerpt',
type: 'text',
},
{
name: 'hasOnePolymorphic',
type: 'relationship',
relationTo: ['users', 'posts'],
hasMany: false,
},
{
name: 'hasManyPolymorphic',
type: 'relationship',
relationTo: ['users', 'posts'],
hasMany: true,
},
],
}