@payloadcms/db-mongodb 4.0.0-internal.fa183d3 → 4.0.0-internal.fec2230

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/create.d.ts.map +1 -1
  2. package/dist/create.js +2 -1
  3. package/dist/create.js.map +1 -1
  4. package/dist/createGlobalVersion.js +1 -1
  5. package/dist/createGlobalVersion.js.map +1 -1
  6. package/dist/createMigration.d.ts.map +1 -1
  7. package/dist/createMigration.js +9 -2
  8. package/dist/createMigration.js.map +1 -1
  9. package/dist/createVersion.js +1 -1
  10. package/dist/createVersion.js.map +1 -1
  11. package/dist/find.js +1 -1
  12. package/dist/find.js.map +1 -1
  13. package/dist/findOne.js +1 -1
  14. package/dist/findOne.js.map +1 -1
  15. package/dist/migrateFresh.d.ts +4 -2
  16. package/dist/migrateFresh.d.ts.map +1 -1
  17. package/dist/migrateFresh.js +20 -6
  18. package/dist/migrateFresh.js.map +1 -1
  19. package/dist/predefinedMigrations/migrateRelationshipsV2_V3.d.ts.map +1 -1
  20. package/dist/predefinedMigrations/migrateRelationshipsV2_V3.js +4 -4
  21. package/dist/predefinedMigrations/migrateRelationshipsV2_V3.js.map +1 -1
  22. package/dist/queries/buildSearchParams.d.ts.map +1 -1
  23. package/dist/queries/buildSearchParams.js +139 -6
  24. package/dist/queries/buildSearchParams.js.map +1 -1
  25. package/dist/queries/buildSortParam.spec.js +1 -1
  26. package/dist/queries/buildSortParam.spec.js.map +1 -1
  27. package/dist/queries/getLocalizedSortProperty.spec.js +1 -1
  28. package/dist/queries/getLocalizedSortProperty.spec.js.map +1 -1
  29. package/dist/queries/parseParams.js.map +1 -1
  30. package/dist/queryDrafts.js +1 -1
  31. package/dist/queryDrafts.js.map +1 -1
  32. package/dist/updateJobs.d.ts.map +1 -1
  33. package/dist/updateJobs.js +70 -13
  34. package/dist/updateJobs.js.map +1 -1
  35. package/dist/utilities/buildJoinAggregation.d.ts +1 -1
  36. package/dist/utilities/buildJoinAggregation.d.ts.map +1 -1
  37. package/dist/utilities/buildJoinAggregation.js +2 -2
  38. package/dist/utilities/buildJoinAggregation.js.map +1 -1
  39. package/dist/utilities/transform.d.ts.map +1 -1
  40. package/dist/utilities/transform.js +15 -0
  41. package/dist/utilities/transform.js.map +1 -1
  42. package/dist/utilities/transform.spec.js +67 -0
  43. package/dist/utilities/transform.spec.js.map +1 -1
  44. package/package.json +5 -5
@@ -1,6 +1,6 @@
1
1
  import { Types } from 'mongoose';
2
2
  import { APIError, escapeRegExp, getFieldByPath, getLocalizedPaths } from 'payload';
3
- import { validOperatorSet } from 'payload/shared';
3
+ import { hasManyRelationshipOperatorSet, isNestedRelationshipQuery, validOperatorSet } from 'payload/shared';
4
4
  import { getCollection } from '../utilities/getEntity.js';
5
5
  import { isObjectID } from '../utilities/isObjectID.js';
6
6
  import { operatorMap } from './operatorMap.js';
@@ -50,6 +50,16 @@ const subQueryOptions = {
50
50
  return undefined;
51
51
  }
52
52
  const [{ field, path }] = paths;
