### 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.
222 lines
4.7 KiB
TypeScript
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,
|
|
},
|
|
],
|
|
}
|