@payloadcms/db-mongodb 4.0.0-internal.b8e7c89 → 4.0.0-internal.bf4bcce

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 (66) hide show
  1. package/dist/connect.d.ts.map +1 -1
  2. package/dist/connect.js +8 -2
  3. package/dist/connect.js.map +1 -1
  4. package/dist/exports/migration-utils.d.ts +1 -0
  5. package/dist/exports/migration-utils.d.ts.map +1 -1
  6. package/dist/exports/migration-utils.js +1 -0
  7. package/dist/exports/migration-utils.js.map +1 -1
  8. package/dist/findDistinct.d.ts.map +1 -1
  9. package/dist/findDistinct.js +52 -8
  10. package/dist/findDistinct.js.map +1 -1
  11. package/dist/init.d.ts.map +1 -1
  12. package/dist/init.js +89 -67
  13. package/dist/init.js.map +1 -1
  14. package/dist/migrateFresh.d.ts.map +1 -1
  15. package/dist/migrateFresh.js +1 -0
  16. package/dist/migrateFresh.js.map +1 -1
  17. package/dist/models/buildCollectionSchema.d.ts +8 -2
  18. package/dist/models/buildCollectionSchema.d.ts.map +1 -1
  19. package/dist/models/buildCollectionSchema.js +4 -2
  20. package/dist/models/buildCollectionSchema.js.map +1 -1
  21. package/dist/models/buildGlobalModel.d.ts +5 -1
  22. package/dist/models/buildGlobalModel.d.ts.map +1 -1
  23. package/dist/models/buildGlobalModel.js +4 -2
  24. package/dist/models/buildGlobalModel.js.map +1 -1
  25. package/dist/models/buildSchema.d.ts +4 -0
  26. package/dist/models/buildSchema.d.ts.map +1 -1
  27. package/dist/models/buildSchema.js +64 -26
  28. package/dist/models/buildSchema.js.map +1 -1
  29. package/dist/models/schemaBuildContext.d.ts +21 -0
  30. package/dist/models/schemaBuildContext.d.ts.map +1 -0
  31. package/dist/models/schemaBuildContext.js +29 -0
  32. package/dist/models/schemaBuildContext.js.map +1 -0
  33. package/dist/predefinedMigrations/migrateSizesToVariants.d.ts +13 -0
  34. package/dist/predefinedMigrations/migrateSizesToVariants.d.ts.map +1 -0
  35. package/dist/predefinedMigrations/migrateSizesToVariants.js +368 -0
  36. package/dist/predefinedMigrations/migrateSizesToVariants.js.map +1 -0
  37. package/dist/predefinedMigrations/sizes-to-variants.d.ts +5 -0
  38. package/dist/predefinedMigrations/sizes-to-variants.d.ts.map +1 -0
  39. package/dist/predefinedMigrations/sizes-to-variants.js +8 -0
  40. package/dist/predefinedMigrations/sizes-to-variants.js.map +1 -0
  41. package/dist/queries/buildSearchParams.d.ts.map +1 -1
  42. package/dist/queries/buildSearchParams.js +50 -0
  43. package/dist/queries/buildSearchParams.js.map +1 -1
  44. package/dist/updateGlobal.js +2 -2
  45. package/dist/updateGlobal.js.map +1 -1
  46. package/dist/updateGlobalVersion.js +2 -2
  47. package/dist/updateGlobalVersion.js.map +1 -1
  48. package/dist/updateJobs.js +1 -1
  49. package/dist/updateJobs.js.map +1 -1
  50. package/dist/updateMany.d.ts.map +1 -1
  51. package/dist/updateMany.js +0 -1
  52. package/dist/updateMany.js.map +1 -1
  53. package/dist/updateOne.js +2 -2
  54. package/dist/updateOne.js.map +1 -1
  55. package/dist/updateVersion.js +2 -2
  56. package/dist/updateVersion.js.map +1 -1
  57. package/dist/utilities/aggregatePaginate.d.ts.map +1 -1
  58. package/dist/utilities/aggregatePaginate.js +3 -1
  59. package/dist/utilities/aggregatePaginate.js.map +1 -1
  60. package/package.json +3 -3
  61. package/dist/queries/buildSortParam.spec.js +0 -123
  62. package/dist/queries/buildSortParam.spec.js.map +0 -1
  63. package/dist/queries/getLocalizedSortProperty.spec.js +0 -215
  64. package/dist/queries/getLocalizedSortProperty.spec.js.map +0 -1
  65. package/dist/utilities/transform.spec.js +0 -546
  66. package/dist/utilities/transform.spec.js.map +0 -1