53
+ if (hasManyRelationshipOperatorSet.has(operator) && paths.length === 1 && (field.type === 'relationship' || field.type === 'upload') && field.hasMany && typeof field.relationTo === 'string' && isNestedRelationshipQuery(val)) {
54
+ return buildHasManyRelationshipSearchParam({
55
+ field,
56
+ locale,
57
+ nestedWhere: val,
58
+ operator: operator,
59
+ path,
60
+ payload
61
+ });
62
+ }
53
63
  if (path) {
54
64
  const sanitizedQueryValue = sanitizeQueryValue({
55
65
  field,
@@ -79,10 +89,16 @@ const subQueryOptions = {
79
89
  // Remove top collection and reverse array
80
90
  // to work backwards from top
81
91
  const pathsToQuery = paths.slice(1).reverse();
92
+ const parentPaths = paths.slice(0, -1).reverse();
82
93
  let relationshipQuery = {
83
94
  value: {}
84
95
  };
85
96
  for (const [i, { collectionSlug, path: subPath }] of pathsToQuery.entries()){
97
+ // The arrays are reversed together, so both entries describe the same relationship hop.
98
+ const parentField = parentPaths[i]?.field;
99
+ if (!parentField) {
100
+ return undefined;
101
+ }
86
102
  if (!collectionSlug) {
87
103
  throw new APIError(`Collection with the slug ${collectionSlug} was not found.`);
88
104
  }
@@ -100,15 +116,14 @@ const subQueryOptions = {
100
116
  }
101
117
  }
102
118
  });
103
- const field = paths[0].field;
104
119
  const select = {
105
120
  _id: true
106
121
  };
107
122
  let joinPath = null;
108
- if (field.type === 'join') {
123
+ if (parentField.type === 'join') {
109
124
  const relationshipField = getFieldByPath({
110
125
  fields: collectionConfig.flattenedFields,
111
- path: field.on
126
+ path: parentField.on
112
127
  });
113
128
  if (!relationshipField) {
114
129
  throw new APIError('Relationship field was not found');
@@ -167,14 +182,53 @@ const subQueryOptions = {
167
182
  const nextSubPath = pathsToQuery[i + 1]?.path;
168
183
  if (nextSubPath) {
169
184
  relationshipQuery = {
170
- value: {
171
- [nextSubPath]: $in
185
+ value: joinPath ? {
186
+ _id: {
187
+ $in
188
+ }
189
+ } : {
190
+ [nextSubPath]: {
191
+ $in
192
+ }
172
193
  }
173
194
  };
174
195
  }
175
196
  continue;
176
197
  }
177
198
  const subQuery = relationshipQuery.value;
199
+ /**
200
+ * Follow this join back to its parent IDs.
201
+ * For example, matching songs yield album IDs, then artist IDs.
202
+ */ if (parentField.type === 'join') {
203
+ const relationshipField = getFieldByPath({
204
+ fields: collectionConfig.flattenedFields,
205
+ path: parentField.on
206
+ });
207
+ if (!relationshipField) {
208
+ throw new APIError('Relationship field was not found');
209
+ }
210
+ let joinPath = relationshipField.localizedPath;
211
+ if (relationshipField.pathHasLocalized && payload.config.localization) {
212
+ joinPath = joinPath.replace('<locale>', locale || payload.config.localization.defaultLocale);
213
+ }
214
+ const $in = await SubModel.distinct(joinPath, subQuery);
215
+ if (i + 1 === pathsToQuery.length) {
216
+ return {
217
+ path: '_id',
218
+ value: {
219
+ $in
220
+ }
221
+ };
222
+ }
223
+ relationshipQuery = {
224
+ value: {
225
+ _id: {
226
+ $in
227
+ }
228
+ }
229
+ };
230
+ continue;
231
+ }
178
232
  const result = await SubModel.find(subQuery, subQueryOptions);
179
233
  const $in = result.map((doc)=>doc._id);
180
234
  // If it is the last recursion
@@ -299,5 +353,84 @@ const subQueryOptions = {
299
353
  }
300
354
  return undefined;
301
355
  }
356
+ /**
357
+ * Builds a MongoDB condition for an operator containing a nested has-many relationship query.
358
+ *
359
+ * First, it finds IDs from the related collection that match the nested query. The parent
360
+ * collection can then use `$in` or `$nin` against its stored relationship IDs.
361
+ *
362
+ * @example
363
+ * ```ts
364
+ * // Input
365
+ * { ingredients: { not_equals: { isHealthy: { equals: false } } } }
366
+ *
367
+ * // Simplified MongoDB result, after finding the matching ingredient IDs
368
+ * { ingredients: { $nin: [unhealthyIngredientID] } }
369
+ * ```
370
+ */ async function buildHasManyRelationshipSearchParam({ field, locale, nestedWhere, operator, path, payload }) {
371
+ if (field.type !== 'relationship' && field.type !== 'upload' || !field.hasMany || typeof field.relationTo !== 'string' || !isNestedRelationshipQuery(nestedWhere)) {
372
+ return undefined;
373
+ }
374
+ const { Model: RelatedModel } = getCollection({
375
+ adapter: payload.db,
376
+ collectionSlug: field.relationTo
377
+ });
378
+ const pathLocale = payload.config.localization ? payload.config.localization.localeCodes.find((localeCode)=>path.split('.').at(-1) === localeCode) : undefined;
379
+ const matchingRelatedDocumentsQuery = await RelatedModel.buildQuery({
380
+ locale: pathLocale ?? locale,
381
+ payload,
382
+ where: nestedWhere
383
+ });
384
+ const findRelatedDocumentIDs = async (query)=>(await RelatedModel.find(query).lean().select({
385
+ _id: true
386
+ })).map((document)=>document._id);
387
+ switch(operator){
388
+ case 'contains':
389
+ {
390
+ const matchingRelatedDocumentIDs = await findRelatedDocumentIDs(matchingRelatedDocumentsQuery);
391
+ return {
392
+ path,
393
+ value: {
394
+ $in: matchingRelatedDocumentIDs
395
+ }
396
+ };
397
+ }
398
+ case 'equals':
399
+ {
400
+ // Every related document satisfies an empty nested query.
401
+ if (!Object.keys(matchingRelatedDocumentsQuery).length) {
402
+ return {
403
+ path,
404
+ value: {
405
+ $nin: []
406
+ }
407
+ };
408
+ }
409
+ // MongoDB rejects `$near` and `$text` when they are inverted with `$nor`. Check the parent
410
+ // instead: none of its IDs may fall outside the matching IDs.
411
+ const matchingRelatedDocumentIDs = await findRelatedDocumentIDs(matchingRelatedDocumentsQuery);
412
+ return {
413
+ path,
414
+ value: {
415
+ $not: {
416
+ $elemMatch: {
417
+ $nin: matchingRelatedDocumentIDs
418
+ }
419
+ }
420
+ }
421
+ };
422
+ }
423
+ case 'not_equals':
424
+ {
425
+ const matchingRelatedDocumentIDs = await findRelatedDocumentIDs(matchingRelatedDocumentsQuery);
426
+ return {
427
+ path,
428
+ value: {
429
+ $nin: matchingRelatedDocumentIDs
430
+ }
431
+ };
432
+ }
433
+ }
434
+ }
302
435
 
303
436
  //# sourceMappingURL=buildSearchParams.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queries/buildSearchParams.ts"],"sourcesContent":["import type { FilterQuery } from 'mongoose'\nimport type { FlattenedField, Operator, PathToQuery, Payload } from 'payload'\n\nimport { Types } from 'mongoose'\nimport { APIError, escapeRegExp, getFieldByPath, getLocalizedPaths } from 'payload'\nimport { validOperatorSet } from 'payload/shared'\n\nimport type { MongooseAdapter } from '../index.js'\nimport type { OperatorMapKey } from './operatorMap.js'\n\nimport { getCollection } from '../utilities/getEntity.js'\nimport { isObjectID } from '../utilities/isObjectID.js'\nimport { operatorMap } from './operatorMap.js'\nimport { sanitizeQueryValue } from './sanitizeQueryValue.js'\n\ntype SearchParam = {\n path?: string\n rawQuery?: unknown\n value?: unknown\n}\n\nconst subQueryOptions = {\n lean: true,\n}\n\n/**\n * Convert the Payload key / value / operator into a MongoDB query\n */\nexport async function buildSearchParam({\n collectionSlug,\n fields,\n globalSlug,\n incomingPath,\n locale,\n operator,\n parentIsLocalized,\n payload,\n val,\n}: {\n collectionSlug?: string\n fields: FlattenedField[]\n globalSlug?: string\n incomingPath: string\n locale?: string\n operator: Operator\n parentIsLocalized: boolean\n payload: Payload\n val: unknown\n}): Promise<SearchParam | undefined> {\n // Replace GraphQL nested field double underscore formatting\n let sanitizedPath = incomingPath.replace(/__/g, '.')\n if (sanitizedPath === 'id') {\n sanitizedPath = '_id'\n }\n\n let paths: PathToQuery[] = []\n\n let hasCustomID = false\n\n if (sanitizedPath === '_id') {\n const customIDFieldType = collectionSlug\n ? payload.collections[collectionSlug]?.customIDType\n : undefined\n\n let idFieldType: 'number' | 'text' = 'text'\n\n if (customIDFieldType) {\n idFieldType = customIDFieldType\n hasCustomID = true\n }\n\n paths.push({\n collectionSlug,\n complete: true,\n field: {\n name: 'id',\n type: idFieldType,\n } as FlattenedField,\n parentIsLocalized: parentIsLocalized ?? false,\n path: '_id',\n })\n } else {\n paths = getLocalizedPaths({\n collectionSlug,\n fields,\n globalSlug,\n incomingPath: sanitizedPath,\n locale,\n parentIsLocalized,\n payload,\n })\n }\n\n if (!paths[0]) {\n return undefined\n }\n\n const [{ field, path }] = paths\n if (path) {\n const sanitizedQueryValue = sanitizeQueryValue({\n field,\n hasCustomID,\n locale,\n operator,\n parentIsLocalized,\n path,\n payload,\n val,\n })\n\n if (!sanitizedQueryValue) {\n return undefined\n }\n\n const { operator: formattedOperator, rawQuery, val: formattedValue } = sanitizedQueryValue\n\n if (rawQuery && paths.length === 1) {\n return { value: rawQuery }\n }\n\n if (!formattedOperator) {\n return undefined\n }\n\n // If there are multiple collections to search through,\n // Recursively build up a list of query constraints\n if (paths.length > 1) {\n // Remove top collection and reverse array\n // to work backwards from top\n const pathsToQuery = paths.slice(1).reverse()\n\n let relationshipQuery: SearchParam = {\n value: {},\n }\n\n for (const [i, { collectionSlug, path: subPath }] of pathsToQuery.entries()) {\n if (!collectionSlug) {\n throw new APIError(`Collection with the slug ${collectionSlug} was not found.`)\n }\n\n const { collectionConfig, Model: SubModel } = getCollection({\n adapter: payload.db as MongooseAdapter,\n collectionSlug,\n })\n\n if (i === 0) {\n const subQuery = await SubModel.buildQuery({\n locale,\n payload,\n where: {\n [subPath]: {\n [formattedOperator]: val,\n },\n },\n })\n\n const field = paths[0].field\n\n const select: Record<string, boolean> = {\n _id: true,\n }\n\n let joinPath: null | string = null\n\n if (field.type === 'join') {\n const relationshipField = getFieldByPath({\n fields: collectionConfig.flattenedFields,\n path: field.on,\n })\n if (!relationshipField) {\n throw new APIError('Relationship field was not found')\n }\n\n let path = relationshipField.localizedPath\n if (relationshipField.pathHasLocalized && payload.config.localization) {\n path = path.replace('<locale>', locale || payload.config.localization.defaultLocale)\n }\n select[path] = true\n\n joinPath = path\n }\n\n if (joinPath) {\n select[joinPath] = true\n }\n\n const result = await SubModel.find(subQuery).lean().select(select)\n\n const $in: unknown[] = []\n\n result.forEach((doc: any) => {\n if (joinPath) {\n let ref = doc\n\n for (const segment of joinPath.split('.')) {\n if (Array.isArray(ref)) {\n ref = ref\n .map((item) => (typeof item === 'object' && item ? item[segment] : undefined))\n .flat()\n .filter((item) => item != null)\n } else if (typeof ref === 'object' && ref) {\n ref = ref[segment]\n } else {\n ref = undefined\n break\n }\n }\n\n if (Array.isArray(ref)) {\n for (const item of ref) {\n if (isObjectID(item)) {\n $in.push(item)\n }\n }\n } else if (isObjectID(ref)) {\n $in.push(ref)\n }\n } else {\n const stringID = doc._id.toString()\n if (Types.ObjectId.isValid(stringID)) {\n $in.push(doc._id)\n } else {\n $in.push(stringID)\n }\n }\n })\n\n if (pathsToQuery.length === 1) {\n return {\n path: joinPath ? '_id' : path,\n value: { $in },\n }\n }\n\n const nextSubPath = pathsToQuery[i + 1]?.path\n\n if (nextSubPath) {\n relationshipQuery = { value: { [nextSubPath]: $in } }\n }\n\n continue\n }\n\n const subQuery = relationshipQuery.value as FilterQuery<any>\n const result = await SubModel.find(subQuery, subQueryOptions)\n\n const $in = result.map((doc) => doc._id)\n\n // If it is the last recursion\n // then pass through the search param\n if (i + 1 === pathsToQuery.length) {\n relationshipQuery = {\n path,\n value: { $in },\n }\n } else {\n const nextSubPath = pathsToQuery[i + 1]?.path\n if (nextSubPath) {\n relationshipQuery = {\n value: {\n [nextSubPath]: { $in },\n },\n }\n }\n }\n }\n\n return relationshipQuery\n }\n\n if (formattedOperator && validOperatorSet.has(formattedOperator as Operator)) {\n const operatorKey = operatorMap[formattedOperator as OperatorMapKey]\n\n if (field.type === 'relationship' || field.type === 'upload') {\n let hasNumberIDRelation\n let multiIDCondition = '$or'\n if (operatorKey === '$ne') {\n multiIDCondition = '$and'\n }\n\n const result = {\n value: {\n [multiIDCondition]: [{ [path]: { [operatorKey]: formattedValue } }],\n },\n }\n\n if (typeof formattedValue === 'string') {\n if (Types.ObjectId.isValid(formattedValue)) {\n result.value[multiIDCondition]?.push({\n [path]: { [operatorKey]: new Types.ObjectId(formattedValue) },\n })\n } else {\n ;(Array.isArray(field.relationTo) ? field.relationTo : [field.relationTo]).forEach(\n (relationTo) => {\n const isRelatedToCustomNumberID =\n payload.collections[relationTo]?.customIDType === 'number'\n\n if (isRelatedToCustomNumberID) {\n hasNumberIDRelation = true\n }\n },\n )\n\n if (hasNumberIDRelation) {\n result.value[multiIDCondition]?.push({\n [path]: { [operatorKey]: parseFloat(formattedValue) },\n })\n }\n }\n }\n\n const length = result.value[multiIDCondition]?.length\n\n if (typeof length === 'number' && length > 1) {\n return result\n }\n }\n\n if (formattedOperator === 'like' && typeof formattedValue === 'string') {\n const words = formattedValue.split(' ')\n\n const result = {\n value: {\n $and: words.map((word) => ({\n [path]: {\n $options: 'i',\n $regex: escapeRegExp(word),\n },\n })),\n },\n }\n\n return result\n }\n\n if (formattedOperator === 'not_like' && typeof formattedValue === 'string') {\n const words = formattedValue.split(' ')\n\n const result = {\n value: {\n $and: words.map((word) => ({\n [path]: {\n $not: {\n $options: 'i',\n $regex: escapeRegExp(word),\n },\n },\n })),\n },\n }\n\n return result\n }\n\n // Some operators like 'near' need to define a full query\n // so if there is no operator key, just return the value\n if (!operatorKey) {\n return {\n path,\n value: formattedValue,\n }\n }\n\n return {\n path,\n value: { [operatorKey]: formattedValue },\n }\n }\n }\n return undefined\n}\n"],"names":["Types","APIError","escapeRegExp","getFieldByPath","getLocalizedPaths","validOperatorSet","getCollection","isObjectID","operatorMap","sanitizeQueryValue","subQueryOptions","lean","buildSearchParam","collectionSlug","fields","globalSlug","incomingPath","locale","operator","parentIsLocalized","payload","val","sanitizedPath","replace","paths","hasCustomID","customIDFieldType","collections","customIDType","undefined","idFieldType","push","complete","field","name","type","path","sanitizedQueryValue","formattedOperator","rawQuery","formattedValue","length","value","pathsToQuery","slice","reverse","relationshipQuery","i","subPath","entries","collectionConfig","Model","SubModel","adapter","db","subQuery","buildQuery","where","select","_id","joinPath","relationshipField","flattenedFields","on","localizedPath","pathHasLocalized","config","localization","defaultLocale","result","find","$in","forEach","doc","ref","segment","split","Array","isArray","map","item","flat","filter","stringID","toString","ObjectId","isValid","nextSubPath","has","operatorKey","hasNumberIDRelation","multiIDCondition","relationTo","isRelatedToCustomNumberID","parseFloat","words","$and","word","$options","$regex","$not"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/queries/buildSearchParams.ts"],"sourcesContent":["import type { QueryFilter } from 'mongoose'\nimport type {\n FlattenedField,\n HasManyRelationshipOperator,\n Operator,\n PathToQuery,\n Payload,\n} from 'payload'\n\nimport { Types } from 'mongoose'\nimport { APIError, escapeRegExp, getFieldByPath, getLocalizedPaths } from 'payload'\nimport {\n hasManyRelationshipOperatorSet,\n isNestedRelationshipQuery,\n validOperatorSet,\n} from 'payload/shared'\n\nimport type { MongooseAdapter } from '../index.js'\nimport type { OperatorMapKey } from './operatorMap.js'\n\nimport { getCollection } from '../utilities/getEntity.js'\nimport { isObjectID } from '../utilities/isObjectID.js'\nimport { operatorMap } from './operatorMap.js'\nimport { sanitizeQueryValue } from './sanitizeQueryValue.js'\n\ntype SearchParam = {\n path?: string\n rawQuery?: unknown\n value?: unknown\n}\n\nconst subQueryOptions = {\n lean: true,\n}\n\n/**\n * Convert the Payload key / value / operator into a MongoDB query\n */\nexport async function buildSearchParam({\n collectionSlug,\n fields,\n globalSlug,\n incomingPath,\n locale,\n operator,\n parentIsLocalized,\n payload,\n val,\n}: {\n collectionSlug?: string\n fields: FlattenedField[]\n globalSlug?: string\n incomingPath: string\n locale?: string\n operator: Operator\n parentIsLocalized: boolean\n payload: Payload\n val: unknown\n}): Promise<SearchParam | undefined> {\n // Replace GraphQL nested field double underscore formatting\n let sanitizedPath = incomingPath.replace(/__/g, '.')\n if (sanitizedPath === 'id') {\n sanitizedPath = '_id'\n }\n\n let paths: PathToQuery[] = []\n\n let hasCustomID = false\n\n if (sanitizedPath === '_id') {\n const customIDFieldType = collectionSlug\n ? payload.collections[collectionSlug]?.customIDType\n : undefined\n\n let idFieldType: 'number' | 'text' = 'text'\n\n if (customIDFieldType) {\n idFieldType = customIDFieldType\n hasCustomID = true\n }\n\n paths.push({\n collectionSlug,\n complete: true,\n field: {\n name: 'id',\n type: idFieldType,\n } as FlattenedField,\n parentIsLocalized: parentIsLocalized ?? false,\n path: '_id',\n })\n } else {\n paths = getLocalizedPaths({\n collectionSlug,\n fields,\n globalSlug,\n incomingPath: sanitizedPath,\n locale,\n parentIsLocalized,\n payload,\n })\n }\n\n if (!paths[0]) {\n return undefined\n }\n\n const [{ field, path }] = paths\n\n if (\n hasManyRelationshipOperatorSet.has(operator as HasManyRelationshipOperator) &&\n paths.length === 1 &&\n (field.type === 'relationship' || field.type === 'upload') &&\n field.hasMany &&\n typeof field.relationTo === 'string' &&\n isNestedRelationshipQuery(val)\n ) {\n return buildHasManyRelationshipSearchParam({\n field,\n locale,\n nestedWhere: val,\n operator: operator as HasManyRelationshipOperator,\n path,\n payload,\n })\n }\n\n if (path) {\n const sanitizedQueryValue = sanitizeQueryValue({\n field,\n hasCustomID,\n locale,\n operator,\n parentIsLocalized,\n path,\n payload,\n val,\n })\n\n if (!sanitizedQueryValue) {\n return undefined\n }\n\n const { operator: formattedOperator, rawQuery, val: formattedValue } = sanitizedQueryValue\n\n if (rawQuery && paths.length === 1) {\n return { value: rawQuery }\n }\n\n if (!formattedOperator) {\n return undefined\n }\n\n // If there are multiple collections to search through,\n // Recursively build up a list of query constraints\n if (paths.length > 1) {\n // Remove top collection and reverse array\n // to work backwards from top\n const pathsToQuery = paths.slice(1).reverse()\n const parentPaths = paths.slice(0, -1).reverse()\n\n let relationshipQuery: SearchParam = {\n value: {},\n }\n\n for (const [i, { collectionSlug, path: subPath }] of pathsToQuery.entries()) {\n // The arrays are reversed together, so both entries describe the same relationship hop.\n const parentField = parentPaths[i]?.field\n\n if (!parentField) {\n return undefined\n }\n\n if (!collectionSlug) {\n throw new APIError(`Collection with the slug ${collectionSlug} was not found.`)\n }\n\n const { collectionConfig, Model: SubModel } = getCollection({\n adapter: payload.db as MongooseAdapter,\n collectionSlug,\n })\n\n if (i === 0) {\n const subQuery = await SubModel.buildQuery({\n locale,\n payload,\n where: {\n [subPath]: {\n [formattedOperator]: val,\n },\n },\n })\n\n const select: Record<string, boolean> = {\n _id: true,\n }\n\n let joinPath: null | string = null\n\n if (parentField.type === 'join') {\n const relationshipField = getFieldByPath({\n fields: collectionConfig.flattenedFields,\n path: parentField.on,\n })\n if (!relationshipField) {\n throw new APIError('Relationship field was not found')\n }\n\n let path = relationshipField.localizedPath\n if (relationshipField.pathHasLocalized && payload.config.localization) {\n path = path.replace('<locale>', locale || payload.config.localization.defaultLocale)\n }\n select[path] = true\n\n joinPath = path\n }\n\n if (joinPath) {\n select[joinPath] = true\n }\n\n const result = await SubModel.find(subQuery).lean().select(select)\n\n const $in: unknown[] = []\n\n result.forEach((doc: any) => {\n if (joinPath) {\n let ref = doc\n\n for (const segment of joinPath.split('.')) {\n if (Array.isArray(ref)) {\n ref = ref\n .map((item) => (typeof item === 'object' && item ? item[segment] : undefined))\n .flat()\n .filter((item) => item != null)\n } else if (typeof ref === 'object' && ref) {\n ref = ref[segment]\n } else {\n ref = undefined\n break\n }\n }\n\n if (Array.isArray(ref)) {\n for (const item of ref) {\n if (isObjectID(item)) {\n $in.push(item)\n }\n }\n } else if (isObjectID(ref)) {\n $in.push(ref)\n }\n } else {\n const stringID = doc._id.toString()\n if (Types.ObjectId.isValid(stringID)) {\n $in.push(doc._id)\n } else {\n $in.push(stringID)\n }\n }\n })\n\n if (pathsToQuery.length === 1) {\n return {\n path: joinPath ? '_id' : path,\n value: { $in },\n }\n }\n\n const nextSubPath = pathsToQuery[i + 1]?.path\n\n if (nextSubPath) {\n relationshipQuery = {\n value: joinPath ? { _id: { $in } } : { [nextSubPath]: { $in } },\n }\n }\n\n continue\n }\n\n const subQuery = relationshipQuery.value as QueryFilter<any>\n\n /**\n * Follow this join back to its parent IDs.\n * For example, matching songs yield album IDs, then artist IDs.\n */\n if (parentField.type === 'join') {\n const relationshipField = getFieldByPath({\n fields: collectionConfig.flattenedFields,\n path: parentField.on,\n })\n if (!relationshipField) {\n throw new APIError('Relationship field was not found')\n }\n\n let joinPath = relationshipField.localizedPath\n if (relationshipField.pathHasLocalized && payload.config.localization) {\n joinPath = joinPath.replace(\n '<locale>',\n locale || payload.config.localization.defaultLocale,\n )\n }\n\n const $in = await SubModel.distinct(joinPath, subQuery)\n if (i + 1 === pathsToQuery.length) {\n return { path: '_id', value: { $in } }\n }\n\n relationshipQuery = { value: { _id: { $in } } }\n continue\n }\n\n const result = await SubModel.find(subQuery, subQueryOptions)\n\n const $in = result.map((doc) => doc._id)\n\n // If it is the last recursion\n // then pass through the search param\n if (i + 1 === pathsToQuery.length) {\n relationshipQuery = {\n path,\n value: { $in },\n }\n } else {\n const nextSubPath = pathsToQuery[i + 1]?.path\n if (nextSubPath) {\n relationshipQuery = {\n value: {\n [nextSubPath]: { $in },\n },\n }\n }\n }\n }\n\n return relationshipQuery\n }\n\n if (formattedOperator && validOperatorSet.has(formattedOperator as Operator)) {\n const operatorKey = operatorMap[formattedOperator as OperatorMapKey]\n\n if (field.type === 'relationship' || field.type === 'upload') {\n let hasNumberIDRelation\n let multiIDCondition = '$or'\n if (operatorKey === '$ne') {\n multiIDCondition = '$and'\n }\n\n const result = {\n value: {\n [multiIDCondition]: [{ [path]: { [operatorKey]: formattedValue } }],\n },\n }\n\n if (typeof formattedValue === 'string') {\n if (Types.ObjectId.isValid(formattedValue)) {\n result.value[multiIDCondition]?.push({\n [path]: { [operatorKey]: new Types.ObjectId(formattedValue) },\n })\n } else {\n ;(Array.isArray(field.relationTo) ? field.relationTo : [field.relationTo]).forEach(\n (relationTo) => {\n const isRelatedToCustomNumberID =\n payload.collections[relationTo]?.customIDType === 'number'\n\n if (isRelatedToCustomNumberID) {\n hasNumberIDRelation = true\n }\n },\n )\n\n if (hasNumberIDRelation) {\n result.value[multiIDCondition]?.push({\n [path]: { [operatorKey]: parseFloat(formattedValue) },\n })\n }\n }\n }\n\n const length = result.value[multiIDCondition]?.length\n\n if (typeof length === 'number' && length > 1) {\n return result\n }\n }\n\n if (formattedOperator === 'like' && typeof formattedValue === 'string') {\n const words = formattedValue.split(' ')\n\n const result = {\n value: {\n $and: words.map((word) => ({\n [path]: {\n $options: 'i',\n $regex: escapeRegExp(word),\n },\n })),\n },\n }\n\n return result\n }\n\n if (formattedOperator === 'not_like' && typeof formattedValue === 'string') {\n const words = formattedValue.split(' ')\n\n const result = {\n value: {\n $and: words.map((word) => ({\n [path]: {\n $not: {\n $options: 'i',\n $regex: escapeRegExp(word),\n },\n },\n })),\n },\n }\n\n return result\n }\n\n // Some operators like 'near' need to define a full query\n // so if there is no operator key, just return the value\n if (!operatorKey) {\n return {\n path,\n value: formattedValue,\n }\n }\n\n return {\n path,\n value: { [operatorKey]: formattedValue },\n }\n }\n }\n return undefined\n}\n\n/**\n * Builds a MongoDB condition for an operator containing a nested has-many relationship query.\n *\n * First, it finds IDs from the related collection that match the nested query. The parent\n * collection can then use `$in` or `$nin` against its stored relationship IDs.\n *\n * @example\n * ```ts\n * // Input\n * { ingredients: { not_equals: { isHealthy: { equals: false } } } }\n *\n * // Simplified MongoDB result, after finding the matching ingredient IDs\n * { ingredients: { $nin: [unhealthyIngredientID] } }\n * ```\n */\nasync function buildHasManyRelationshipSearchParam({\n field,\n locale,\n nestedWhere,\n operator,\n path,\n payload,\n}: {\n field: FlattenedField\n locale?: string\n nestedWhere: unknown\n operator: HasManyRelationshipOperator\n path: string\n payload: Payload\n}): Promise<SearchParam | undefined> {\n if (\n (field.type !== 'relationship' && field.type !== 'upload') ||\n !field.hasMany ||\n typeof field.relationTo !== 'string' ||\n !isNestedRelationshipQuery(nestedWhere)\n ) {\n return undefined\n }\n\n const { Model: RelatedModel } = getCollection({\n adapter: payload.db as MongooseAdapter,\n collectionSlug: field.relationTo,\n })\n const pathLocale = payload.config.localization\n ? payload.config.localization.localeCodes.find(\n (localeCode) => path.split('.').at(-1) === localeCode,\n )\n : undefined\n const matchingRelatedDocumentsQuery = await RelatedModel.buildQuery({\n locale: pathLocale ?? locale,\n payload,\n where: nestedWhere,\n })\n\n const findRelatedDocumentIDs = async (query: Record<string, unknown>) =>\n (await RelatedModel.find(query).lean().select({ _id: true })).map((document) => document._id)\n\n switch (operator) {\n case 'contains': {\n const matchingRelatedDocumentIDs = await findRelatedDocumentIDs(matchingRelatedDocumentsQuery)\n\n return {\n path,\n value: { $in: matchingRelatedDocumentIDs },\n }\n }\n\n case 'equals': {\n // Every related document satisfies an empty nested query.\n if (!Object.keys(matchingRelatedDocumentsQuery).length) {\n return {\n path,\n value: { $nin: [] },\n }\n }\n\n // MongoDB rejects `$near` and `$text` when they are inverted with `$nor`. Check the parent\n // instead: none of its IDs may fall outside the matching IDs.\n const matchingRelatedDocumentIDs = await findRelatedDocumentIDs(matchingRelatedDocumentsQuery)\n\n return {\n path,\n value: { $not: { $elemMatch: { $nin: matchingRelatedDocumentIDs } } },\n }\n }\n\n case 'not_equals': {\n const matchingRelatedDocumentIDs = await findRelatedDocumentIDs(matchingRelatedDocumentsQuery)\n\n return {\n path,\n value: { $nin: matchingRelatedDocumentIDs },\n }\n }\n }\n}\n"],"names":["Types","APIError","escapeRegExp","getFieldByPath","getLocalizedPaths","hasManyRelationshipOperatorSet","isNestedRelationshipQuery","validOperatorSet","getCollection","isObjectID","operatorMap","sanitizeQueryValue","subQueryOptions","lean","buildSearchParam","collectionSlug","fields","globalSlug","incomingPath","locale","operator","parentIsLocalized","payload","val","sanitizedPath","replace","paths","hasCustomID","customIDFieldType","collections","customIDType","undefined","idFieldType","push","complete","field","name","type","path","has","length","hasMany","relationTo","buildHasManyRelationshipSearchParam","nestedWhere","sanitizedQueryValue","formattedOperator","rawQuery","formattedValue","value","pathsToQuery","slice","reverse","parentPaths","relationshipQuery","i","subPath","entries","parentField","collectionConfig","Model","SubModel","adapter","db","subQuery","buildQuery","where","select","_id","joinPath","relationshipField","flattenedFields","on","localizedPath","pathHasLocalized","config","localization","defaultLocale","result","find","$in","forEach","doc","ref","segment","split","Array","isArray","map","item","flat","filter","stringID","toString","ObjectId","isValid","nextSubPath","distinct","operatorKey","hasNumberIDRelation","multiIDCondition","isRelatedToCustomNumberID","parseFloat","words","$and","word","$options","$regex","$not","RelatedModel","pathLocale","localeCodes","localeCode","at","matchingRelatedDocumentsQuery","findRelatedDocumentIDs","query","document","matchingRelatedDocumentIDs","Object","keys","$nin","$elemMatch"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { buildSortParam } from './buildSortParam.js';
4
4
  let config;
5
5
  describe('builds sort params', ()=>{
6
6
  beforeAll(async ()=>{
7
- config = await sanitizeConfig({
7
+ config = sanitizeConfig({
8
8
  localization: {
9
9
  defaultLocale: 'en',
10
10
  fallback: true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queries/buildSortParam.spec.ts"],"sourcesContent":["import type { Config, SanitizedConfig } from 'payload'\nimport { describe, beforeAll, it, expect } from 'vitest'\n\nimport { sanitizeConfig } from 'payload'\n\nimport { buildSortParam } from './buildSortParam.js'\nimport { MongooseAdapter } from '../index.js'\n\nlet config: SanitizedConfig\n\ndescribe('builds sort params', () => {\n beforeAll(async () => {\n config = await sanitizeConfig({\n localization: {\n defaultLocale: 'en',\n fallback: true,\n locales: ['en', 'es'],\n },\n } as Config)\n })\n it('adds a fallback on non-unique field', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n },\n ],\n locale: 'en',\n sort: 'order',\n timestamps: true,\n adapter: {\n disableFallbackSort: false,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ order: 'asc', createdAt: 'desc' })\n })\n\n it('adds a fallback when sort isnt provided', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n },\n ],\n locale: 'en',\n sort: undefined,\n timestamps: true,\n adapter: {\n disableFallbackSort: false,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ createdAt: 'desc' })\n })\n\n it('does not add a fallback on non-unique field when disableFallbackSort is true', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n },\n ],\n locale: 'en',\n sort: 'order',\n timestamps: true,\n adapter: {\n disableFallbackSort: true,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ order: 'asc' })\n })\n\n // This test should be true even when disableFallbackSort is false\n it('does not add a fallback on unique field', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n unique: true, // Marking this field as unique\n },\n ],\n locale: 'en',\n sort: 'order',\n timestamps: true,\n adapter: {\n disableFallbackSort: false,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ order: 'asc' })\n })\n})\n"],"names":["describe","beforeAll","it","expect","sanitizeConfig","buildSortParam","config","localization","defaultLocale","fallback","locales","result","parentIsLocalized","fields","name","type","locale","sort","timestamps","adapter","disableFallbackSort","toStrictEqual","order","createdAt","undefined","unique"],"mappings":"AACA,SAASA,QAAQ,EAAEC,SAAS,EAAEC,EAAE,EAAEC,MAAM,QAAQ,SAAQ;AAExD,SAASC,cAAc,QAAQ,UAAS;AAExC,SAASC,cAAc,QAAQ,sBAAqB;AAGpD,IAAIC;AAEJN,SAAS,sBAAsB;IAC7BC,UAAU;QACRK,SAAS,MAAMF,eAAe;YAC5BG,cAAc;gBACZC,eAAe;gBACfC,UAAU;gBACVC,SAAS;oBAAC;oBAAM;iBAAK;YACvB;QACF;IACF;IACAR,GAAG,uCAAuC;QACxC,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEC,OAAO;YAAOC,WAAW;QAAO;IACjE;IAEArB,GAAG,2CAA2C;QAC5C,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,MAAMO;YACNN,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEE,WAAW;QAAO;IACnD;IAEArB,GAAG,gFAAgF;QACjF,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEC,OAAO;QAAM;IAC9C;IAEA,kEAAkE;IAClEpB,GAAG,2CAA2C;QAC5C,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;oBACNU,QAAQ;gBACV;aACD;YACDT,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEC,OAAO;QAAM;IAC9C;AACF"}
1
+ {"version":3,"sources":["../../src/queries/buildSortParam.spec.ts"],"sourcesContent":["import type { Config, SanitizedConfig } from 'payload'\nimport { describe, beforeAll, it, expect } from 'vitest'\n\nimport { sanitizeConfig } from 'payload'\n\nimport { buildSortParam } from './buildSortParam.js'\nimport { MongooseAdapter } from '../index.js'\n\nlet config: SanitizedConfig\n\ndescribe('builds sort params', () => {\n beforeAll(async () => {\n config = sanitizeConfig({\n localization: {\n defaultLocale: 'en',\n fallback: true,\n locales: ['en', 'es'],\n },\n } as Config)\n })\n it('adds a fallback on non-unique field', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n },\n ],\n locale: 'en',\n sort: 'order',\n timestamps: true,\n adapter: {\n disableFallbackSort: false,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ order: 'asc', createdAt: 'desc' })\n })\n\n it('adds a fallback when sort isnt provided', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n },\n ],\n locale: 'en',\n sort: undefined,\n timestamps: true,\n adapter: {\n disableFallbackSort: false,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ createdAt: 'desc' })\n })\n\n it('does not add a fallback on non-unique field when disableFallbackSort is true', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n },\n ],\n locale: 'en',\n sort: 'order',\n timestamps: true,\n adapter: {\n disableFallbackSort: true,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ order: 'asc' })\n })\n\n // This test should be true even when disableFallbackSort is false\n it('does not add a fallback on unique field', () => {\n const result = buildSortParam({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n {\n name: 'order',\n type: 'number',\n unique: true, // Marking this field as unique\n },\n ],\n locale: 'en',\n sort: 'order',\n timestamps: true,\n adapter: {\n disableFallbackSort: false,\n } as MongooseAdapter,\n })\n\n expect(result).toStrictEqual({ order: 'asc' })\n })\n})\n"],"names":["describe","beforeAll","it","expect","sanitizeConfig","buildSortParam","config","localization","defaultLocale","fallback","locales","result","parentIsLocalized","fields","name","type","locale","sort","timestamps","adapter","disableFallbackSort","toStrictEqual","order","createdAt","undefined","unique"],"mappings":"AACA,SAASA,QAAQ,EAAEC,SAAS,EAAEC,EAAE,EAAEC,MAAM,QAAQ,SAAQ;AAExD,SAASC,cAAc,QAAQ,UAAS;AAExC,SAASC,cAAc,QAAQ,sBAAqB;AAGpD,IAAIC;AAEJN,SAAS,sBAAsB;IAC7BC,UAAU;QACRK,SAASF,eAAe;YACtBG,cAAc;gBACZC,eAAe;gBACfC,UAAU;gBACVC,SAAS;oBAAC;oBAAM;iBAAK;YACvB;QACF;IACF;IACAR,GAAG,uCAAuC;QACxC,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEC,OAAO;YAAOC,WAAW;QAAO;IACjE;IAEArB,GAAG,2CAA2C;QAC5C,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,MAAMO;YACNN,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEE,WAAW;QAAO;IACnD;IAEArB,GAAG,gFAAgF;QACjF,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEC,OAAO;QAAM;IAC9C;IAEA,kEAAkE;IAClEpB,GAAG,2CAA2C;QAC5C,MAAMS,SAASN,eAAe;YAC5BC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;gBACA;oBACED,MAAM;oBACNC,MAAM;oBACNU,QAAQ;gBACV;aACD;YACDT,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;gBACPC,qBAAqB;YACvB;QACF;QAEAjB,OAAOQ,QAAQU,aAAa,CAAC;YAAEC,OAAO;QAAM;IAC9C;AACF"}
@@ -4,7 +4,7 @@ import { getLocalizedSortProperty } from './getLocalizedSortProperty.js';
4
4
  let config;
5
5
  describe('get localized sort property', ()=>{
6
6
  beforeAll(async ()=>{
7
- config = await sanitizeConfig({
7
+ config = sanitizeConfig({
8
8
  localization: {
9
9
  defaultLocale: 'en',
10
10
  fallback: true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queries/getLocalizedSortProperty.spec.ts"],"sourcesContent":["import { describe, beforeAll, it, expect } from 'vitest'\nimport type { Config, SanitizedConfig } from 'payload'\nimport { flattenAllFields, sanitizeConfig } from 'payload'\n\nimport { getLocalizedSortProperty } from './getLocalizedSortProperty.js'\n\nlet config: SanitizedConfig\n\ndescribe('get localized sort property', () => {\n beforeAll(async () => {\n config = await sanitizeConfig({\n localization: {\n defaultLocale: 'en',\n fallback: true,\n locales: ['en', 'es'],\n },\n } as Config)\n })\n it('passes through a non-localized sort property', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n ],\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title')\n })\n\n it('properly localizes an un-localized sort property', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title.en')\n })\n\n it('keeps specifically asked-for localized sort properties', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n locale: 'en',\n segments: ['title', 'es'],\n })\n\n expect(result).toStrictEqual('title.es')\n })\n\n it('properly localizes nested sort properties', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n name: 'group',\n type: 'group',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['group', 'title'],\n })\n\n expect(result).toStrictEqual('group.title.en')\n })\n\n it('keeps requested locale with nested sort properties', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n name: 'group',\n type: 'group',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['group', 'title', 'es'],\n })\n\n expect(result).toStrictEqual('group.title.es')\n })\n\n it('properly localizes field within row', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title.en')\n })\n\n it('properly localizes field within named tab', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n name: 'tab',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['tab', 'title'],\n })\n\n expect(result).toStrictEqual('tab.title.en')\n })\n\n it('properly localizes field within unnamed tab', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n label: 'Tab',\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title.en')\n })\n})\n"],"names":["describe","beforeAll","it","expect","flattenAllFields","sanitizeConfig","getLocalizedSortProperty","config","localization","defaultLocale","fallback","locales","result","parentIsLocalized","fields","name","type","locale","segments","toStrictEqual","localized","tabs","label"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,SAAS,EAAEC,EAAE,EAAEC,MAAM,QAAQ,SAAQ;AAExD,SAASC,gBAAgB,EAAEC,cAAc,QAAQ,UAAS;AAE1D,SAASC,wBAAwB,QAAQ,gCAA+B;AAExE,IAAIC;AAEJP,SAAS,+BAA+B;IACtCC,UAAU;QACRM,SAAS,MAAMF,eAAe;YAC5BG,cAAc;gBACZC,eAAe;gBACfC,UAAU;gBACVC,SAAS;oBAAC;oBAAM;iBAAK;YACvB;QACF;IACF;IACAT,GAAG,gDAAgD;QACjD,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;gBACR;aACD;YACDC,QAAQ;YACRC,UAAU;gBAAC;aAAQ;QACrB;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,oDAAoD;QACrD,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;oBACNI,WAAW;gBACb;aACD;YACDH,QAAQ;YACRC,UAAU;gBAAC;aAAQ;QACrB;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,0DAA0D;QAC3D,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;oBACNI,WAAW;gBACb;aACD;YACDH,QAAQ;YACRC,UAAU;gBAAC;gBAAS;aAAK;QAC3B;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,6CAA6C;QAC9C,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQV,iBAAiB;gBACvBU,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNF,QAAQ;4BACN;gCACEC,MAAM;gCACNC,MAAM;gCACNI,WAAW;4BACb;yBACD;oBACH;iBACD;YACH;YACAH,QAAQ;YACRC,UAAU;gBAAC;gBAAS;aAAQ;QAC9B;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,sDAAsD;QACvD,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQV,iBAAiB;gBACvBU,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNF,QAAQ;4BACN;gCACEC,MAAM;gCACNC,MAAM;gCACNI,WAAW;4BACb;yBACD;oBACH;iBACD;YACH;YACAH,QAAQ;YACRC,UAAU;gBAAC;gBAAS;gBAAS;aAAK;QACpC;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,uCAAuC;QACxC,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQV,iBAAiB;gBACvBU,QAAQ;oBACN;wBACEE,MAAM;wBACNF,QAAQ;4BACN;gCACEC,MAAM;gCACNC,MAAM;gCACNI,WAAW;4BACb;yBACD;oBACH;iBACD;YACH;YACAH,QAAQ;YACRC,UAAU;gBAAC;aAAQ;QACrB;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,6CAA6C;QAC9C,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQV,iBAAiB;gBACvBU,QAAQ;oBACN;wBACEE,MAAM;wBACNK,MAAM;4BACJ;gCACEN,MAAM;gCACND,QAAQ;oCACN;wCACEC,MAAM;wCACNC,MAAM;wCACNI,WAAW;oCACb;iCACD;4BACH;yBACD;oBACH;iBACD;YACH;YACAH,QAAQ;YACRC,UAAU;gBAAC;gBAAO;aAAQ;QAC5B;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;IAEAjB,GAAG,+CAA+C;QAChD,MAAMU,SAASN,yBAAyB;YACtCC;YACAM,mBAAmB;YACnBC,QAAQV,iBAAiB;gBACvBU,QAAQ;oBACN;wBACEE,MAAM;wBACNK,MAAM;4BACJ;gCACEP,QAAQ;oCACN;wCACEC,MAAM;wCACNC,MAAM;wCACNI,WAAW;oCACb;iCACD;gCACDE,OAAO;4BACT;yBACD;oBACH;iBACD;YACH;YACAL,QAAQ;YACRC,UAAU;gBAAC;aAAQ;QACrB;QAEAf,OAAOS,QAAQO,aAAa,CAAC;IAC/B;AACF"}
