## Description Prior to this change, the `defaultValue` for fields have only been used in the application layer of Payload. With this change, you get the added benefit of having the database columns get the default also. This is especially helpful when adding new columns to postgres with existing data to avoid needing to write complex migrations. In MongoDB this change applies the default to the Mongoose model which is useful when calling payload.db.create() directly. This only works for statically defined values. 🙏 A big thanks to @r1tsuu for the feature and implementation idea as I lifted some code from PR https://github.com/payloadcms/payload/pull/6983 - [x] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [x] New feature (non-breaking change which adds functionality) - [x] This change requires a documentation update ## Checklist: - [x] I have added tests that prove my fix is effective or that my feature works - [x] Existing test suite passes locally with my changes - [x] I have made corresponding changes to the documentation
308 lines
6.8 KiB
TypeScript
308 lines
6.8 KiB
TypeScript
import { fileURLToPath } from 'node:url'
|
|
import path from 'path'
|
|
const filename = fileURLToPath(import.meta.url)
|
|
const dirname = path.dirname(filename)
|
|
import type { TextField } from 'payload'
|
|
|
|
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
|
import { devUser } from '../credentials.js'
|
|
|
|
const defaultValueField: TextField = {
|
|
name: 'defaultValue',
|
|
type: 'text',
|
|
defaultValue: 'default value from database',
|
|
}
|
|
|
|
export default buildConfigWithDefaults({
|
|
collections: [
|
|
{
|
|
slug: 'posts',
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'throwAfterChange',
|
|
type: 'checkbox',
|
|
defaultValue: false,
|
|
hooks: {
|
|
afterChange: [
|
|
({ value }) => {
|
|
if (value) {
|
|
throw new Error('throw after change')
|
|
}
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
hooks: {
|
|
beforeOperation: [
|
|
({ args, operation, req }) => {
|
|
if (operation === 'update') {
|
|
const defaultIDType = req.payload.db.defaultIDType
|
|
|
|
if (defaultIDType === 'number' && typeof args.id === 'string') {
|
|
throw new Error('ID was not sanitized to a number properly')
|
|
}
|
|
}
|
|
|
|
return args
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
slug: 'default-values',
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
},
|
|
defaultValueField,
|
|
{
|
|
name: 'array',
|
|
type: 'array',
|
|
// default array with one object to test subfield defaultValue properties for Mongoose
|
|
defaultValue: [{}],
|
|
fields: [defaultValueField],
|
|
},
|
|
{
|
|
name: 'group',
|
|
type: 'group',
|
|
// we need to have to use as default in order to have subfield defaultValue properties directly for Mongoose
|
|
defaultValue: {},
|
|
fields: [defaultValueField],
|
|
},
|
|
{
|
|
name: 'select',
|
|
type: 'select',
|
|
defaultValue: 'default',
|
|
options: [
|
|
{ value: 'option0', label: 'Option 0' },
|
|
{ value: 'option1', label: 'Option 1' },
|
|
{ value: 'default', label: 'Default' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
slug: 'relation-a',
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'richText',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
labels: {
|
|
plural: 'Relation As',
|
|
singular: 'Relation A',
|
|
},
|
|
},
|
|
{
|
|
slug: 'relation-b',
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'relationship',
|
|
type: 'relationship',
|
|
relationTo: 'relation-a',
|
|
},
|
|
{
|
|
name: 'richText',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
labels: {
|
|
plural: 'Relation Bs',
|
|
singular: 'Relation B',
|
|
},
|
|
},
|
|
{
|
|
slug: 'pg-migrations',
|
|
fields: [
|
|
{
|
|
name: 'relation1',
|
|
type: 'relationship',
|
|
relationTo: 'relation-a',
|
|
},
|
|
{
|
|
name: 'myArray',
|
|
type: 'array',
|
|
fields: [
|
|
{
|
|
name: 'relation2',
|
|
type: 'relationship',
|
|
relationTo: 'relation-b',
|
|
},
|
|
{
|
|
name: 'mySubArray',
|
|
type: 'array',
|
|
fields: [
|
|
{
|
|
name: 'relation3',
|
|
type: 'relationship',
|
|
localized: true,
|
|
relationTo: 'relation-b',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'myGroup',
|
|
type: 'group',
|
|
fields: [
|
|
{
|
|
name: 'relation4',
|
|
type: 'relationship',
|
|
localized: true,
|
|
relationTo: 'relation-b',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'myBlocks',
|
|
type: 'blocks',
|
|
blocks: [
|
|
{
|
|
slug: 'myBlock',
|
|
fields: [
|
|
{
|
|
name: 'relation5',
|
|
type: 'relationship',
|
|
relationTo: 'relation-a',
|
|
},
|
|
{
|
|
name: 'relation6',
|
|
type: 'relationship',
|
|
localized: true,
|
|
relationTo: 'relation-b',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
versions: true,
|
|
},
|
|
{
|
|
slug: 'custom-schema',
|
|
dbName: 'customs',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'localizedText',
|
|
type: 'text',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'relationship',
|
|
type: 'relationship',
|
|
hasMany: true,
|
|
relationTo: 'relation-a',
|
|
},
|
|
{
|
|
name: 'select',
|
|
type: 'select',
|
|
dbName: ({ tableName }) => `${tableName}_customSelect`,
|
|
enumName: 'selectEnum',
|
|
hasMany: true,
|
|
options: ['a', 'b', 'c'],
|
|
},
|
|
{
|
|
name: 'radio',
|
|
type: 'select',
|
|
enumName: 'radioEnum',
|
|
options: ['a', 'b', 'c'],
|
|
},
|
|
{
|
|
name: 'array',
|
|
type: 'array',
|
|
dbName: 'customArrays',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'localizedText',
|
|
type: 'text',
|
|
localized: true,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'blocks',
|
|
type: 'blocks',
|
|
blocks: [
|
|
{
|
|
slug: 'block',
|
|
dbName: 'customBlocks',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'localizedText',
|
|
type: 'text',
|
|
localized: true,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
versions: {
|
|
drafts: true,
|
|
},
|
|
},
|
|
],
|
|
globals: [
|
|
{
|
|
slug: 'global',
|
|
dbName: 'customGlobal',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
],
|
|
versions: true,
|
|
},
|
|
],
|
|
localization: {
|
|
defaultLocale: 'en',
|
|
locales: ['en', 'es'],
|
|
},
|
|
onInit: async (payload) => {
|
|
await payload.create({
|
|
collection: 'users',
|
|
data: {
|
|
email: devUser.email,
|
|
password: devUser.password,
|
|
},
|
|
})
|
|
},
|
|
typescript: {
|
|
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
|
},
|
|
})
|
|
|
|
export const postDoc = {
|
|
title: 'test post',
|
|
}
|