@@ -0,0 +1,368 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { getSession } from '../utilities/getSession.js';
3
+ /** Mongo error codes for an index that conflicts with an existing index. */ const INDEX_CONFLICT_CODES = new Set([
4
+ 85,
5
+ 86
6
+ ]);
7
+ /** Mongo error code for a collection that hasn't been created yet. */ const NAMESPACE_NOT_FOUND_CODE = 26;
8
+ const GENERATED_VARIANT_METADATA_FIELDS = new Set([
9
+ 'filename',
10
+ 'filesize',
11
+ 'height',
12
+ 'mimeType',
13
+ 'url',
14
+ 'width'
15
+ ]);
16
+ /**
17
+ * Moves every upload collection's stored image sizes between the legacy `sizes` field and
18
+ * `variants`, on each collection and its versions collection (`version.sizes`). Uses `$rename`,
19
+ * so no document is rewritten beyond the renamed key, and re-keys the indexes on those fields.
20
+ * Documents that are already renamed are left as they are, so it's safe to re-run.
21
+ */ export async function migrateSizesToVariants({ direction = 'up', payload, req }) {
22
+ const adapter = payload.db;
23
+ const session = await getSession(adapter, req);
24
+ const [from, to] = direction === 'up' ? [
25
+ 'sizes',
26
+ 'variants'
27
+ ] : [
28
+ 'variants',
29
+ 'sizes'
30
+ ];
31
+ const targets = [];
32
+ for (const collection of payload.config.collections){
33
+ if (!collection.upload) {
34
+ continue;
35
+ }
36
+ const upload = typeof collection.upload === 'object' ? collection.upload : undefined;
37
+ const expectedVariantNames = (upload?.variants ?? []).map(({ name })=>name);
38
+ targets.push({
39
+ collection: adapter.collections[collection.slug].collection,
40
+ expectedVariantNames,
41
+ fromPath: from,
42
+ toPath: to
43
+ });
44
+ if (collection.versions && adapter.versions[collection.slug]) {
45
+ targets.push({
46
+ collection: adapter.versions[collection.slug].collection,
47
+ expectedVariantNames,
48
+ fromPath: `version.${from}`,
49
+ toPath: `version.${to}`
50
+ });
51
+ }
52
+ }
53
+ for (const { collection, expectedVariantNames, fromPath, toPath } of targets){
54
+ const [sourceData, directCollision] = await Promise.all([
55
+ collection.findOne({
56
+ [fromPath]: {
57
+ $exists: true
58
+ }
59
+ }, {
60
+ projection: {
61
+ _id: 1
62
+ }
63
+ }),
64
+ collection.findOne({
65
+ [fromPath]: {
66
+ $exists: true
67
+ },
68
+ [toPath]: {
69
+ $exists: true
70
+ }
71
+ }, {
72
+ projection: {
73
+ _id: 1
74
+ }
75
+ })
76
+ ]);
77
+ if (sourceData && (directCollision || await findUnexpectedDestinationData({
78
+ collection,
79
+ expectedVariantNames,
80
+ toPath
81
+ }))) {
82
+ throw new Error(`Cannot run the sizes-to-variants migration because collection "${collection.collectionName}" contains both "${fromPath}" and "${toPath}" data. Move or rename the existing destination data before running this migration.`);
83
+ }
84
+ }
85
+ // Index changes can't be part of a multi-document transaction, and one made after the
86
+ // migration's transaction has written to a collection aborts it. A transaction's snapshot starts
87
+ // at its first operation, so re-keying every index before any transactional write is safe.
88
+ for (const target of targets){
89
+ await rekeyIndexes(target);
90
+ }
91
+ for (const { collection, fromPath, toPath } of targets){
92
+ const result = await collection.updateMany({
93
+ [fromPath]: {
94
+ $exists: true
95
+ },
96
+ [toPath]: {
97
+ $exists: false
98
+ }
99
+ }, {
100
+ $rename: {
101
+ [fromPath]: toPath
102
+ }
103
+ }, {
104
+ session
105
+ });
106
+ payload.logger.info({
107
+ msg: `sizes-to-variants (${direction}): renamed ${fromPath} on ${result.modifiedCount} document(s) in "${collection.collectionName}"`
108
+ });
109
+ }
110
+ }
111
+ async function findUnexpectedDestinationData({ collection, expectedVariantNames, toPath }) {
112
+ const expectedVariantNameSet = new Set(expectedVariantNames);
113
+ const cursor = collection.find({
114
+ [toPath]: {
115
+ $exists: true
116
+ }
117
+ }, {
118
+ projection: {
119
+ _id: 1,
120
+ [toPath]: 1
121
+ }
122
+ });
123
+ try {
124
+ for await (const document of cursor){
125
+ const destinationData = getDocumentPath({
126
+ document,
127
+ path: toPath
128
+ });
129
+ if (hasUnexpectedVariantData({
130
+ destinationData,
131
+ expectedVariantNameSet
132
+ })) {
133
+ return document;
134
+ }
135
+ }
136
+ } finally{
137
+ await cursor.close();
138
+ }
139
+ return null;
140
+ }
141
+ function getDocumentPath({ document, path }) {
142
+ return path.split('.').reduce((value, pathSegment)=>{
143
+ if (!isRecord(value)) {
144
+ return undefined;
145
+ }
146
+ return value[pathSegment];
147
+ }, document);
148
+ }
149
+ function hasUnexpectedVariantData({ destinationData, expectedVariantNameSet }) {
150
+ if (!isRecord(destinationData)) {
151
+ return destinationData !== null && destinationData !== undefined;
152
+ }
153
+ for (const [variantName, variantData] of Object.entries(destinationData)){
154
+ if (!expectedVariantNameSet.has(variantName)) {
155
+ return true;
156
+ }
157
+ if (variantData === null || variantData === undefined) {
158
+ continue;
159
+ }
160
+ if (!isRecord(variantData) || Object.keys(variantData).some((metadataFieldName)=>!GENERATED_VARIANT_METADATA_FIELDS.has(metadataFieldName))) {
161
+ return true;
162
+ }
163
+ }
164
+ return false;
165
+ }
166
+ function isRecord(value) {
167
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
168
+ }
169
+ async function rekeyIndexes({ collection, fromPath, toPath }) {
170
+ let indexes;
171
+ try {
172
+ indexes = await collection.indexes();
173
+ } catch (err) {
174
+ if (err.code === NAMESPACE_NOT_FOUND_CODE) {
175
+ return;
176
+ }
177
+ throw err;
178
+ }
179
+ for (const index of indexes){
180
+ const sourceKeys = getIndexKeysForCreate({
181
+ fromPath,
182
+ index,
183
+ toPath: fromPath
184
+ });
185
+ if (!Object.keys(sourceKeys).some((key)=>isPathAtOrBelow({
186
+ key,
187
+ path: fromPath
188
+ }))) {
189
+ continue;
190
+ }
191
+ const rekeyedKeys = getIndexKeysForCreate({
192
+ fromPath,
193
+ index,
194
+ toPath
195
+ });
196
+ const destinationOptions = getDestinationIndexOptions({
197
+ fromPath,
198
+ index,
199
+ toPath
200
+ });
201
+ if (index.weights && '_fts' in index.key && '_ftsx' in index.key) {
202
+ await rekeyTextIndex({
203
+ collection,
204
+ destinationOptions,
205
+ index,
206
+ rekeyedKeys,
207
+ sourceKeys
208
+ });
209
+ continue;
210
+ }
211
+ try {
212
+ await collection.createIndex(rekeyedKeys, destinationOptions);
213
+ } catch (err) {
214
+ if (!INDEX_CONFLICT_CODES.has(err.code ?? 0)) {
215
+ throw err;
216
+ }
217
+ const destinationIndex = (await collection.indexes()).find((candidate)=>isDeepStrictEqual(getIndexKeysForCreate({
218
+ fromPath: toPath,
219
+ index: candidate,
220
+ toPath
221
+ }), rekeyedKeys));
222
+ const existingDestinationOptions = destinationIndex ? getDestinationIndexOptions({
223
+ fromPath: toPath,
224
+ index: destinationIndex,
225
+ toPath
226
+ }) : undefined;
227
+ if (!destinationIndex || !isDeepStrictEqual(existingDestinationOptions, destinationOptions)) {
228
+ throw err;
229
+ }
230
+ }
231
+ await collection.dropIndex(index.name);
232
+ }
233
+ }
234
+ async function rekeyTextIndex({ collection, destinationOptions, index, rekeyedKeys, sourceKeys }) {
235
+ if (!index.name) {
236
+ throw new Error('Cannot re-key an unnamed MongoDB text index.');
237
+ }
238
+ const sourceOptions = {
239
+ ...getDestinationIndexOptions({
240
+ fromPath: '',
241
+ index,
242
+ toPath: ''
243
+ }),
244
+ name: index.name
245
+ };
246
+ await collection.dropIndex(index.name);
247
+ try {
248
+ await collection.createIndex(rekeyedKeys, destinationOptions);
249
+ } catch (err) {
250
+ try {
251
+ await collection.createIndex(sourceKeys, sourceOptions);
252
+ } catch (restoreErr) {
253
+ throw new AggregateError([
254
+ err,
255
+ restoreErr
256
+ ], `Failed to create the replacement for MongoDB text index "${index.name}" and failed to restore the source index.`);
257
+ }
258
+ throw err;
259
+ }
260
+ }
261
+ function getIndexKeysForCreate({ fromPath, index, toPath }) {
262
+ const keys = [];
263
+ const hasInternalTextKeys = '_fts' in index.key && '_ftsx' in index.key;
264
+ for (const [key, value] of Object.entries(index.key)){
265
+ if (hasInternalTextKeys && key === '_fts') {
266
+ for (const textPath of Object.keys(index.weights ?? {})){
267
+ keys.push([
268
+ rekeyPath({
269
+ fromPath,
270
+ path: textPath,
271
+ toPath
272
+ }),
273
+ 'text'
274
+ ]);
275
+ }
276
+ continue;
277
+ }
278
+ if (hasInternalTextKeys && key === '_ftsx') {
279
+ continue;
280
+ }
281
+ keys.push([
282
+ rekeyPath({
283
+ fromPath,
284
+ path: key,
285
+ toPath
286
+ }),
287
+ value
288
+ ]);
289
+ }
290
+ return Object.fromEntries(keys);
291
+ }
292
+ function getDestinationIndexOptions({ fromPath, index, toPath }) {
293
+ const options = {
294
+ '2dsphereIndexVersion': index['2dsphereIndexVersion'],
295
+ background: index.background,
296
+ bits: index.bits,
297
+ bucketSize: index.bucketSize,
298
+ collation: index.collation,
299
+ default_language: index.default_language,
300
+ expireAfterSeconds: index.expireAfterSeconds,
301
+ hidden: index.hidden,
302
+ language_override: index.language_override,
303
+ max: index.max,
304
+ min: index.min,
305
+ partialFilterExpression: index.partialFilterExpression ? rekeyDocumentPaths({
306
+ document: index.partialFilterExpression,
307
+ fromPath,
308
+ toPath
309
+ }) : undefined,
310
+ sparse: index.sparse,
311
+ storageEngine: index.storageEngine,
312
+ textIndexVersion: index.textIndexVersion,
313
+ unique: index.unique,
314
+ weights: index.weights ? rekeyDocumentPaths({
315
+ document: index.weights,
316
+ fromPath,
317
+ toPath
318
+ }) : undefined,
319
+ wildcardProjection: index.wildcardProjection ? rekeyDocumentPaths({
320
+ document: index.wildcardProjection,
321
+ fromPath,
322
+ toPath
323
+ }) : undefined
324
+ };
325
+ return Object.fromEntries(Object.entries(options).filter(([, value])=>value !== undefined));
326
+ }
327
+ function rekeyDocumentPaths({ document, fromPath, toPath }) {
328
+ return Object.fromEntries(Object.entries(document).map(([key, value])=>[
329
+ rekeyPath({
330
+ fromPath,
331
+ path: key,
332
+ toPath
333
+ }),
334
+ rekeyDocumentValue({
335
+ fromPath,
336
+ toPath,
337
+ value
338
+ })
339
+ ]));
340
+ }
341
+ function isPathAtOrBelow({ key, path }) {
342
+ return key === path || key.startsWith(`${path}.`);
343
+ }
344
+ function rekeyPath({ fromPath, path, toPath }) {
345
+ return isPathAtOrBelow({
346
+ key: path,
347
+ path: fromPath
348
+ }) ? `${toPath}${path.slice(fromPath.length)}` : path;
349
+ }
350
+ function rekeyDocumentValue({ fromPath, toPath, value }) {
351
+ if (Array.isArray(value)) {
352
+ return value.map((item)=>rekeyDocumentValue({
353
+ fromPath,
354
+ toPath,
355
+ value: item
356
+ }));
357
+ }
358
+ if (value !== null && typeof value === 'object' && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) {
359
+ return rekeyDocumentPaths({
360
+ document: value,
361
+ fromPath,
362
+ toPath
363
+ });
364
+ }
365
+ return value;
366
+ }
367
+
368
+ //# sourceMappingURL=migrateSizesToVariants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/predefinedMigrations/migrateSizesToVariants.ts"],"sourcesContent":["import type {\n Collection,\n CreateIndexesOptions,\n Document,\n IndexDescriptionInfo,\n IndexDirection,\n} from 'mongodb'\nimport type { Payload, PayloadRequest } from 'payload'\n\nimport { isDeepStrictEqual } from 'node:util'\n\nimport type { MongooseAdapter } from '../index.js'\n\nimport { getSession } from '../utilities/getSession.js'\n\n/** Mongo error codes for an index that conflicts with an existing index. */\nconst INDEX_CONFLICT_CODES = new Set([85, 86])\n/** Mongo error code for a collection that hasn't been created yet. */\nconst NAMESPACE_NOT_FOUND_CODE = 26\nconst GENERATED_VARIANT_METADATA_FIELDS = new Set([\n 'filename',\n 'filesize',\n 'height',\n 'mimeType',\n 'url',\n 'width',\n])\n\n/**\n * Moves every upload collection's stored image sizes between the legacy `sizes` field and\n * `variants`, on each collection and its versions collection (`version.sizes`). Uses `$rename`,\n * so no document is rewritten beyond the renamed key, and re-keys the indexes on those fields.\n * Documents that are already renamed are left as they are, so it's safe to re-run.\n */\nexport async function migrateSizesToVariants({\n direction = 'up',\n payload,\n req,\n}: {\n direction?: 'down' | 'up'\n payload: Payload\n req?: Partial<PayloadRequest>\n}): Promise<void> {\n const adapter = payload.db as unknown as MongooseAdapter\n const session = await getSession(adapter, req)\n const [from, to] = direction === 'up' ? ['sizes', 'variants'] : ['variants', 'sizes']\n\n const targets: {\n collection: Collection\n expectedVariantNames: string[]\n fromPath: string\n toPath: string\n }[] = []\n\n for (const collection of payload.config.collections) {\n if (!collection.upload) {\n continue\n }\n\n const upload = typeof collection.upload === 'object' ? collection.upload : undefined\n const expectedVariantNames = (upload?.variants ?? []).map(({ name }) => name)\n\n targets.push({\n collection: adapter.collections[collection.slug]!.collection,\n expectedVariantNames,\n fromPath: from,\n toPath: to,\n })\n\n if (collection.versions && adapter.versions[collection.slug]) {\n targets.push({\n collection: adapter.versions[collection.slug]!.collection,\n expectedVariantNames,\n fromPath: `version.${from}`,\n toPath: `version.${to}`,\n })\n }\n }\n\n for (const { collection, expectedVariantNames, fromPath, toPath } of targets) {\n const [sourceData, directCollision] = await Promise.all([\n collection.findOne({ [fromPath]: { $exists: true } }, { projection: { _id: 1 } }),\n collection.findOne(\n { [fromPath]: { $exists: true }, [toPath]: { $exists: true } },\n { projection: { _id: 1 } },\n ),\n ])\n\n if (\n sourceData &&\n (directCollision ||\n (await findUnexpectedDestinationData({ collection, expectedVariantNames, toPath })))\n ) {\n throw new Error(\n `Cannot run the sizes-to-variants migration because collection \"${collection.collectionName}\" contains both \"${fromPath}\" and \"${toPath}\" data. Move or rename the existing destination data before running this migration.`,\n )\n }\n }\n\n // Index changes can't be part of a multi-document transaction, and one made after the\n // migration's transaction has written to a collection aborts it. A transaction's snapshot starts\n // at its first operation, so re-keying every index before any transactional write is safe.\n for (const target of targets) {\n await rekeyIndexes(target)\n }\n\n for (const { collection, fromPath, toPath } of targets) {\n const result = await collection.updateMany(\n { [fromPath]: { $exists: true }, [toPath]: { $exists: false } },\n { $rename: { [fromPath]: toPath } },\n { session },\n )\n\n payload.logger.info({\n msg: `sizes-to-variants (${direction}): renamed ${fromPath} on ${result.modifiedCount} document(s) in \"${collection.collectionName}\"`,\n })\n }\n}\n\nasync function findUnexpectedDestinationData({\n collection,\n expectedVariantNames,\n toPath,\n}: {\n collection: Collection\n expectedVariantNames: string[]\n toPath: string\n}): Promise<Document | null> {\n const expectedVariantNameSet = new Set(expectedVariantNames)\n const cursor = collection.find(\n { [toPath]: { $exists: true } },\n { projection: { _id: 1, [toPath]: 1 } },\n )\n\n try {\n for await (const document of cursor) {\n const destinationData = getDocumentPath({ document, path: toPath })\n\n if (hasUnexpectedVariantData({ destinationData, expectedVariantNameSet })) {\n return document\n }\n }\n } finally {\n await cursor.close()\n }\n\n return null\n}\n\nfunction getDocumentPath({ document, path }: { document: Document; path: string }): unknown {\n return path.split('.').reduce<unknown>((value, pathSegment) => {\n if (!isRecord(value)) {\n return undefined\n }\n\n return value[pathSegment]\n }, document)\n}\n\nfunction hasUnexpectedVariantData({\n destinationData,\n expectedVariantNameSet,\n}: {\n destinationData: unknown\n expectedVariantNameSet: Set<string>\n}): boolean {\n if (!isRecord(destinationData)) {\n return destinationData !== null && destinationData !== undefined\n }\n\n for (const [variantName, variantData] of Object.entries(destinationData)) {\n if (!expectedVariantNameSet.has(variantName)) {\n return true\n }\n\n if (variantData === null || variantData === undefined) {\n continue\n }\n\n if (\n !isRecord(variantData) ||\n Object.keys(variantData).some(\n (metadataFieldName) => !GENERATED_VARIANT_METADATA_FIELDS.has(metadataFieldName),\n )\n ) {\n return true\n }\n }\n\n return false\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nasync function rekeyIndexes({\n collection,\n fromPath,\n toPath,\n}: {\n collection: Collection\n fromPath: string\n toPath: string\n}): Promise<void> {\n let indexes: IndexDescriptionInfo[]\n\n try {\n indexes = await collection.indexes()\n } catch (err) {\n if ((err as { code?: number }).code === NAMESPACE_NOT_FOUND_CODE) {\n return\n }\n\n throw err\n }\n\n for (const index of indexes) {\n const sourceKeys = getIndexKeysForCreate({ fromPath, index, toPath: fromPath })\n\n if (!Object.keys(sourceKeys).some((key) => isPathAtOrBelow({ key, path: fromPath }))) {\n continue\n }\n\n const rekeyedKeys = getIndexKeysForCreate({ fromPath, index, toPath })\n const destinationOptions = getDestinationIndexOptions({ fromPath, index, toPath })\n\n if (index.weights && '_fts' in index.key && '_ftsx' in index.key) {\n await rekeyTextIndex({\n collection,\n destinationOptions,\n index,\n rekeyedKeys,\n sourceKeys,\n })\n continue\n }\n\n try {\n await collection.createIndex(rekeyedKeys, destinationOptions)\n } catch (err) {\n if (!INDEX_CONFLICT_CODES.has((err as { code?: number }).code ?? 0)) {\n throw err\n }\n\n const destinationIndex = (await collection.indexes()).find((candidate) =>\n isDeepStrictEqual(\n getIndexKeysForCreate({ fromPath: toPath, index: candidate, toPath }),\n rekeyedKeys,\n ),\n )\n const existingDestinationOptions = destinationIndex\n ? getDestinationIndexOptions({\n fromPath: toPath,\n index: destinationIndex,\n toPath,\n })\n : undefined\n\n if (!destinationIndex || !isDeepStrictEqual(existingDestinationOptions, destinationOptions)) {\n throw err\n }\n }\n\n await collection.dropIndex(index.name!)\n }\n}\n\nasync function rekeyTextIndex({\n collection,\n destinationOptions,\n index,\n rekeyedKeys,\n sourceKeys,\n}: {\n collection: Collection\n destinationOptions: CreateIndexesOptions\n index: IndexDescriptionInfo\n rekeyedKeys: Record<string, IndexDirection>\n sourceKeys: Record<string, IndexDirection>\n}): Promise<void> {\n if (!index.name) {\n throw new Error('Cannot re-key an unnamed MongoDB text index.')\n }\n\n const sourceOptions: CreateIndexesOptions = {\n ...getDestinationIndexOptions({ fromPath: '', index, toPath: '' }),\n name: index.name,\n }\n\n await collection.dropIndex(index.name)\n\n try {\n await collection.createIndex(rekeyedKeys, destinationOptions)\n } catch (err) {\n try {\n await collection.createIndex(sourceKeys, sourceOptions)\n } catch (restoreErr) {\n throw new AggregateError(\n [err, restoreErr],\n `Failed to create the replacement for MongoDB text index \"${index.name}\" and failed to restore the source index.`,\n )\n }\n\n throw err\n }\n}\n\nfunction getIndexKeysForCreate({\n fromPath,\n index,\n toPath,\n}: {\n fromPath: string\n index: IndexDescriptionInfo\n toPath: string\n}): Record<string, IndexDirection> {\n const keys: [string, IndexDirection][] = []\n const hasInternalTextKeys = '_fts' in index.key && '_ftsx' in index.key\n\n for (const [key, value] of Object.entries(index.key)) {\n if (hasInternalTextKeys && key === '_fts') {\n for (const textPath of Object.keys(index.weights ?? {})) {\n keys.push([rekeyPath({ fromPath, path: textPath, toPath }), 'text'])\n }\n continue\n }\n\n if (hasInternalTextKeys && key === '_ftsx') {\n continue\n }\n\n keys.push([rekeyPath({ fromPath, path: key, toPath }), value])\n }\n\n return Object.fromEntries(keys)\n}\n\nfunction getDestinationIndexOptions({\n fromPath,\n index,\n toPath,\n}: {\n fromPath: string\n index: IndexDescriptionInfo\n toPath: string\n}): CreateIndexesOptions {\n const options: CreateIndexesOptions = {\n '2dsphereIndexVersion': index['2dsphereIndexVersion'],\n background: index.background,\n bits: index.bits,\n bucketSize: index.bucketSize,\n collation: index.collation,\n default_language: index.default_language,\n expireAfterSeconds: index.expireAfterSeconds,\n hidden: index.hidden,\n language_override: index.language_override,\n max: index.max,\n min: index.min,\n partialFilterExpression: index.partialFilterExpression\n ? rekeyDocumentPaths({ document: index.partialFilterExpression, fromPath, toPath })\n : undefined,\n sparse: index.sparse,\n storageEngine: index.storageEngine,\n textIndexVersion: index.textIndexVersion,\n unique: index.unique,\n weights: index.weights\n ? rekeyDocumentPaths({ document: index.weights, fromPath, toPath })\n : undefined,\n wildcardProjection: index.wildcardProjection\n ? rekeyDocumentPaths({ document: index.wildcardProjection, fromPath, toPath })\n : undefined,\n }\n\n return Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ) as CreateIndexesOptions\n}\n\nfunction rekeyDocumentPaths({\n document,\n fromPath,\n toPath,\n}: {\n document: Document\n fromPath: string\n toPath: string\n}): Document {\n return Object.fromEntries(\n Object.entries(document).map(([key, value]) => [\n rekeyPath({ fromPath, path: key, toPath }),\n rekeyDocumentValue({ fromPath, toPath, value }),\n ]),\n )\n}\n\nfunction isPathAtOrBelow({ key, path }: { key: string; path: string }): boolean {\n return key === path || key.startsWith(`${path}.`)\n}\n\nfunction rekeyPath({\n fromPath,\n path,\n toPath,\n}: {\n fromPath: string\n path: string\n toPath: string\n}): string {\n return isPathAtOrBelow({ key: path, path: fromPath })\n ? `${toPath}${path.slice(fromPath.length)}`\n : path\n}\n\nfunction rekeyDocumentValue({\n fromPath,\n toPath,\n value,\n}: {\n fromPath: string\n toPath: string\n value: unknown\n}): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => rekeyDocumentValue({ fromPath, toPath, value: item }))\n }\n\n if (\n value !== null &&\n typeof value === 'object' &&\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)\n ) {\n return rekeyDocumentPaths({ document: value as Document, fromPath, toPath })\n }\n\n return value\n}\n"],"names":["isDeepStrictEqual","getSession","INDEX_CONFLICT_CODES","Set","NAMESPACE_NOT_FOUND_CODE","GENERATED_VARIANT_METADATA_FIELDS","migrateSizesToVariants","direction","payload","req","adapter","db","session","from","to","targets","collection","config","collections","upload","undefined","expectedVariantNames","variants","map","name","push","slug","fromPath","toPath","versions","sourceData","directCollision","Promise","all","findOne","$exists","projection","_id","findUnexpectedDestinationData","Error","collectionName","target","rekeyIndexes","result","updateMany","$rename","logger","info","msg","modifiedCount","expectedVariantNameSet","cursor","find","document","destinationData","getDocumentPath","path","hasUnexpectedVariantData","close","split","reduce","value","pathSegment","isRecord","variantName","variantData","Object","entries","has","keys","some","metadataFieldName","Array","isArray","indexes","err","code","index","sourceKeys","getIndexKeysForCreate","key","isPathAtOrBelow","rekeyedKeys","destinationOptions","getDestinationIndexOptions","weights","rekeyTextIndex","createIndex","destinationIndex","candidate","existingDestinationOptions","dropIndex","sourceOptions","restoreErr","AggregateError","hasInternalTextKeys","textPath","rekeyPath","fromEntries","options","background","bits","bucketSize","collation","default_language","expireAfterSeconds","hidden","language_override","max","min","partialFilterExpression","rekeyDocumentPaths","sparse","storageEngine","textIndexVersion","unique","wildcardProjection","filter","rekeyDocumentValue","startsWith","slice","length","item","getPrototypeOf","prototype"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ declare const imports = "import { migrateSizesToVariants } from '@payloadcms/db-mongodb/migration-utils'";
2
+ declare const upSQL = " await migrateSizesToVariants({ payload, req })\n";
3
+ declare const downSQL = " await migrateSizesToVariants({ direction: 'down', payload, req })\n";
4
+ export { downSQL, imports, upSQL };
5
+ //# sourceMappingURL=sizes-to-variants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sizes-to-variants.d.ts","sourceRoot":"","sources":["../../src/predefinedMigrations/sizes-to-variants.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,OAAO,oFAAoF,CAAA;AACjG,QAAA,MAAM,KAAK,uDACV,CAAA;AACD,QAAA,MAAM,OAAO,0EACZ,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,8 @@
1
+ const imports = `import { migrateSizesToVariants } from '@payloadcms/db-mongodb/migration-utils'`;
2
+ const upSQL = ` await migrateSizesToVariants({ payload, req })
3
+ `;
4
+ const downSQL = ` await migrateSizesToVariants({ direction: 'down', payload, req })
5
+ `;
6
+ export { downSQL, imports, upSQL };
7
+
8
+ //# sourceMappingURL=sizes-to-variants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/predefinedMigrations/sizes-to-variants.ts"],"sourcesContent":["const imports = `import { migrateSizesToVariants } from '@payloadcms/db-mongodb/migration-utils'`\nconst upSQL = ` await migrateSizesToVariants({ payload, req })\n`\nconst downSQL = ` await migrateSizesToVariants({ direction: 'down', payload, req })\n`\n\nexport { downSQL, imports, upSQL }\n"],"names":["imports","upSQL","downSQL"],"mappings":"AAAA,MAAMA,UAAU,CAAC,+EAA+E,CAAC;AACjG,MAAMC,QAAQ,CAAC;AACf,CAAC;AACD,MAAMC,UAAU,CAAC;AACjB,CAAC;AAED,SAASA,OAAO,EAAEF,OAAO,EAAEC,KAAK,GAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"buildSearchParams.d.ts","sourceRoot":"","sources":["../../src/queries/buildSearchParams.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAEd,QAAQ,EAER,OAAO,EACR,MAAM,SAAS,CAAA;AAkBhB,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,cAAc,EACd,MAAM,EACN,UAAU,EACV,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,OAAO,EACP,GAAG,GACJ,EAAE;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,OAAO,CAAA;CACb,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CA4XnC"}
1
+ {"version":3,"file":"buildSearchParams.d.ts","sourceRoot":"","sources":["../../src/queries/buildSearchParams.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAEd,QAAQ,EAER,OAAO,EACR,MAAM,SAAS,CAAA;AAkBhB,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,cAAc,EACd,MAAM,EACN,UAAU,EACV,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,OAAO,EACP,GAAG,GACJ,EAAE;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,OAAO,CAAA;CACb,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAmZnC"}
@@ -60,6 +60,17 @@ const subQueryOptions = {
60
60
  payload
61
61
  });