1
+ {"version":3,"sources":["../../src/queries/getLocalizedSortProperty.spec.ts"],"sourcesContent":["import { describe, beforeAll, it, expect } from 'vitest'\nimport type { Config, SanitizedConfig } from 'payload'\nimport { flattenAllFields, sanitizeConfig } from 'payload'\n\nimport { getLocalizedSortProperty } from './getLocalizedSortProperty.js'\n\nlet config: SanitizedConfig\n\ndescribe('get localized sort property', () => {\n beforeAll(async () => {\n config = sanitizeConfig({\n localization: {\n defaultLocale: 'en',\n fallback: true,\n locales: ['en', 'es'],\n },\n } as Config)\n })\n it('passes through a non-localized sort property', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n },\n ],\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title')\n })\n\n it('properly localizes an un-localized sort property', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title.en')\n })\n\n it('keeps specifically asked-for localized sort properties', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n locale: 'en',\n segments: ['title', 'es'],\n })\n\n expect(result).toStrictEqual('title.es')\n })\n\n it('properly localizes nested sort properties', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n name: 'group',\n type: 'group',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['group', 'title'],\n })\n\n expect(result).toStrictEqual('group.title.en')\n })\n\n it('keeps requested locale with nested sort properties', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n name: 'group',\n type: 'group',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['group', 'title', 'es'],\n })\n\n expect(result).toStrictEqual('group.title.es')\n })\n\n it('properly localizes field within row', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title.en')\n })\n\n it('properly localizes field within named tab', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n name: 'tab',\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['tab', 'title'],\n })\n\n expect(result).toStrictEqual('tab.title.en')\n })\n\n it('properly localizes field within unnamed tab', () => {\n const result = getLocalizedSortProperty({\n config,\n parentIsLocalized: false,\n fields: flattenAllFields({\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n },\n ],\n label: 'Tab',\n },\n ],\n },\n ],\n }),\n locale: 'en',\n segments: ['title'],\n })\n\n expect(result).toStrictEqual('title.en')\n })\n})\n"],"names":["describe","beforeAll","it","expect","flattenAllFields","sanitizeConfig","getLocalizedSortProperty","config","localization","defaultLocale","fallback","locales","result","parentIsLocalized","fields","name","type","locale","segments","toStrictEqual","localized","tabs","label"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/queries/parseParams.ts"],"sourcesContent":["import type { FilterQuery } from 'mongoose'\nimport type { FlattenedField, Operator, Payload, Where } from 'payload'\n\nimport { deepMergeWithCombinedArrays } from 'payload'\nimport { validOperatorSet } from 'payload/shared'\n\nimport { buildAndOrConditions } from './buildAndOrConditions.js'\nimport { buildSearchParam } from './buildSearchParams.js'\n\nexport async function parseParams({\n collectionSlug,\n fields,\n globalSlug,\n locale,\n parentIsLocalized,\n payload,\n where,\n}: {\n collectionSlug?: string\n fields: FlattenedField[]\n globalSlug?: string\n locale?: string\n parentIsLocalized: boolean\n payload: Payload\n where: Where\n}): Promise<Record<string, unknown>> {\n let result = {} as FilterQuery<any>\n\n if (typeof where === 'object') {\n // We need to determine if the whereKey is an AND, OR, or a schema path\n for (const relationOrPath of Object.keys(where)) {\n const condition = where[relationOrPath]\n let conditionOperator: '$and' | '$or' | null = null\n if (relationOrPath.toLowerCase() === 'and') {\n conditionOperator = '$and'\n } else if (relationOrPath.toLowerCase() === 'or') {\n conditionOperator = '$or'\n }\n if (Array.isArray(condition)) {\n const builtConditions = await buildAndOrConditions({\n collectionSlug,\n fields,\n globalSlug,\n locale,\n parentIsLocalized,\n payload,\n where: condition,\n })\n if (builtConditions.length > 0 && conditionOperator !== null) {\n result[conditionOperator] = builtConditions\n }\n } else {\n // It's a path - and there can be multiple comparisons on a single path.\n // For example - title like 'test' and title not equal to 'tester'\n // So we need to loop on keys again here to handle each operator independently\n const pathOperators = where[relationOrPath]\n if (typeof pathOperators === 'object') {\n const validOperators: Operator[] = Object.keys(pathOperators).filter((operator) =>\n validOperatorSet.has(operator as Operator),\n ) as Operator[]\n\n for (const operator of validOperators) {\n const searchParam = await buildSearchParam({\n collectionSlug,\n fields,\n globalSlug,\n incomingPath: relationOrPath,\n locale,\n operator,\n parentIsLocalized,\n payload,\n val: (pathOperators as Record<string, Where>)[operator],\n })\n\n if (searchParam?.value && searchParam?.path) {\n if (validOperators.length > 1) {\n if (!result.$and) {\n result.$and = []\n }\n result.$and.push({\n [searchParam.path]: searchParam.value,\n })\n } else {\n if (result[searchParam.path]) {\n if (!result.$and) {\n result.$and = []\n }\n\n result.$and.push({ [searchParam.path]: result[searchParam.path] })\n result.$and.push({\n [searchParam.path]: searchParam.value,\n })\n delete result[searchParam.path]\n } else {\n result[searchParam.path] = searchParam.value\n }\n }\n } else if (typeof searchParam?.value === 'object') {\n result = deepMergeWithCombinedArrays(result, searchParam.value ?? {}, {\n // dont clone Types.ObjectIDs\n clone: false,\n })\n }\n }\n }\n }\n }\n }\n\n return result\n}\n"],"names":["deepMergeWithCombinedArrays","validOperatorSet","buildAndOrConditions","buildSearchParam","parseParams","collectionSlug","fields","globalSlug","locale","parentIsLocalized","payload","where","result","relationOrPath","Object","keys","condition","conditionOperator","toLowerCase","Array","isArray","builtConditions","length","pathOperators","validOperators","filter","operator","has","searchParam","incomingPath","val","value","path","$and","push","clone"],"mappings":"AAGA,SAASA,2BAA2B,QAAQ,UAAS;AACrD,SAASC,gBAAgB,QAAQ,iBAAgB;AAEjD,SAASC,oBAAoB,QAAQ,4BAA2B;AAChE,SAASC,gBAAgB,QAAQ,yBAAwB;AAEzD,OAAO,eAAeC,YAAY,EAChCC,cAAc,EACdC,MAAM,EACNC,UAAU,EACVC,MAAM,EACNC,iBAAiB,EACjBC,OAAO,EACPC,KAAK,EASN;IACC,IAAIC,SAAS,CAAC;IAEd,IAAI,OAAOD,UAAU,UAAU;QAC7B,uEAAuE;QACvE,KAAK,MAAME,kBAAkBC,OAAOC,IAAI,CAACJ,OAAQ;YAC/C,MAAMK,YAAYL,KAAK,CAACE,eAAe;YACvC,IAAII,oBAA2C;YAC/C,IAAIJ,eAAeK,WAAW,OAAO,OAAO;gBAC1CD,oBAAoB;YACtB,OAAO,IAAIJ,eAAeK,WAAW,OAAO,MAAM;gBAChDD,oBAAoB;YACtB;YACA,IAAIE,MAAMC,OAAO,CAACJ,YAAY;gBAC5B,MAAMK,kBAAkB,MAAMnB,qBAAqB;oBACjDG;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC,OAAOK;gBACT;gBACA,IAAIK,gBAAgBC,MAAM,GAAG,KAAKL,sBAAsB,MAAM;oBAC5DL,MAAM,CAACK,kBAAkB,GAAGI;gBAC9B;YACF,OAAO;gBACL,wEAAwE;gBACxE,kEAAkE;gBAClE,8EAA8E;gBAC9E,MAAME,gBAAgBZ,KAAK,CAACE,eAAe;gBAC3C,IAAI,OAAOU,kBAAkB,UAAU;oBACrC,MAAMC,iBAA6BV,OAAOC,IAAI,CAACQ,eAAeE,MAAM,CAAC,CAACC,WACpEzB,iBAAiB0B,GAAG,CAACD;oBAGvB,KAAK,MAAMA,YAAYF,eAAgB;wBACrC,MAAMI,cAAc,MAAMzB,iBAAiB;4BACzCE;4BACAC;4BACAC;4BACAsB,cAAchB;4BACdL;4BACAkB;4BACAjB;4BACAC;4BACAoB,KAAK,AAACP,aAAuC,CAACG,SAAS;wBACzD;wBAEA,IAAIE,aAAaG,SAASH,aAAaI,MAAM;4BAC3C,IAAIR,eAAeF,MAAM,GAAG,GAAG;gCAC7B,IAAI,CAACV,OAAOqB,IAAI,EAAE;oCAChBrB,OAAOqB,IAAI,GAAG,EAAE;gCAClB;gCACArB,OAAOqB,IAAI,CAACC,IAAI,CAAC;oCACf,CAACN,YAAYI,IAAI,CAAC,EAAEJ,YAAYG,KAAK;gCACvC;4BACF,OAAO;gCACL,IAAInB,MAAM,CAACgB,YAAYI,IAAI,CAAC,EAAE;oCAC5B,IAAI,CAACpB,OAAOqB,IAAI,EAAE;wCAChBrB,OAAOqB,IAAI,GAAG,EAAE;oCAClB;oCAEArB,OAAOqB,IAAI,CAACC,IAAI,CAAC;wCAAE,CAACN,YAAYI,IAAI,CAAC,EAAEpB,MAAM,CAACgB,YAAYI,IAAI,CAAC;oCAAC;oCAChEpB,OAAOqB,IAAI,CAACC,IAAI,CAAC;wCACf,CAACN,YAAYI,IAAI,CAAC,EAAEJ,YAAYG,KAAK;oCACvC;oCACA,OAAOnB,MAAM,CAACgB,YAAYI,IAAI,CAAC;gCACjC,OAAO;oCACLpB,MAAM,CAACgB,YAAYI,IAAI,CAAC,GAAGJ,YAAYG,KAAK;gCAC9C;4BACF;wBACF,OAAO,IAAI,OAAOH,aAAaG,UAAU,UAAU;4BACjDnB,SAASZ,4BAA4BY,QAAQgB,YAAYG,KAAK,IAAI,CAAC,GAAG;gCACpE,6BAA6B;gCAC7BI,OAAO;4BACT;wBACF;oBACF;gBACF;YACF;QACF;IACF;IAEA,OAAOvB;AACT"}
1
+ {"version":3,"sources":["../../src/queries/parseParams.ts"],"sourcesContent":["import type { QueryFilter } from 'mongoose'\nimport type { FlattenedField, Operator, Payload, Where } from 'payload'\n\nimport { deepMergeWithCombinedArrays } from 'payload'\nimport { validOperatorSet } from 'payload/shared'\n\nimport { buildAndOrConditions } from './buildAndOrConditions.js'\nimport { buildSearchParam } from './buildSearchParams.js'\n\nexport async function parseParams({\n collectionSlug,\n fields,\n globalSlug,\n locale,\n parentIsLocalized,\n payload,\n where,\n}: {\n collectionSlug?: string\n fields: FlattenedField[]\n globalSlug?: string\n locale?: string\n parentIsLocalized: boolean\n payload: Payload\n where: Where\n}): Promise<Record<string, unknown>> {\n let result = {} as QueryFilter<any>\n\n if (typeof where === 'object') {\n // We need to determine if the whereKey is an AND, OR, or a schema path\n for (const relationOrPath of Object.keys(where)) {\n const condition = where[relationOrPath]\n let conditionOperator: '$and' | '$or' | null = null\n if (relationOrPath.toLowerCase() === 'and') {\n conditionOperator = '$and'\n } else if (relationOrPath.toLowerCase() === 'or') {\n conditionOperator = '$or'\n }\n if (Array.isArray(condition)) {\n const builtConditions = await buildAndOrConditions({\n collectionSlug,\n fields,\n globalSlug,\n locale,\n parentIsLocalized,\n payload,\n where: condition,\n })\n if (builtConditions.length > 0 && conditionOperator !== null) {\n result[conditionOperator] = builtConditions\n }\n } else {\n // It's a path - and there can be multiple comparisons on a single path.\n // For example - title like 'test' and title not equal to 'tester'\n // So we need to loop on keys again here to handle each operator independently\n const pathOperators = where[relationOrPath]\n if (typeof pathOperators === 'object') {\n const validOperators: Operator[] = Object.keys(pathOperators).filter((operator) =>\n validOperatorSet.has(operator as Operator),\n ) as Operator[]\n\n for (const operator of validOperators) {\n const searchParam = await buildSearchParam({\n collectionSlug,\n fields,\n globalSlug,\n incomingPath: relationOrPath,\n locale,\n operator,\n parentIsLocalized,\n payload,\n val: (pathOperators as Record<string, Where>)[operator],\n })\n\n if (searchParam?.value && searchParam?.path) {\n if (validOperators.length > 1) {\n if (!result.$and) {\n result.$and = []\n }\n result.$and.push({\n [searchParam.path]: searchParam.value,\n })\n } else {\n if (result[searchParam.path]) {\n if (!result.$and) {\n result.$and = []\n }\n\n result.$and.push({ [searchParam.path]: result[searchParam.path] })\n result.$and.push({\n [searchParam.path]: searchParam.value,\n })\n delete result[searchParam.path]\n } else {\n result[searchParam.path] = searchParam.value\n }\n }\n } else if (typeof searchParam?.value === 'object') {\n result = deepMergeWithCombinedArrays(result, searchParam.value ?? {}, {\n // dont clone Types.ObjectIDs\n clone: false,\n })\n }\n }\n }\n }\n }\n }\n\n return result\n}\n"],"names":["deepMergeWithCombinedArrays","validOperatorSet","buildAndOrConditions","buildSearchParam","parseParams","collectionSlug","fields","globalSlug","locale","parentIsLocalized","payload","where","result","relationOrPath","Object","keys","condition","conditionOperator","toLowerCase","Array","isArray","builtConditions","length","pathOperators","validOperators","filter","operator","has","searchParam","incomingPath","val","value","path","$and","push","clone"],"mappings":"AAGA,SAASA,2BAA2B,QAAQ,UAAS;AACrD,SAASC,gBAAgB,QAAQ,iBAAgB;AAEjD,SAASC,oBAAoB,QAAQ,4BAA2B;AAChE,SAASC,gBAAgB,QAAQ,yBAAwB;AAEzD,OAAO,eAAeC,YAAY,EAChCC,cAAc,EACdC,MAAM,EACNC,UAAU,EACVC,MAAM,EACNC,iBAAiB,EACjBC,OAAO,EACPC,KAAK,EASN;IACC,IAAIC,SAAS,CAAC;IAEd,IAAI,OAAOD,UAAU,UAAU;QAC7B,uEAAuE;QACvE,KAAK,MAAME,kBAAkBC,OAAOC,IAAI,CAACJ,OAAQ;YAC/C,MAAMK,YAAYL,KAAK,CAACE,eAAe;YACvC,IAAII,oBAA2C;YAC/C,IAAIJ,eAAeK,WAAW,OAAO,OAAO;gBAC1CD,oBAAoB;YACtB,OAAO,IAAIJ,eAAeK,WAAW,OAAO,MAAM;gBAChDD,oBAAoB;YACtB;YACA,IAAIE,MAAMC,OAAO,CAACJ,YAAY;gBAC5B,MAAMK,kBAAkB,MAAMnB,qBAAqB;oBACjDG;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC,OAAOK;gBACT;gBACA,IAAIK,gBAAgBC,MAAM,GAAG,KAAKL,sBAAsB,MAAM;oBAC5DL,MAAM,CAACK,kBAAkB,GAAGI;gBAC9B;YACF,OAAO;gBACL,wEAAwE;gBACxE,kEAAkE;gBAClE,8EAA8E;gBAC9E,MAAME,gBAAgBZ,KAAK,CAACE,eAAe;gBAC3C,IAAI,OAAOU,kBAAkB,UAAU;oBACrC,MAAMC,iBAA6BV,OAAOC,IAAI,CAACQ,eAAeE,MAAM,CAAC,CAACC,WACpEzB,iBAAiB0B,GAAG,CAACD;oBAGvB,KAAK,MAAMA,YAAYF,eAAgB;wBACrC,MAAMI,cAAc,MAAMzB,iBAAiB;4BACzCE;4BACAC;4BACAC;4BACAsB,cAAchB;4BACdL;4BACAkB;4BACAjB;4BACAC;4BACAoB,KAAK,AAACP,aAAuC,CAACG,SAAS;wBACzD;wBAEA,IAAIE,aAAaG,SAASH,aAAaI,MAAM;4BAC3C,IAAIR,eAAeF,MAAM,GAAG,GAAG;gCAC7B,IAAI,CAACV,OAAOqB,IAAI,EAAE;oCAChBrB,OAAOqB,IAAI,GAAG,EAAE;gCAClB;gCACArB,OAAOqB,IAAI,CAACC,IAAI,CAAC;oCACf,CAACN,YAAYI,IAAI,CAAC,EAAEJ,YAAYG,KAAK;gCACvC;4BACF,OAAO;gCACL,IAAInB,MAAM,CAACgB,YAAYI,IAAI,CAAC,EAAE;oCAC5B,IAAI,CAACpB,OAAOqB,IAAI,EAAE;wCAChBrB,OAAOqB,IAAI,GAAG,EAAE;oCAClB;oCAEArB,OAAOqB,IAAI,CAACC,IAAI,CAAC;wCAAE,CAACN,YAAYI,IAAI,CAAC,EAAEpB,MAAM,CAACgB,YAAYI,IAAI,CAAC;oCAAC;oCAChEpB,OAAOqB,IAAI,CAACC,IAAI,CAAC;wCACf,CAACN,YAAYI,IAAI,CAAC,EAAEJ,YAAYG,KAAK;oCACvC;oCACA,OAAOnB,MAAM,CAACgB,YAAYI,IAAI,CAAC;gCACjC,OAAO;oCACLpB,MAAM,CAACgB,YAAYI,IAAI,CAAC,GAAGJ,YAAYG,KAAK;gCAC9C;4BACF;wBACF,OAAO,IAAI,OAAOH,aAAaG,UAAU,UAAU;4BACjDnB,SAASZ,4BAA4BY,QAAQgB,YAAYG,KAAK,IAAI,CAAC,GAAG;gCACpE,6BAA6B;gCAC7BI,OAAO;4BACT;wBACF;oBACF;gBACF;YACF;QACF;IACF;IAEA,OAAOvB;AACT"}
@@ -105,7 +105,7 @@ export const queryDrafts = async function queryDrafts({ collection: collectionSl
105
105
  query: versionQuery,
106
106
  versions: true
107
107
  });
108
- if (aggregate || sortAggregation.length > 0) {
108
+ if (aggregate.length > 0 || sortAggregation.length > 0) {
109
109
  result = await aggregatePaginate({
110
110
  adapter: this,
111
111
  collation: paginationOptions.collation,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/queryDrafts.ts"],"sourcesContent":["import type { PaginateOptions, PipelineStage, QueryOptions } from 'mongoose'\nimport type { QueryDrafts } from 'payload'\n\nimport { buildVersionCollectionFields, combineQueries, flattenWhereToOperators } from 'payload'\n\nimport type { MongooseAdapter } from './index.js'\n\nimport { buildQuery } from './queries/buildQuery.js'\nimport { buildSortParam } from './queries/buildSortParam.js'\nimport { aggregatePaginate } from './utilities/aggregatePaginate.js'\nimport { buildJoinAggregation } from './utilities/buildJoinAggregation.js'\nimport { buildProjectionFromSelect } from './utilities/buildProjectionFromSelect.js'\nimport { getCollection } from './utilities/getEntity.js'\nimport { getSession } from './utilities/getSession.js'\nimport { resolveJoins } from './utilities/resolveJoins.js'\nimport { transform } from './utilities/transform.js'\n\nexport const queryDrafts: QueryDrafts = async function queryDrafts(\n this: MongooseAdapter,\n {\n collection: collectionSlug,\n joins,\n limit,\n locale,\n page,\n pagination,\n req,\n select,\n sort: sortArg,\n where = {},\n },\n) {\n const { collectionConfig, Model } = getCollection({\n adapter: this,\n collectionSlug,\n versions: true,\n })\n\n let hasNearConstraint\n let sort\n\n if (where) {\n const constraints = flattenWhereToOperators(where)\n hasNearConstraint = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near'))\n }\n\n const fields = buildVersionCollectionFields(this.payload.config, collectionConfig, true)\n\n const sortAggregation: PipelineStage[] = []\n if (!hasNearConstraint) {\n sort = buildSortParam({\n adapter: this,\n config: this.payload.config,\n fields,\n locale,\n sort: sortArg || collectionConfig.defaultSort,\n sortAggregation,\n timestamps: true,\n versions: true,\n })\n }\n\n const combinedWhere = combineQueries({ latest: { equals: true } }, where)\n\n const versionQuery = await buildQuery({\n adapter: this,\n fields,\n locale,\n where: combinedWhere,\n })\n\n const projection = buildProjectionFromSelect({\n adapter: this,\n fields,\n select,\n })\n\n const session = await getSession(this, req)\n const options: QueryOptions = {\n session,\n }\n\n // useEstimatedCount is faster, but not accurate, as it ignores any filters. It is thus set to true if there are no filters.\n const useEstimatedCount =\n hasNearConstraint || !versionQuery || Object.keys(versionQuery).length === 0\n const paginationOptions: PaginateOptions = {\n lean: true,\n leanWithId: true,\n options,\n page,\n pagination,\n projection,\n sort,\n useEstimatedCount,\n }\n\n if (this.collation) {\n const localizationConfig = this.payload.config.localization\n const defaultLocale =\n (typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'\n\n paginationOptions.collation = {\n locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,\n ...this.collation,\n }\n }\n\n if (\n !useEstimatedCount &&\n Object.keys(versionQuery).length === 0 &&\n this.disableIndexHints !== true\n ) {\n // Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding\n // a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents,\n // which makes queries very slow. This only happens when no query (filter) is provided. If one is provided, it uses\n // the correct indexed field\n paginationOptions.useCustomCountFn = () => {\n return Promise.resolve(\n Model.countDocuments(versionQuery, {\n collation: paginationOptions.collation,\n hint: { _id: 1 },\n session,\n }),\n )\n }\n }\n\n if (limit && limit > 0) {\n paginationOptions.limit = limit\n // limit must also be set here, it's ignored when pagination is false\n\n paginationOptions.options!.limit = limit\n }\n\n let result\n\n const aggregate = await buildJoinAggregation({\n adapter: this,\n collection: collectionSlug,\n collectionConfig,\n joins,\n locale,\n projection,\n query: versionQuery,\n versions: true,\n })\n\n if (aggregate || sortAggregation.length > 0) {\n result = await aggregatePaginate({\n adapter: this,\n collation: paginationOptions.collation,\n joinAggregation: aggregate,\n limit: paginationOptions.limit,\n Model,\n page: paginationOptions.page,\n pagination: paginationOptions.pagination,\n projection: paginationOptions.projection,\n query: versionQuery,\n session: paginationOptions.options?.session ?? undefined,\n sort: paginationOptions.sort as object,\n sortAggregation,\n useEstimatedCount: paginationOptions.useEstimatedCount,\n })\n } else {\n result = await Model.paginate(versionQuery, paginationOptions)\n }\n\n if (!this.useJoinAggregations) {\n await resolveJoins({\n adapter: this,\n collectionSlug,\n docs: result.docs as Record<string, unknown>[],\n joins,\n locale,\n versions: true,\n })\n }\n\n transform({\n adapter: this,\n data: result.docs,\n fields: buildVersionCollectionFields(this.payload.config, collectionConfig),\n operation: 'read',\n })\n\n for (let i = 0; i < result.docs.length; i++) {\n const id = result.docs[i].parent\n result.docs[i] = result.docs[i].version ?? {}\n result.docs[i].id = id\n }\n\n return result\n}\n"],"names":["buildVersionCollectionFields","combineQueries","flattenWhereToOperators","buildQuery","buildSortParam","aggregatePaginate","buildJoinAggregation","buildProjectionFromSelect","getCollection","getSession","resolveJoins","transform","queryDrafts","collection","collectionSlug","joins","limit","locale","page","pagination","req","select","sort","sortArg","where","collectionConfig","Model","adapter","versions","hasNearConstraint","constraints","some","prop","Object","keys","key","fields","payload","config","sortAggregation","defaultSort","timestamps","combinedWhere","latest","equals","versionQuery","projection","session","options","useEstimatedCount","length","paginationOptions","lean","leanWithId","collation","localizationConfig","localization","defaultLocale","disableIndexHints","useCustomCountFn","Promise","resolve","countDocuments","hint","_id","result","aggregate","query","joinAggregation","undefined","paginate","useJoinAggregations","docs","data","operation","i","id","parent","version"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/queryDrafts.ts"],"sourcesContent":["import type { PaginateOptions, PipelineStage, QueryOptions } from 'mongoose'\nimport type { QueryDrafts } from 'payload'\n\nimport { buildVersionCollectionFields, combineQueries, flattenWhereToOperators } from 'payload'\n\nimport type { MongooseAdapter } from './index.js'\n\nimport { buildQuery } from './queries/buildQuery.js'\nimport { buildSortParam } from './queries/buildSortParam.js'\nimport { aggregatePaginate } from './utilities/aggregatePaginate.js'\nimport { buildJoinAggregation } from './utilities/buildJoinAggregation.js'\nimport { buildProjectionFromSelect } from './utilities/buildProjectionFromSelect.js'\nimport { getCollection } from './utilities/getEntity.js'\nimport { getSession } from './utilities/getSession.js'\nimport { resolveJoins } from './utilities/resolveJoins.js'\nimport { transform } from './utilities/transform.js'\n\nexport const queryDrafts: QueryDrafts = async function queryDrafts(\n this: MongooseAdapter,\n {\n collection: collectionSlug,\n joins,\n limit,\n locale,\n page,\n pagination,\n req,\n select,\n sort: sortArg,\n where = {},\n },\n) {\n const { collectionConfig, Model } = getCollection({\n adapter: this,\n collectionSlug,\n versions: true,\n })\n\n let hasNearConstraint\n let sort\n\n if (where) {\n const constraints = flattenWhereToOperators(where)\n hasNearConstraint = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near'))\n }\n\n const fields = buildVersionCollectionFields(this.payload.config, collectionConfig, true)\n\n const sortAggregation: PipelineStage[] = []\n if (!hasNearConstraint) {\n sort = buildSortParam({\n adapter: this,\n config: this.payload.config,\n fields,\n locale,\n sort: sortArg || collectionConfig.defaultSort,\n sortAggregation,\n timestamps: true,\n versions: true,\n })\n }\n\n const combinedWhere = combineQueries({ latest: { equals: true } }, where)\n\n const versionQuery = await buildQuery({\n adapter: this,\n fields,\n locale,\n where: combinedWhere,\n })\n\n const projection = buildProjectionFromSelect({\n adapter: this,\n fields,\n select,\n })\n\n const session = await getSession(this, req)\n const options: QueryOptions = {\n session,\n }\n\n // useEstimatedCount is faster, but not accurate, as it ignores any filters. It is thus set to true if there are no filters.\n const useEstimatedCount =\n hasNearConstraint || !versionQuery || Object.keys(versionQuery).length === 0\n const paginationOptions: PaginateOptions = {\n lean: true,\n leanWithId: true,\n options,\n page,\n pagination,\n projection,\n sort,\n useEstimatedCount,\n }\n\n if (this.collation) {\n const localizationConfig = this.payload.config.localization\n const defaultLocale =\n (typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'\n\n paginationOptions.collation = {\n locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,\n ...this.collation,\n }\n }\n\n if (\n !useEstimatedCount &&\n Object.keys(versionQuery).length === 0 &&\n this.disableIndexHints !== true\n ) {\n // Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding\n // a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents,\n // which makes queries very slow. This only happens when no query (filter) is provided. If one is provided, it uses\n // the correct indexed field\n paginationOptions.useCustomCountFn = () => {\n return Promise.resolve(\n Model.countDocuments(versionQuery, {\n collation: paginationOptions.collation,\n hint: { _id: 1 },\n session,\n }),\n )\n }\n }\n\n if (limit && limit > 0) {\n paginationOptions.limit = limit\n // limit must also be set here, it's ignored when pagination is false\n\n paginationOptions.options!.limit = limit\n }\n\n let result\n\n const aggregate = await buildJoinAggregation({\n adapter: this,\n collection: collectionSlug,\n collectionConfig,\n joins,\n locale,\n projection,\n query: versionQuery,\n versions: true,\n })\n\n if (aggregate.length > 0 || sortAggregation.length > 0) {\n result = await aggregatePaginate({\n adapter: this,\n collation: paginationOptions.collation,\n joinAggregation: aggregate,\n limit: paginationOptions.limit,\n Model,\n page: paginationOptions.page,\n pagination: paginationOptions.pagination,\n projection: paginationOptions.projection,\n query: versionQuery,\n session: paginationOptions.options?.session ?? undefined,\n sort: paginationOptions.sort as object,\n sortAggregation,\n useEstimatedCount: paginationOptions.useEstimatedCount,\n })\n } else {\n result = await Model.paginate(versionQuery, paginationOptions)\n }\n\n if (!this.useJoinAggregations) {\n await resolveJoins({\n adapter: this,\n collectionSlug,\n docs: result.docs as Record<string, unknown>[],\n joins,\n locale,\n versions: true,\n })\n }\n\n transform({\n adapter: this,\n data: result.docs,\n fields: buildVersionCollectionFields(this.payload.config, collectionConfig),\n operation: 'read',\n })\n\n for (let i = 0; i < result.docs.length; i++) {\n const id = result.docs[i].parent\n result.docs[i] = result.docs[i].version ?? {}\n result.docs[i].id = id\n }\n\n return result\n}\n"],"names":["buildVersionCollectionFields","combineQueries","flattenWhereToOperators","buildQuery","buildSortParam","aggregatePaginate","buildJoinAggregation","buildProjectionFromSelect","getCollection","getSession","resolveJoins","transform","queryDrafts","collection","collectionSlug","joins","limit","locale","page","pagination","req","select","sort","sortArg","where","collectionConfig","Model","adapter","versions","hasNearConstraint","constraints","some","prop","Object","keys","key","fields","payload","config","sortAggregation","defaultSort","timestamps","combinedWhere","latest","equals","versionQuery","projection","session","options","useEstimatedCount","length","paginationOptions","lean","leanWithId","collation","localizationConfig","localization","defaultLocale","disableIndexHints","useCustomCountFn","Promise","resolve","countDocuments","hint","_id","result","aggregate","query","joinAggregation","undefined","paginate","useJoinAggregations","docs","data","operation","i","id","parent","version"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"updateJobs.d.ts","sourceRoot":"","sources":["../src/updateJobs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAO,UAAU,EAAS,MAAM,SAAS,CAAA;AAWrD,eAAO,MAAM,UAAU,EAAE,UAiIxB,CAAA"}
1
+ {"version":3,"file":"updateJobs.d.ts","sourceRoot":"","sources":["../src/updateJobs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAO,UAAU,EAAS,MAAM,SAAS,CAAA;AAWrD,eAAO,MAAM,UAAU,EAAE,UAiLxB,CAAA"}
@@ -24,7 +24,7 @@ export const updateJobs = async function updateMany({ id, data, limit, req, retu
24
24
  sort: sortArg || collectionConfig.defaultSort,
25
25
  timestamps: true
26
26
  });
27
- let query = await buildQuery({
27
+ const query = await buildQuery({
28
28
  adapter: this,
29
29
  collectionSlug: collectionConfig.slug,
30
30
  fields: collectionConfig.flattenedFields,
@@ -90,25 +90,82 @@ export const updateJobs = async function updateMany({ id, data, limit, req, retu
90
90
  doc
91
91
  ] : [];
92
92
  }
93
- } else {
94
- if (typeof limit === 'number' && limit > 0) {
95
- const documentsToUpdate = await Model.find(query, {}, {
96
- ...findOptions,
97
- limit,
98
- projection: {
99
- _id: 1
93
+ } else if (limit === 1) {
94
+ /**
95
+ * Select, update, and return one job atomically in a single database call.
96
+ * We can only do this with limit === 1, which can be expressed as findOne.
97
+ */ const doc = await Model.findOneAndUpdate(query, updateData, {
98
+ ...findOptions,
99
+ projection: returning === false ? {
100
+ _id: 1
101
+ } : undefined,
102
+ sort
103
+ });
104
+ if (returning === false) {
105
+ return null;
106
+ }
107
+ result = doc ? [
108
+ doc
109
+ ] : [];
110
+ } else if (typeof limit === 'number' && limit > 1) {
111
+ const candidates = await Model.find(query, {}, {
112
+ ...findOptions,
113
+ limit,
114
+ projection: {
115
+ _id: 1
116
+ },
117
+ sort
118
+ });
119
+ if (candidates.length === 0) {
120
+ return null;
121
+ }
122
+ const candidateIDs = candidates.map((candidate)=>candidate._id);
123
+ if (typeof data.processingToken === 'string') {
124
+ /**
125
+ * `processingToken` identifies this claim update. `processing: true` cannot, because every
126
+ * worker writes the same value. The token lets us reliably find the jobs this update won.
127
+ */ const claimQuery = {
128
+ $and: [
129
+ query,
130
+ {
131
+ _id: {
132
+ $in: candidateIDs
133
+ }
134
+ }
135
+ ]
136
+ };
137
+ await Model.updateMany(claimQuery, updateData, baseOptions);
138
+ if (returning === false) {
139
+ return null;
140
+ }
141
+ const claimedJobsQuery = {
142
+ _id: {
143
+ $in: candidateIDs
100
144
  },
145
+ processingToken: {
146
+ $eq: data.processingToken
147
+ }
148
+ };
149
+ result = await Model.find(claimedJobsQuery, {}, {
150
+ ...findOptions,
101
151
  sort
102
152
  });
103
- if (documentsToUpdate.length === 0) {
104
- return null;
105
- }
106
- query = {
153
+ } else {
154
+ const limitedUpdateQuery = {
107
155
  _id: {
108
- $in: documentsToUpdate.map((doc)=>doc._id)
156
+ $in: candidateIDs
109
157
  }
110
158
  };
159
+ await Model.updateMany(limitedUpdateQuery, updateData, baseOptions);
160
+ if (returning === false) {
161
+ return null;
162
+ }
163
+ result = await Model.find(limitedUpdateQuery, {}, {
164
+ ...findOptions,
165
+ sort
166
+ });
111
167
  }
168
+ } else {
112
169
  await Model.updateMany(query, updateData, baseOptions);
113
170
  if (returning === false) {
114
171
  return null;