fix(db-postgres): drafts cannot be saved because not null constraint (#3547)

This commit is contained in:
Dan Ribbens
2023-10-11 10:18:44 -04:00
committed by GitHub
parent 4dd4e9aaae
commit aabc0650f8
4 changed files with 113 additions and 77 deletions

View File

@@ -24,6 +24,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
buildTable({
adapter: this,
buildRelationships: true,
disableNotNull: !!collection?.versions?.drafts,
disableUnique: false,
fields: collection.fields,
tableName,
@@ -37,6 +38,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
buildTable({
adapter: this,
buildRelationships: true,
disableNotNull: !!collection.versions?.drafts,
disableUnique: true,
fields: versionFields,
tableName: versionsTableName,
@@ -51,6 +53,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
buildTable({
adapter: this,
buildRelationships: true,
disableNotNull: !!global?.versions?.drafts,
disableUnique: false,
fields: global.fields,
tableName,
@@ -64,6 +67,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
buildTable({
adapter: this,
buildRelationships: true,
disableNotNull: !!global.versions?.drafts,
disableUnique: true,
fields: versionFields,
tableName: versionsTableName,

View File

@@ -27,6 +27,7 @@ type Args = {
baseColumns?: Record<string, PgColumnBuilder>
baseExtraConfig?: Record<string, (cols: GenericColumns) => IndexBuilder | UniqueConstraintBuilder>
buildRelationships?: boolean
disableNotNull: boolean
disableUnique: boolean
fields: Field[]
rootRelationsToBuild?: Map<string, string>
@@ -46,6 +47,7 @@ export const buildTable = ({
baseColumns = {},
baseExtraConfig = {},
buildRelationships,
disableNotNull,
disableUnique = false,
fields,
rootRelationsToBuild,
@@ -102,6 +104,7 @@ export const buildTable = ({
adapter,
buildRelationships,
columns,
disableNotNull,
disableUnique,
fields,
indexes,

View File

@@ -34,6 +34,7 @@ type Args = {
buildRelationships: boolean
columnPrefix?: string
columns: Record<string, PgColumnBuilder>
disableNotNull: boolean
disableUnique?: boolean
fieldPrefix?: string
fields: (Field | TabAsField)[]
@@ -62,6 +63,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix,
columns,
disableNotNull,
disableUnique = false,
fieldPrefix,
fields,
@@ -218,6 +220,7 @@ export const traverseFields = ({
adapter,
baseColumns,
baseExtraConfig,
disableNotNull,
disableUnique,
fields: [],
tableName: selectTableName,
@@ -274,6 +277,7 @@ export const traverseFields = ({
adapter,
baseColumns,
baseExtraConfig,
disableNotNull,
disableUnique,
fields: field.fields,
rootRelationsToBuild,
@@ -339,6 +343,7 @@ export const traverseFields = ({
adapter,
baseColumns,
baseExtraConfig,
disableNotNull,
disableUnique,
fields: block.fields,
rootRelationsToBuild,
@@ -399,6 +404,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix,
columns,
disableNotNull,
disableUnique,
fieldPrefix,
fields: field.fields,
@@ -432,6 +438,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix: `${columnName}_`,
columns,
disableNotNull,
disableUnique,
fieldPrefix: `${fieldName}_`,
fields: field.fields,
@@ -466,6 +473,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix,
columns,
disableNotNull,
disableUnique,
fieldPrefix,
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
@@ -502,6 +510,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix,
columns,
disableNotNull,
disableUnique,
fieldPrefix,
fields: field.fields,
@@ -544,7 +553,13 @@ export const traverseFields = ({
const condition = field.admin && field.admin.condition
if (targetTable[fieldName] && 'required' in field && field.required && !condition) {
if (
!disableNotNull &&
targetTable[fieldName] &&
'required' in field &&
field.required &&
!condition
) {
targetTable[fieldName].notNull()
}
})

View File

@@ -6,6 +6,7 @@ import { initPayloadTest } from '../helpers/configHelpers'
import AutosavePosts from './collections/Autosave'
import configPromise from './config'
import AutosaveGlobal from './globals/Autosave'
import { autosaveSlug } from './shared'
let collectionLocalPostID: string
let collectionLocalVersionID
@@ -56,8 +57,8 @@ describe('Versions', () => {
// First: delete potential existing versions from previous tests
if (collectionLocalPostID) {
await payload.delete({
collection,
id: collectionLocalPostID,
collection,
})
}
@@ -65,8 +66,8 @@ describe('Versions', () => {
const autosavePost = await payload.create({
collection,
data: {
title: 'Here is an autosave post in EN',
description: '345j23o4ifj34jf54g',
title: 'Here is an autosave post in EN',
},
})
collectionLocalPostID = autosavePost.id
@@ -91,10 +92,23 @@ describe('Versions', () => {
describe('Collections - Local', () => {
describe('Create', () => {
it('should allow creating a draft with missing required field data', async () => {
const draft = await payload.create({
collection: autosaveSlug,
data: {
description: undefined,
title: 'i have a title',
},
draft: true,
})
expect(draft.id).toBeDefined()
})
it('should allow a new version to be created and updated', async () => {
const updatedPost = await payload.findByID({
collection,
id: collectionLocalPostID,
collection,
})
expect(updatedPost.title).toBe(updatedTitle)
expect(updatedPost._status).toStrictEqual('draft')
@@ -105,8 +119,8 @@ describe('Versions', () => {
const autosavePost = await payload.create({
collection,
data: {
title: 'unique unchanging title',
description: 'description 1',
title: 'unique unchanging title',
},
})
@@ -133,8 +147,8 @@ describe('Versions', () => {
it('should allow a version to be retrieved by ID', async () => {
const version = await payload.findVersionByID({
collection,
id: collectionLocalVersionID,
collection,
})
expect(version.id).toStrictEqual(collectionLocalVersionID)
@@ -145,20 +159,20 @@ describe('Versions', () => {
const spanishTitle = 'Title in ES'
await payload.update({
collection,
id: collectionLocalPostID,
collection,
data: {
title: englishTitle,
},
})
const updatedPostES = await payload.update({
collection,
id: collectionLocalPostID,
locale: 'es',
collection,
data: {
title: spanishTitle,
},
locale: 'es',
})
expect(updatedPostES.title).toBe(spanishTitle)
@@ -166,8 +180,8 @@ describe('Versions', () => {
const newEnglishTitle = 'New title in EN'
await payload.update({
collection,
id: collectionLocalPostID,
collection,
data: {
title: newEnglishTitle,
},
@@ -193,14 +207,14 @@ describe('Versions', () => {
const somePost = await payload.create({
collection,
data: {
title: 'first post',
description: 'description 1',
title: 'first post',
},
})
const updatedPost = await payload.update({
collection,
id: collectionLocalPostID,
collection,
data: {
title: 'This should be the latest version',
},
@@ -216,8 +230,8 @@ describe('Versions', () => {
const title2 = 'Another updated post title in EN'
const updatedPost = await payload.update({
collection,
id: collectionLocalPostID,
collection,
data: {
title: title2,
},
@@ -227,8 +241,8 @@ describe('Versions', () => {
// Make sure it was updated correctly
const draftFromUpdatedPost = await payload.findByID({
collection,
id: collectionLocalPostID,
collection,
draft: true,
})
expect(draftFromUpdatedPost.title).toBe(title2)
@@ -239,15 +253,15 @@ describe('Versions', () => {
// restore to latest version
const restoredVersion = await payload.restoreVersion({
collection,
id: versions.docs[1].id,
collection,
})
expect(restoredVersion.title).toBeDefined()
const latestDraft = await payload.findByID({
collection,
id: collectionLocalPostID,
collection,
draft: true,
})
@@ -262,9 +276,9 @@ describe('Versions', () => {
const originalPublishedPost = await payload.create({
collection,
data: {
title: originalTitle,
description: 'kjnjyhbbdsfseankuhsjsfghb',
_status: 'published',
description: 'kjnjyhbbdsfseankuhsjsfghb',
title: originalTitle,
},
})
@@ -273,11 +287,11 @@ describe('Versions', () => {
await payload.update({
id: originalPublishedPost.id,
collection,
locale: 'en',
data: {
title: patchedTitle,
},
draft: true,
locale: 'en',
})
const spanishTitle = 'es title'
@@ -286,23 +300,23 @@ describe('Versions', () => {
await payload.update({
id: originalPublishedPost.id,
collection,
locale: 'es',
data: {
title: spanishTitle,
},
draft: true,
locale: 'es',
})
const publishedPost = await payload.findByID({
collection,
id: originalPublishedPost.id,
collection,
})
const draftPost = await payload.findByID({
collection,
locale: 'all',
id: originalPublishedPost.id,
collection,
draft: true,
locale: 'all',
})
expect(publishedPost.title).toBe(originalTitle)
@@ -315,39 +329,39 @@ describe('Versions', () => {
it('creates proper number of drafts', async () => {
const originalDraft = await payload.create({
collection: 'draft-posts',
draft: true,
data: {
title: 'A',
_status: 'draft',
description: 'A',
_status: 'draft',
title: 'A',
},
draft: true,
})
await payload.update({
collection: 'draft-posts',
id: originalDraft.id,
draft: true,
collection: 'draft-posts',
data: {
title: 'B',
_status: 'draft',
description: 'B',
_status: 'draft',
title: 'B',
},
draft: true,
})
await payload.update({
collection: 'draft-posts',
id: originalDraft.id,
draft: true,
collection: 'draft-posts',
data: {
title: 'C',
description: 'C',
_status: 'draft',
description: 'C',
title: 'C',
},
draft: true,
})
const mostRecentDraft = await payload.findByID({
collection: 'draft-posts',
id: originalDraft.id,
collection: 'draft-posts',
draft: true,
})
@@ -373,52 +387,52 @@ describe('Versions', () => {
const doc1 = await payload.create({
collection: 'version-posts',
data: {
title: 'A',
description: 'A',
title: 'A',
},
})
await payload.update({
collection: 'version-posts',
id: doc1.id,
collection: 'version-posts',
data: {
title: 'B',
description: 'B',
title: 'B',
},
})
await payload.update({
collection: 'version-posts',
id: doc1.id,
collection: 'version-posts',
data: {
title: 'C',
description: 'C',
title: 'C',
},
})
const doc2 = await payload.create({
collection: 'version-posts',
data: {
title: 'D',
description: 'D',
title: 'D',
},
})
await payload.update({
collection: 'version-posts',
id: doc2.id,
collection: 'version-posts',
data: {
title: 'E',
description: 'E',
title: 'E',
},
})
await payload.update({
collection: 'version-posts',
id: doc2.id,
collection: 'version-posts',
data: {
title: 'F',
description: 'F',
title: 'F',
},
})
@@ -473,31 +487,31 @@ describe('Versions', () => {
firstDraft = await payload.create({
collection: 'draft-posts',
data: {
title: originalTitle,
description: 'my description',
radio: 'test',
title: originalTitle,
},
})
// This will be created in the `_draft-posts_versions` collection
await payload.update({
collection: 'draft-posts',
id: firstDraft.id,
draft: true,
collection: 'draft-posts',
data: {
title: updatedTitle1,
},
draft: true,
})
// This will be created in the `_draft-posts_versions` collection
// and will be the newest draft, able to be queried on
await payload.update({
collection: 'draft-posts',
id: firstDraft.id,
draft: true,
collection: 'draft-posts',
data: {
title: updatedTitle2,
},
draft: true,
})
})
@@ -583,8 +597,8 @@ describe('Versions', () => {
// First: delete potential existing versions from previous tests
if (collectionGraphQLPostID) {
await payload.delete({
collection,
id: collectionGraphQLPostID,
collection,
})
}
@@ -780,17 +794,17 @@ describe('Versions', () => {
beforeEach(async () => {
const title2 = 'Here is an updated global title in EN'
await payload.updateGlobal({
slug: globalSlug,
data: {
title: 'Test Global',
},
slug: globalSlug,
})
const updatedGlobal = await payload.updateGlobal({
slug: globalSlug,
data: {
title: title2,
},
slug: globalSlug,
})
const versions = await payload.findGlobalVersions({
@@ -814,8 +828,8 @@ describe('Versions', () => {
describe('Read', () => {
it('should allow a version to be retrieved by ID', async () => {
const version = await payload.findGlobalVersionByID({
slug: globalSlug,
id: globalLocalVersionID,
slug: globalSlug,
})
expect(version.id).toStrictEqual(globalLocalVersionID)
@@ -828,18 +842,18 @@ describe('Versions', () => {
const spanishTitle = 'Title in ES'
await payload.updateGlobal({
slug: globalSlug,
data: {
title: englishTitle,
},
slug: globalSlug,
})
const updatedGlobalES = await payload.updateGlobal({
slug: globalSlug,
locale: 'es',
data: {
title: spanishTitle,
},
locale: 'es',
slug: globalSlug,
})
expect(updatedGlobalES.title).toBe(spanishTitle)
@@ -847,15 +861,15 @@ describe('Versions', () => {
const newEnglishTitle = 'New title in EN'
await payload.updateGlobal({
slug: globalSlug,
data: {
title: newEnglishTitle,
},
slug: globalSlug,
})
const versions = await payload.findGlobalVersions({
slug: globalSlug,
locale: 'all',
slug: globalSlug,
})
expect(versions.docs[0].version.title.en).toStrictEqual(newEnglishTitle)
@@ -868,18 +882,18 @@ describe('Versions', () => {
const title2 = 'Another updated title in EN'
const updatedGlobal = await payload.updateGlobal({
slug: globalSlug,
data: {
title: title2,
},
slug: globalSlug,
})
expect(updatedGlobal.title).toBe(title2)
// Make sure it was updated correctly
const foundUpdatedGlobal = await payload.findGlobal({
slug: globalSlug,
draft: true,
slug: globalSlug,
})
expect(foundUpdatedGlobal.title).toBe(title2)
@@ -890,15 +904,15 @@ describe('Versions', () => {
globalLocalVersionID = versions.docs[1].id
const restore = await payload.restoreGlobalVersion({
slug: globalSlug,
id: globalLocalVersionID,
slug: globalSlug,
})
expect(restore.title).toBeDefined()
const restoredGlobal = await payload.findGlobal({
slug: globalSlug,
draft: true,
slug: globalSlug,
})
expect(restoredGlobal.title).toBe(restore.title)
@@ -910,43 +924,43 @@ describe('Versions', () => {
const originalTitle = 'Here is a published global'
await payload.updateGlobal({
slug: globalSlug,
data: {
title: originalTitle,
description: 'kjnjyhbbdsfseankuhsjsfghb',
_status: 'published',
description: 'kjnjyhbbdsfseankuhsjsfghb',
title: originalTitle,
},
slug: globalSlug,
})
const publishedGlobal = await payload.findGlobal({
slug: globalSlug,
draft: true,
slug: globalSlug,
})
const updatedTitle2 = 'Here is a draft global with a patched title'
await payload.updateGlobal({
slug: globalSlug,
locale: 'en',
data: {
title: updatedTitle2,
},
draft: true,
locale: 'en',
slug: globalSlug,
})
await payload.updateGlobal({
slug: globalSlug,
locale: 'es',
data: {
title: updatedTitle2,
},
draft: true,
locale: 'es',
slug: globalSlug,
})
const updatedGlobal = await payload.findGlobal({
slug: globalSlug,
locale: 'all',
draft: true,
locale: 'all',
slug: globalSlug,
})
expect(publishedGlobal.title).toBe(originalTitle)
@@ -958,22 +972,22 @@ describe('Versions', () => {
const originalTitle = 'Here is a draft'
await payload.updateGlobal({
slug: globalSlug,
data: {
title: originalTitle,
_status: 'draft',
title: originalTitle,
},
draft: true,
slug: globalSlug,
})
const updatedTitle2 = 'Now try to publish'
const result = await payload.updateGlobal({
slug: globalSlug,
data: {
title: updatedTitle2,
_status: 'published',
title: updatedTitle2,
},
slug: globalSlug,
})
expect(result.title).toBe(updatedTitle2)