From ddb8ca4de2e8f877a0ba8fe142feb20d7e2936de Mon Sep 17 00:00:00 2001 From: Yunsup Sim Date: Fri, 22 Aug 2025 17:39:21 +0900 Subject: [PATCH] fix(db-*): add delete version id for non-mongodb (#10613) Fixes #10526 ### What? `updateVersion` throws error at deleting before version of draft. ### Why? When triggers `db.updateVersion` with non-mongodb environment, `saveVersion` in `payload/src/versions/saveVersions.ts` doesn't remove `id` in `versionData`. ### How? Add `delete versionData.id` for non-mongodb environments. --------- Co-authored-by: German Jablonski <43938777+GermanJablo@users.noreply.github.com> --- .../collections/AutosaveWithMultiSelect.ts | 32 +++++++++ test/versions/config.ts | 2 + test/versions/int.spec.ts | 68 ++++++++++++++++++- test/versions/payload-types.ts | 29 ++++++++ test/versions/slugs.ts | 2 + 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 test/versions/collections/AutosaveWithMultiSelect.ts diff --git a/test/versions/collections/AutosaveWithMultiSelect.ts b/test/versions/collections/AutosaveWithMultiSelect.ts new file mode 100644 index 000000000..7245397d6 --- /dev/null +++ b/test/versions/collections/AutosaveWithMultiSelect.ts @@ -0,0 +1,32 @@ +import type { CollectionConfig } from 'payload' + +import { autosaveWithMultiSelectCollectionSlug } from '../slugs.js' + +const AutosaveWithMultiSelectPosts: CollectionConfig = { + slug: autosaveWithMultiSelectCollectionSlug, + versions: { + drafts: { + autosave: { + interval: 2000, + }, + }, + }, + fields: [ + { + name: 'title', + label: 'Title', + type: 'text', + required: true, + unique: true, + localized: true, + }, + { + name: 'tag', + type: 'select', + options: ['blog', 'essay', 'portfolio'], + hasMany: true, + }, + ], +} + +export default AutosaveWithMultiSelectPosts diff --git a/test/versions/config.ts b/test/versions/config.ts index daa998f57..bf568f893 100644 --- a/test/versions/config.ts +++ b/test/versions/config.ts @@ -6,6 +6,7 @@ import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' import AutosavePosts from './collections/Autosave.js' import AutosaveWithDraftButtonPosts from './collections/AutosaveWithDraftButton.js' import AutosaveWithDraftValidate from './collections/AutosaveWithDraftValidate.js' +import AutosaveWithMultiSelectPosts from './collections/AutosaveWithMultiSelect.js' import CustomIDs from './collections/CustomIDs.js' import { Diff } from './collections/Diff/index.js' import DisablePublish from './collections/DisablePublish.js' @@ -41,6 +42,7 @@ export default buildConfigWithDefaults({ Posts, AutosavePosts, AutosaveWithDraftButtonPosts, + AutosaveWithMultiSelectPosts, AutosaveWithDraftValidate, DraftPosts, DraftWithMax, diff --git a/test/versions/int.spec.ts b/test/versions/int.spec.ts index b45959f3c..561cef0f7 100644 --- a/test/versions/int.spec.ts +++ b/test/versions/int.spec.ts @@ -8,7 +8,7 @@ import * as qs from 'qs-esm' import { fileURLToPath } from 'url' import type { NextRESTClient } from '../helpers/NextRESTClient.js' -import type { DraftPost } from './payload-types.js' +import type { AutosaveMultiSelectPost } from './payload-types.js' import { devUser } from '../credentials.js' import { initPayloadInt } from '../helpers/initPayloadInt.js' @@ -18,6 +18,7 @@ import AutosaveGlobal from './globals/Autosave.js' import { autosaveCollectionSlug, autoSaveGlobalSlug, + autosaveWithMultiSelectCollectionSlug, draftCollectionSlug, draftGlobalSlug, localizedCollectionSlug, @@ -654,6 +655,71 @@ describe('Versions', () => { expect(Number(updatedUpdatedAt)).toBeGreaterThan(Number(createdUpdatedAt)) }) + it('should update correct version at doc that has hasMany field when saving with autosave', async () => { + const firstDocTag: AutosaveMultiSelectPost['tag'] = ['blog', 'essay'] + const doc = await payload.create({ + collection: autosaveWithMultiSelectCollectionSlug, + data: { + title: 'title 1', + tag: firstDocTag, + _status: 'published', + }, + draft: false, + }) + await payload.update({ + collection: autosaveWithMultiSelectCollectionSlug, + id: doc.id, + data: { + title: 'title 2', + tag: firstDocTag, + }, + draft: true, + autosave: true, + }) + + const doc2 = await payload.create({ + collection: autosaveWithMultiSelectCollectionSlug, + data: { + title: 'title 1-2', + tag: ['blog'], + _status: 'published', + }, + draft: false, + }) + + await payload.update({ + collection: autosaveWithMultiSelectCollectionSlug, + id: doc2.id, + data: { + tag: ['blog'], + title: 'title 2-2', + }, + draft: true, + autosave: true, + }) + await payload.update({ + collection: autosaveWithMultiSelectCollectionSlug, + id: doc2.id, + data: { + tag: ['blog'], + title: 'title 3-2', + }, + draft: true, + autosave: true, + }) + + const lastDocVersion = await payload.findVersions({ + collection: autosaveWithMultiSelectCollectionSlug, + where: { + parent: { + equals: doc.id, + }, + }, + limit: 1, + }) + expect(lastDocVersion.docs[0]?.version.tag).toEqual(firstDocTag) + }) + it('should validate when publishing with the draft arg', async () => { // no title (not valid for publishing) const doc = await payload.create({ diff --git a/test/versions/payload-types.ts b/test/versions/payload-types.ts index 8f5cc917a..de12c3986 100644 --- a/test/versions/payload-types.ts +++ b/test/versions/payload-types.ts @@ -72,6 +72,7 @@ export interface Config { 'autosave-posts': AutosavePost; 'autosave-with-draft-button-posts': AutosaveWithDraftButtonPost; 'autosave-with-validate-posts': AutosaveWithValidatePost; + 'autosave-multi-select-posts': AutosaveMultiSelectPost; 'draft-posts': DraftPost; 'draft-with-max-posts': DraftWithMaxPost; 'draft-with-validate-posts': DraftWithValidatePost; @@ -96,6 +97,7 @@ export interface Config { 'autosave-posts': AutosavePostsSelect | AutosavePostsSelect; 'autosave-with-draft-button-posts': AutosaveWithDraftButtonPostsSelect | AutosaveWithDraftButtonPostsSelect; 'autosave-with-validate-posts': AutosaveWithValidatePostsSelect | AutosaveWithValidatePostsSelect; + 'autosave-multi-select-posts': AutosaveMultiSelectPostsSelect | AutosaveMultiSelectPostsSelect; 'draft-posts': DraftPostsSelect | DraftPostsSelect; 'draft-with-max-posts': DraftWithMaxPostsSelect | DraftWithMaxPostsSelect; 'draft-with-validate-posts': DraftWithValidatePostsSelect | DraftWithValidatePostsSelect; @@ -291,6 +293,18 @@ export interface AutosaveWithValidatePost { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "autosave-multi-select-posts". + */ +export interface AutosaveMultiSelectPost { + id: string; + title: string; + tag?: ('blog' | 'essay' | 'portfolio')[] | null; + updatedAt: string; + createdAt: string; + _status?: ('draft' | 'published') | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "draft-with-max-posts". @@ -695,6 +709,10 @@ export interface PayloadLockedDocument { relationTo: 'autosave-with-validate-posts'; value: string | AutosaveWithValidatePost; } | null) + | ({ + relationTo: 'autosave-multi-select-posts'; + value: string | AutosaveMultiSelectPost; + } | null) | ({ relationTo: 'draft-posts'; value: string | DraftPost; @@ -850,6 +868,17 @@ export interface AutosaveWithValidatePostsSelect { createdAt?: T; _status?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "autosave-multi-select-posts_select". + */ +export interface AutosaveMultiSelectPostsSelect { + title?: T; + tag?: T; + updatedAt?: T; + createdAt?: T; + _status?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "draft-posts_select". diff --git a/test/versions/slugs.ts b/test/versions/slugs.ts index d460444a9..4f6fc3628 100644 --- a/test/versions/slugs.ts +++ b/test/versions/slugs.ts @@ -1,4 +1,5 @@ export const autosaveCollectionSlug = 'autosave-posts' +export const autosaveWithMultiSelectCollectionSlug = 'autosave-multi-select-posts' export const autosaveWithDraftButtonSlug = 'autosave-with-draft-button-posts' @@ -28,6 +29,7 @@ export const textCollectionSlug = 'text' export const collectionSlugs = [ autosaveCollectionSlug, + autosaveWithMultiSelectCollectionSlug, draftCollectionSlug, postCollectionSlug, diffCollectionSlug,