Skip to content

Commit 890846c

Browse files
committed
Merge branch 'main' into fix/db-postgres-numbers-texts-trigger-delete
2 parents 56a1888 + 4081953 commit 890846c

File tree

51 files changed

+347
-75
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+347
-75
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "payload-monorepo",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"private": true,
55
"type": "module",
66
"scripts": {

packages/admin-bar/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@payloadcms/admin-bar",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"description": "An admin bar for React apps using Payload",
55
"homepage": "https://payloadcms.com",
66
"repository": {

packages/create-payload-app/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-payload-app",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"homepage": "https://payloadcms.com",
55
"repository": {
66
"type": "git",

packages/db-mongodb/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@payloadcms/db-mongodb",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"description": "The officially supported MongoDB database adapter for Payload",
55
"homepage": "https://payloadcms.com",
66
"repository": {

packages/db-mongodb/src/find.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { PaginateOptions } from 'mongoose'
1+
import type { PaginateOptions, PipelineStage } from 'mongoose'
22
import type { Find } from 'payload'
33

44
import { flattenWhereToOperators } from 'payload'
@@ -41,13 +41,17 @@ export const find: Find = async function find(
4141
hasNearConstraint = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near'))
4242
}
4343

44+
const sortAggregation: PipelineStage[] = []
45+
4446
let sort
4547
if (!hasNearConstraint) {
4648
sort = buildSortParam({
49+
adapter: this,
4750
config: this.payload.config,
4851
fields: collectionConfig.flattenedFields,
4952
locale,
5053
sort: sortArg || collectionConfig.defaultSort,
54+
sortAggregation,
5155
timestamps: true,
5256
})
5357
}
@@ -128,8 +132,8 @@ export const find: Find = async function find(
128132
locale,
129133
query,
130134
})
131-
// build join aggregation
132-
if (aggregate) {
135+
136+
if (aggregate || sortAggregation.length > 0) {
133137
result = await aggregatePaginate({
134138
adapter: this,
135139
collation: paginationOptions.collation,
@@ -142,6 +146,7 @@ export const find: Find = async function find(
142146
query,
143147
session: paginationOptions.options?.session ?? undefined,
144148
sort: paginationOptions.sort as object,
149+
sortAggregation,
145150
useEstimatedCount: paginationOptions.useEstimatedCount,
146151
})
147152
} else {

packages/db-mongodb/src/findGlobalVersions.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
4848
let sort
4949
if (!hasNearConstraint) {
5050
sort = buildSortParam({
51+
adapter: this,
5152
config: this.payload.config,
5253
fields: versionFields,
5354
locale,
@@ -103,7 +104,7 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
103104
if (limit && limit >= 0) {
104105
paginationOptions.limit = limit
105106
// limit must also be set here, it's ignored when pagination is false
106-
107+
107108
paginationOptions.options!.limit = limit
108109

109110
// Disable pagination if limit is 0

packages/db-mongodb/src/findVersions.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const findVersions: FindVersions = async function findVersions(
5050
let sort
5151
if (!hasNearConstraint) {
5252
sort = buildSortParam({
53+
adapter: this,
5354
config: this.payload.config,
5455
fields: collectionConfig.flattenedFields,
5556
locale,
@@ -111,7 +112,7 @@ export const findVersions: FindVersions = async function findVersions(
111112
if (limit && limit >= 0) {
112113
paginationOptions.limit = limit
113114
// limit must also be set here, it's ignored when pagination is false
114-
115+
115116
paginationOptions.options!.limit = limit
116117

117118
// Disable pagination if limit is 0

packages/db-mongodb/src/queries/buildSortParam.ts

+131-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
1-
import type { FlattenedField, SanitizedConfig, Sort } from 'payload'
1+
import type { PipelineStage } from 'mongoose'
22

3+
import {
4+
APIError,
5+
type FlattenedField,
6+
getFieldByPath,
7+
type SanitizedConfig,
8+
type Sort,
9+
} from 'payload'
10+
11+
import type { MongooseAdapter } from '../index.js'
12+
13+
import { getCollection } from '../utilities/getEntity.js'
314
import { getLocalizedSortProperty } from './getLocalizedSortProperty.js'
415

516
type Args = {
17+
adapter: MongooseAdapter
618
config: SanitizedConfig
719
fields: FlattenedField[]
820
locale?: string
921
parentIsLocalized?: boolean
1022
sort: Sort
23+
sortAggregation?: PipelineStage[]
1124
timestamps: boolean
25+
versions?: boolean
1226
}
1327

1428
export type SortArgs = {
@@ -18,13 +32,111 @@ export type SortArgs = {
1832

1933
export type SortDirection = 'asc' | 'desc'
2034

35+
const relationshipSort = ({
36+
adapter,
37+
fields,
38+
locale,
39+
path,
40+
sort,
41+
sortAggregation,
42+
sortDirection,
43+
versions,
44+
}: {
45+
adapter: MongooseAdapter
46+
fields: FlattenedField[]
47+
locale?: string
48+
path: string
49+
sort: Record<string, string>
50+
sortAggregation: PipelineStage[]
51+
sortDirection: SortDirection
52+
versions?: boolean
53+
}) => {
54+
let currentFields = fields
55+
const segments = path.split('.')
56+
if (segments.length < 2) {
57+
return false
58+
}
59+
60+
for (const [i, segment] of segments.entries()) {
61+
if (versions && i === 0 && segment === 'version') {
62+
segments.shift()
63+
continue
64+
}
65+
66+
const field = currentFields.find((each) => each.name === segment)
67+
68+
if (!field) {
69+
return false
70+
}
71+
72+
if ('fields' in field) {
73+
currentFields = field.flattenedFields
74+
} else if (
75+
(field.type === 'relationship' || field.type === 'upload') &&
76+
i !== segments.length - 1
77+
) {
78+
const relationshipPath = segments.slice(0, i + 1).join('.')
79+
let sortFieldPath = segments.slice(i + 1, segments.length).join('.')
80+
if (Array.isArray(field.relationTo)) {
81+
throw new APIError('Not supported')
82+
}
83+
84+
const foreignCollection = getCollection({ adapter, collectionSlug: field.relationTo })
85+
86+
const foreignFieldPath = getFieldByPath({
87+
fields: foreignCollection.collectionConfig.flattenedFields,
88+
path: sortFieldPath,
89+
})
90+
91+
if (!foreignFieldPath) {
92+
return false
93+
}
94+
95+
if (foreignFieldPath.pathHasLocalized && locale) {
96+
sortFieldPath = foreignFieldPath.localizedPath.replace('<locale>', locale)
97+
}
98+
99+
if (
100+
!sortAggregation.some((each) => {
101+
return '$lookup' in each && each.$lookup.as === `__${path}`
102+
})
103+
) {
104+
sortAggregation.push({
105+
$lookup: {
106+
as: `__${path}`,
107+
foreignField: '_id',
108+
from: foreignCollection.Model.collection.name,
109+
localField: relationshipPath,
110+
pipeline: [
111+
{
112+
$project: {
113+
[sortFieldPath]: true,
114+
},
115+
},
116+
],
117+
},
118+
})
119+
120+
sort[`__${path}.${sortFieldPath}`] = sortDirection
121+
122+
return true
123+
}
124+
}
125+
}
126+
127+
return false
128+
}
129+
21130
export const buildSortParam = ({
131+
adapter,
22132
config,
23133
fields,
24134
locale,
25135
parentIsLocalized = false,
26136
sort,
137+
sortAggregation,
27138
timestamps,
139+
versions,
28140
}: Args): Record<string, string> => {
29141
if (!sort) {
30142
if (timestamps) {
@@ -52,6 +164,23 @@ export const buildSortParam = ({
52164
acc['_id'] = sortDirection
53165
return acc
54166
}
167+
168+
if (
169+
sortAggregation &&
170+
relationshipSort({
171+
adapter,
172+
fields,
173+
locale,
174+
path: sortProperty,
175+
sort: acc,
176+
sortAggregation,
177+
sortDirection,
178+
versions,
179+
})
180+
) {
181+
return acc
182+
}
183+
55184
const localizedProperty = getLocalizedSortProperty({
56185
config,
57186
fields,
@@ -60,6 +189,7 @@ export const buildSortParam = ({
60189
segments: sortProperty.split('.'),
61190
})
62191
acc[localizedProperty] = sortDirection
192+
63193
return acc
64194
}, {})
65195

packages/db-mongodb/src/queryDrafts.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { PaginateOptions, QueryOptions } from 'mongoose'
1+
import type { PaginateOptions, PipelineStage, QueryOptions } from 'mongoose'
22
import type { QueryDrafts } from 'payload'
33

44
import { buildVersionCollectionFields, combineQueries, flattenWhereToOperators } from 'payload'
@@ -47,19 +47,24 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
4747
hasNearConstraint = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near'))
4848
}
4949

50+
const fields = buildVersionCollectionFields(this.payload.config, collectionConfig, true)
51+
52+
const sortAggregation: PipelineStage[] = []
5053
if (!hasNearConstraint) {
5154
sort = buildSortParam({
55+
adapter: this,
5256
config: this.payload.config,
53-
fields: collectionConfig.flattenedFields,
57+
fields,
5458
locale,
5559
sort: sortArg || collectionConfig.defaultSort,
60+
sortAggregation,
5661
timestamps: true,
62+
versions: true,
5763
})
5864
}
5965

6066
const combinedWhere = combineQueries({ latest: { equals: true } }, where)
6167

62-
const fields = buildVersionCollectionFields(this.payload.config, collectionConfig, true)
6368
const versionQuery = await buildQuery({
6469
adapter: this,
6570
fields,
@@ -133,7 +138,7 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
133138
})
134139

135140
// build join aggregation
136-
if (aggregate) {
141+
if (aggregate || sortAggregation.length > 0) {
137142
result = await aggregatePaginate({
138143
adapter: this,
139144
collation: paginationOptions.collation,

packages/db-mongodb/src/updateMany.ts

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const updateMany: UpdateMany = async function updateMany(
3939
let sort: Record<string, unknown> | undefined
4040
if (!hasNearConstraint) {
4141
sort = buildSortParam({
42+
adapter: this,
4243
config: this.payload.config,
4344
fields: collectionConfig.flattenedFields,
4445
locale,

packages/db-mongodb/src/utilities/aggregatePaginate.ts

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const aggregatePaginate = async ({
1616
query,
1717
session,
1818
sort,
19+
sortAggregation,
1920
useEstimatedCount,
2021
}: {
2122
adapter: MongooseAdapter
@@ -29,10 +30,17 @@ export const aggregatePaginate = async ({
2930
query: Record<string, unknown>
3031
session?: ClientSession
3132
sort?: object
33+
sortAggregation?: PipelineStage[]
3234
useEstimatedCount?: boolean
3335
}): Promise<PaginatedDocs<any>> => {
3436
const aggregation: PipelineStage[] = [{ $match: query }]
3537

38+
if (sortAggregation && sortAggregation.length > 0) {
39+
for (const stage of sortAggregation) {
40+
aggregation.push(stage)
41+
}
42+
}
43+
3644
if (sort) {
3745
const $sort: Record<string, -1 | 1> = {}
3846

packages/db-mongodb/src/utilities/buildJoinAggregation.ts

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export const buildJoinAggregation = async ({
8787
}
8888

8989
const sort = buildSortParam({
90+
adapter,
9091
config: adapter.payload.config,
9192
fields: aggregatedFields,
9293
locale,
@@ -279,6 +280,7 @@ export const buildJoinAggregation = async ({
279280
}
280281

281282
const sort = buildSortParam({
283+
adapter,
282284
config: adapter.payload.config,
283285
fields: collectionConfig.flattenedFields,
284286
locale,

packages/db-postgres/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@payloadcms/db-postgres",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"description": "The officially supported Postgres database adapter for Payload",
55
"homepage": "https://payloadcms.com",
66
"repository": {

packages/db-sqlite/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@payloadcms/db-sqlite",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"description": "The officially supported SQLite database adapter for Payload",
55
"homepage": "https://payloadcms.com",
66
"repository": {

packages/db-vercel-postgres/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@payloadcms/db-vercel-postgres",
3-
"version": "3.28.1",
3+
"version": "3.29.0",
44
"description": "Vercel Postgres adapter for Payload",
55
"homepage": "https://payloadcms.com",
66
"repository": {

0 commit comments

Comments
 (0)