62
62
  }
63
+ if (operator === 'contains' && paths.length === 1 && field.type === 'join' && typeof field.collection === 'string' && isNestedRelationshipQuery(val)) {
64
+ return buildJoinContainsSearchParam({
65
+ field,
66
+ locale,
67
+ nestedWhere: val,
68
+ payload
69
+ });
70
+ }
71
+ if ((operator === 'contains' || operator === 'like' || operator === 'not_like') && (isNestedRelationshipQuery(val) || Array.isArray(val) && val.some((entry)=>isNestedRelationshipQuery(entry)))) {
72
+ throw new APIError(`Invalid value for "${operator}" on path "${path}": expected a string.`, 400);
73
+ }
63
74
  if (path) {
64
75
  const sanitizedQueryValue = sanitizeQueryValue({
65
76
  field,
@@ -432,5 +443,44 @@ const subQueryOptions = {
432
443
  }
433
444
  }
434
445
  }
446
+ /**
447
+ * Builds a MongoDB condition for a `contains` query nested on a join field.
448
+ *
449
+ * Finds documents in the joined collection that match the nested query, then follows the join's
450
+ * `on` relationship to collect the parent IDs those documents point back to. Because the nested
451
+ * query resolves against a single joined document, the user's filter and any injected access
452
+ * constraint must be satisfied by the same document.
453
+ */ async function buildJoinContainsSearchParam({ field, locale, nestedWhere, payload }) {
454
+ if (field.type !== 'join' || typeof field.collection !== 'string' || !isNestedRelationshipQuery(nestedWhere)) {
455
+ return undefined;
456
+ }
457
+ const { collectionConfig, Model: JoinedModel } = getCollection({
458
+ adapter: payload.db,
459
+ collectionSlug: field.collection
460
+ });
461
+ const relationshipField = getFieldByPath({
462
+ fields: collectionConfig.flattenedFields,
463
+ path: field.on
464
+ });
465
+ if (!relationshipField) {
466
+ throw new APIError('Relationship field was not found');
467
+ }
468
+ let joinPath = relationshipField.localizedPath;
469
+ if (relationshipField.pathHasLocalized && payload.config.localization) {
470
+ joinPath = joinPath.replace('<locale>', locale || payload.config.localization.defaultLocale);
471
+ }
472
+ const subQuery = await JoinedModel.buildQuery({
473
+ locale,
474
+ payload,
475
+ where: nestedWhere
476
+ });
477
+ const parentIDs = await JoinedModel.distinct(joinPath, subQuery);
478
+ return {
479
+ path: '_id',
480
+ value: {
481
+ $in: parentIDs
482
+ }
483
+ };
484
+ }
435
485
 
436
486
  //# sourceMappingURL=buildSearchParams.js.map
@@ -1 +1 @@
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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"}
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 (\n operator === 'contains' &&\n paths.length === 1 &&\n field.type === 'join' &&\n typeof field.collection === 'string' &&\n isNestedRelationshipQuery(val)\n ) {\n return buildJoinContainsSearchParam({\n field,\n locale,\n nestedWhere: val,\n payload,\n })\n }\n\n if (\n (operator === 'contains' || operator === 'like' || operator === 'not_like') &&\n (isNestedRelationshipQuery(val) ||\n (Array.isArray(val) && val.some((entry) => isNestedRelationshipQuery(entry))))\n ) {\n throw new APIError(`Invalid value for \"${operator}\" on path \"${path}\": expected a string.`, 400)\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\n/**\n * Builds a MongoDB condition for a `contains` query nested on a join field.\n *\n * Finds documents in the joined collection that match the nested query, then follows the join's\n * `on` relationship to collect the parent IDs those documents point back to. Because the nested\n * query resolves against a single joined document, the user's filter and any injected access\n * constraint must be satisfied by the same document.\n */\nasync function buildJoinContainsSearchParam({\n field,\n locale,\n nestedWhere,\n payload,\n}: {\n field: FlattenedField\n locale?: string\n nestedWhere: unknown\n payload: Payload\n}): Promise<SearchParam | undefined> {\n if (\n field.type !== 'join' ||\n typeof field.collection !== 'string' ||\n !isNestedRelationshipQuery(nestedWhere)\n ) {\n return undefined\n }\n\n const { collectionConfig, Model: JoinedModel } = getCollection({\n adapter: payload.db as MongooseAdapter,\n collectionSlug: field.collection,\n })\n\n const relationshipField = getFieldByPath({\n fields: collectionConfig.flattenedFields,\n path: field.on,\n })\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('<locale>', locale || payload.config.localization.defaultLocale)\n }\n\n const subQuery = await JoinedModel.buildQuery({\n locale,\n payload,\n where: nestedWhere,\n })\n\n const parentIDs = await JoinedModel.distinct(joinPath, subQuery)\n\n return {\n path: '_id',\n value: { $in: parentIDs },\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","collection","buildJoinContainsSearchParam","Array","isArray","some","entry","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","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","JoinedModel","parentIDs"],"mappings":"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"}