fix: add missed pagination property to findVersions and findGlobalVersions and handle it properly (#13763)

* The `pagination` property was missing in `findVersions` and
`findGlobalVersions` Local API operations, although the actual functions
did have it -
1b93c4becc/packages/payload/src/collections/operations/findVersions.ts (L25)
* The handling of the `pagination` property in those functions was
broken, this PR fixes it.
This commit is contained in:
Sasha
2025-09-17 00:05:54 +03:00
committed by GitHub
parent 731c4fb700
commit a9553925f6
9 changed files with 179 additions and 5 deletions

View File

@@ -97,11 +97,15 @@ export const findVersionsOperation = async <TData extends TypeWithVersion<TData>
// Find // Find
// ///////////////////////////////////// // /////////////////////////////////////
const usePagination = pagination && limit !== 0
const sanitizedLimit = limit ?? (usePagination ? 10 : 0)
const sanitizedPage = page || 1
const paginatedDocs = await payload.db.findVersions<TData>({ const paginatedDocs = await payload.db.findVersions<TData>({
collection: collectionConfig.slug, collection: collectionConfig.slug,
limit: limit ?? 10, limit: sanitizedLimit,
locale: locale!, locale: locale!,
page: page || 1, page: sanitizedPage,
pagination, pagination,
req, req,
select, select,

View File

@@ -61,6 +61,11 @@ export type Options<TSlug extends CollectionSlug> = {
* @default 1 * @default 1
*/ */
page?: number page?: number
/**
* Set to `false` to return all documents and avoid querying for document counts which introduces some overhead.
* You can also combine that property with a specified `limit` to limit documents but avoid the count query.
*/
pagination?: boolean
/** /**
* Specify [populate](https://payloadcms.com/docs/queries/select#populate) to control which fields to include to the result from populated documents. * Specify [populate](https://payloadcms.com/docs/queries/select#populate) to control which fields to include to the result from populated documents.
*/ */
@@ -114,6 +119,7 @@ export async function findVersionsLocal<TSlug extends CollectionSlug>(
limit, limit,
overrideAccess = true, overrideAccess = true,
page, page,
pagination = true,
populate, populate,
select, select,
showHiddenFields, showHiddenFields,
@@ -136,6 +142,7 @@ export async function findVersionsLocal<TSlug extends CollectionSlug>(
limit, limit,
overrideAccess, overrideAccess,
page, page,
pagination,
populate, populate,
req: await createLocalReq(options as CreateLocalReqOptions, payload), req: await createLocalReq(options as CreateLocalReqOptions, payload),
select, select,

View File

@@ -79,11 +79,15 @@ export const findVersionsOperation = async <T extends TypeWithVersion<T>>(
// Find // Find
// ///////////////////////////////////// // /////////////////////////////////////
const usePagination = pagination && limit !== 0
const sanitizedLimit = limit ?? (usePagination ? 10 : 0)
const sanitizedPage = page || 1
const paginatedDocs = await payload.db.findGlobalVersions<T>({ const paginatedDocs = await payload.db.findGlobalVersions<T>({
global: globalConfig.slug, global: globalConfig.slug,
limit: limit ?? 10, limit: sanitizedLimit,
locale: locale!, locale: locale!,
page: page || 1, page: sanitizedPage,
pagination, pagination,
req, req,
select, select,

View File

@@ -53,6 +53,11 @@ export type Options<TSlug extends GlobalSlug> = {
* @default 1 * @default 1
*/ */
page?: number page?: number
/**
* Set to `false` to return all documents and avoid querying for document counts which introduces some overhead.
* You can also combine that property with a specified `limit` to limit documents but avoid the count query.
*/
pagination?: boolean
/** /**
* Specify [populate](https://payloadcms.com/docs/queries/select#populate) to control which fields to include to the result from populated documents. * Specify [populate](https://payloadcms.com/docs/queries/select#populate) to control which fields to include to the result from populated documents.
*/ */
@@ -101,6 +106,7 @@ export async function findGlobalVersionsLocal<TSlug extends GlobalSlug>(
limit, limit,
overrideAccess = true, overrideAccess = true,
page, page,
pagination = true,
populate, populate,
select, select,
showHiddenFields, showHiddenFields,
@@ -120,6 +126,7 @@ export async function findGlobalVersionsLocal<TSlug extends GlobalSlug>(
limit, limit,
overrideAccess, overrideAccess,
page, page,
pagination,
populate, populate,
req: await createLocalReq(options as CreateLocalReqOptions, payload), req: await createLocalReq(options as CreateLocalReqOptions, payload),
select, select,

View File

@@ -25,6 +25,7 @@ import AutosaveGlobal from './globals/Autosave.js'
import AutosaveWithDraftButtonGlobal from './globals/AutosaveWithDraftButton.js' import AutosaveWithDraftButtonGlobal from './globals/AutosaveWithDraftButton.js'
import DisablePublishGlobal from './globals/DisablePublish.js' import DisablePublishGlobal from './globals/DisablePublish.js'
import DraftGlobal from './globals/Draft.js' import DraftGlobal from './globals/Draft.js'
import DraftUnlimitedGlobal from './globals/DraftUnlimited.js'
import DraftWithMaxGlobal from './globals/DraftWithMax.js' import DraftWithMaxGlobal from './globals/DraftWithMax.js'
import LocalizedGlobal from './globals/LocalizedGlobal.js' import LocalizedGlobal from './globals/LocalizedGlobal.js'
import { MaxVersions } from './globals/MaxVersions.js' import { MaxVersions } from './globals/MaxVersions.js'
@@ -66,6 +67,7 @@ export default buildConfigWithDefaults({
DisablePublishGlobal, DisablePublishGlobal,
LocalizedGlobal, LocalizedGlobal,
MaxVersions, MaxVersions,
DraftUnlimitedGlobal,
], ],
indexSortableFields: true, indexSortableFields: true,
localization: { localization: {

View File

@@ -0,0 +1,61 @@
import type { GlobalConfig } from 'payload'
import { draftUnlimitedGlobalSlug } from '../slugs.js'
const DraftUnlimitedGlobal: GlobalConfig = {
slug: draftUnlimitedGlobalSlug,
label: 'Draft Unlimited Global',
admin: {
preview: () => 'https://payloadcms.com',
components: {
views: {
edit: {
version: {
actions: ['/elements/GlobalVersionButton/index.js'],
},
versions: {
actions: ['/elements/GlobalVersionsButton/index.js'],
},
},
},
},
},
versions: {
max: 0,
drafts: {
schedulePublish: true,
},
},
access: {
read: ({ req: { user } }) => {
if (user) {
return true
}
return {
or: [
{
_status: {
equals: 'published',
},
},
{
_status: {
exists: false,
},
},
],
}
},
},
fields: [
{
name: 'title',
type: 'text',
required: true,
localized: true,
},
],
}
export default DraftUnlimitedGlobal

View File

@@ -573,6 +573,44 @@ describe('Versions', () => {
expect(restoredVersion.title).toStrictEqual('v1') expect(restoredVersion.title).toStrictEqual('v1')
}) })
it('findVersions - pagination should work correctly', async () => {
const post = await payload.create({
collection: 'draft-posts',
data: { description: 'a', title: 'title' },
})
for (let i = 0; i < 100; i++) {
await payload.update({ collection: 'draft-posts', id: post.id, data: {} })
}
const res = await payload.findVersions({
collection: 'draft-posts',
where: { parent: { equals: post.id } },
})
expect(res.totalDocs).toBe(101)
expect(res.docs).toHaveLength(10)
const resPaginationFalse = await payload.findVersions({
collection: 'draft-posts',
where: { parent: { equals: post.id } },
pagination: false,
})
const resPaginationFalse2 = await payload.find({
collection: 'draft-posts',
// where: { parent: { equals: post.id } },
pagination: false,
})
expect(resPaginationFalse.docs).toHaveLength(101)
expect(resPaginationFalse.totalDocs).toBe(101)
const resPaginationFalseLimit0 = await payload.findVersions({
collection: 'draft-posts',
where: { parent: { equals: post.id } },
pagination: false,
limit: 0,
})
expect(resPaginationFalseLimit0.docs).toHaveLength(101)
expect(resPaginationFalseLimit0.totalDocs).toBe(101)
})
describe('Update', () => { describe('Update', () => {
it('should allow a draft to be patched', async () => { it('should allow a draft to be patched', async () => {
const originalTitle = 'Here is a published post' const originalTitle = 'Here is a published post'
@@ -1802,6 +1840,31 @@ describe('Versions', () => {
expect(version_1_deleted).toBeFalsy() expect(version_1_deleted).toBeFalsy()
}) })
it('findGlobalVersions - pagination should work correctly', async () => {
for (let i = 0; i < 100; i++) {
await payload.updateGlobal({ slug: 'draft-unlimited-global', data: { title: 'title' } })
}
const res = await payload.findGlobalVersions({
slug: 'draft-unlimited-global',
})
expect(res.totalDocs).toBe(100)
expect(res.docs).toHaveLength(10)
const resPaginationFalse = await payload.findGlobalVersions({
slug: 'draft-unlimited-global',
pagination: false,
})
expect(resPaginationFalse.docs).toHaveLength(100)
expect(resPaginationFalse.totalDocs).toBe(100)
const resPaginationFalseLimit0 = await payload.findGlobalVersions({
slug: 'draft-unlimited-global',
pagination: false,
limit: 0,
})
expect(resPaginationFalseLimit0.docs).toHaveLength(100)
expect(resPaginationFalseLimit0.totalDocs).toBe(100)
})
describe('Read', () => { describe('Read', () => {
it('should allow a version to be retrieved by ID', async () => { it('should allow a version to be retrieved by ID', async () => {
const version = await payload.findGlobalVersionByID({ const version = await payload.findGlobalVersionByID({

View File

@@ -128,6 +128,7 @@ export interface Config {
'disable-publish-global': DisablePublishGlobal; 'disable-publish-global': DisablePublishGlobal;
'localized-global': LocalizedGlobal; 'localized-global': LocalizedGlobal;
'max-versions': MaxVersion; 'max-versions': MaxVersion;
'draft-unlimited-global': DraftUnlimitedGlobal;
}; };
globalsSelect: { globalsSelect: {
'autosave-global': AutosaveGlobalSelect<false> | AutosaveGlobalSelect<true>; 'autosave-global': AutosaveGlobalSelect<false> | AutosaveGlobalSelect<true>;
@@ -137,6 +138,7 @@ export interface Config {
'disable-publish-global': DisablePublishGlobalSelect<false> | DisablePublishGlobalSelect<true>; 'disable-publish-global': DisablePublishGlobalSelect<false> | DisablePublishGlobalSelect<true>;
'localized-global': LocalizedGlobalSelect<false> | LocalizedGlobalSelect<true>; 'localized-global': LocalizedGlobalSelect<false> | LocalizedGlobalSelect<true>;
'max-versions': MaxVersionsSelect<false> | MaxVersionsSelect<true>; 'max-versions': MaxVersionsSelect<false> | MaxVersionsSelect<true>;
'draft-unlimited-global': DraftUnlimitedGlobalSelect<false> | DraftUnlimitedGlobalSelect<true>;
}; };
locale: 'en' | 'es' | 'de'; locale: 'en' | 'es' | 'de';
user: User & { user: User & {
@@ -1348,6 +1350,17 @@ export interface MaxVersion {
updatedAt?: string | null; updatedAt?: string | null;
createdAt?: string | null; createdAt?: string | null;
} }
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "draft-unlimited-global".
*/
export interface DraftUnlimitedGlobal {
id: string;
title: string;
_status?: ('draft' | 'published') | null;
updatedAt?: string | null;
createdAt?: string | null;
}
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "autosave-global_select". * via the `definition` "autosave-global_select".
@@ -1426,6 +1439,17 @@ export interface MaxVersionsSelect<T extends boolean = true> {
createdAt?: T; createdAt?: T;
globalType?: T; globalType?: T;
} }
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "draft-unlimited-global_select".
*/
export interface DraftUnlimitedGlobalSelect<T extends boolean = true> {
title?: T;
_status?: T;
updatedAt?: T;
createdAt?: T;
globalType?: T;
}
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "TaskSchedulePublish". * via the `definition` "TaskSchedulePublish".
@@ -1447,7 +1471,7 @@ export interface TaskSchedulePublish {
relationTo: 'draft-posts-with-change-hook'; relationTo: 'draft-posts-with-change-hook';
value: string | DraftPostsWithChangeHook; value: string | DraftPostsWithChangeHook;
} | null); } | null);
global?: 'draft-global' | null; global?: ('draft-global' | 'draft-unlimited-global') | null;
user?: (string | null) | User; user?: (string | null) | User;
}; };
output?: unknown; output?: unknown;

View File

@@ -48,6 +48,8 @@ export const autosaveWithDraftButtonGlobal = 'autosave-with-draft-button-global'
export const draftGlobalSlug = 'draft-global' export const draftGlobalSlug = 'draft-global'
export const draftUnlimitedGlobalSlug = 'draft-unlimited-global'
export const draftWithMaxGlobalSlug = 'draft-with-max-global' export const draftWithMaxGlobalSlug = 'draft-with-max-global'
export const globalSlugs = [autoSaveGlobalSlug, draftGlobalSlug] export const globalSlugs = [autoSaveGlobalSlug, draftGlobalSlug]