@payloadcms/db-mongodb 4.0.0-internal.a6582c6 → 4.0.0-internal.a9d2e4e

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 (185) hide show
  1. package/dist/connect.d.ts.map +1 -1
  2. package/dist/connect.js +9 -2
  3. package/dist/connect.js.map +1 -1
  4. package/dist/count.d.ts.map +1 -1
  5. package/dist/count.js +33 -4
  6. package/dist/count.js.map +1 -1
  7. package/dist/countGlobalVersions.d.ts.map +1 -1
  8. package/dist/countGlobalVersions.js +10 -2
  9. package/dist/countGlobalVersions.js.map +1 -1
  10. package/dist/countVersions.d.ts.map +1 -1
  11. package/dist/countVersions.js +36 -4
  12. package/dist/countVersions.js.map +1 -1
  13. package/dist/create.d.ts.map +1 -1
  14. package/dist/create.js +2 -1
  15. package/dist/create.js.map +1 -1
  16. package/dist/createGlobalVersion.d.ts +1 -1
  17. package/dist/createGlobalVersion.d.ts.map +1 -1
  18. package/dist/createGlobalVersion.js +25 -2
  19. package/dist/createGlobalVersion.js.map +1 -1
  20. package/dist/createMigration.d.ts.map +1 -1
  21. package/dist/createMigration.js +9 -2
  22. package/dist/createMigration.js.map +1 -1
  23. package/dist/createVersion.d.ts.map +1 -1
  24. package/dist/createVersion.js +17 -4
  25. package/dist/createVersion.js.map +1 -1
  26. package/dist/deleteBranchGlobal.d.ts +10 -0
  27. package/dist/deleteBranchGlobal.d.ts.map +1 -0
  28. package/dist/deleteBranchGlobal.js +26 -0
  29. package/dist/deleteBranchGlobal.js.map +1 -0
  30. package/dist/deleteMany.d.ts.map +1 -1
  31. package/dist/deleteMany.js +1 -0
  32. package/dist/deleteMany.js.map +1 -1
  33. package/dist/deleteOne.d.ts.map +1 -1
  34. package/dist/deleteOne.js +20 -1
  35. package/dist/deleteOne.js.map +1 -1
  36. package/dist/deleteVersions.d.ts.map +1 -1
  37. package/dist/deleteVersions.js +1 -0
  38. package/dist/deleteVersions.js.map +1 -1
  39. package/dist/exports/migration-utils.d.ts +2 -0
  40. package/dist/exports/migration-utils.d.ts.map +1 -1
  41. package/dist/exports/migration-utils.js +2 -0
  42. package/dist/exports/migration-utils.js.map +1 -1
  43. package/dist/find.d.ts.map +1 -1
  44. package/dist/find.js +44 -8
  45. package/dist/find.js.map +1 -1
  46. package/dist/findDistinct.d.ts.map +1 -1
  47. package/dist/findDistinct.js +115 -12
  48. package/dist/findDistinct.js.map +1 -1
  49. package/dist/findGlobal.d.ts.map +1 -1
  50. package/dist/findGlobal.js +48 -9
  51. package/dist/findGlobal.js.map +1 -1
  52. package/dist/findGlobalVersions.d.ts.map +1 -1
  53. package/dist/findGlobalVersions.js +10 -2
  54. package/dist/findGlobalVersions.js.map +1 -1
  55. package/dist/findOne.d.ts.map +1 -1
  56. package/dist/findOne.js +43 -5
  57. package/dist/findOne.js.map +1 -1
  58. package/dist/findVersions.d.ts.map +1 -1
  59. package/dist/findVersions.js +49 -5
  60. package/dist/findVersions.js.map +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +4 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/init.d.ts.map +1 -1
  65. package/dist/init.js +89 -67
  66. package/dist/init.js.map +1 -1
  67. package/dist/migrateFresh.d.ts +4 -2
  68. package/dist/migrateFresh.d.ts.map +1 -1
  69. package/dist/migrateFresh.js +21 -6
  70. package/dist/migrateFresh.js.map +1 -1
  71. package/dist/models/buildCollectionSchema.d.ts +8 -2
  72. package/dist/models/buildCollectionSchema.d.ts.map +1 -1
  73. package/dist/models/buildCollectionSchema.js +4 -2
  74. package/dist/models/buildCollectionSchema.js.map +1 -1
  75. package/dist/models/buildGlobalModel.d.ts +5 -1
  76. package/dist/models/buildGlobalModel.d.ts.map +1 -1
  77. package/dist/models/buildGlobalModel.js +34 -3
  78. package/dist/models/buildGlobalModel.js.map +1 -1
  79. package/dist/models/buildSchema.d.ts +4 -0
  80. package/dist/models/buildSchema.d.ts.map +1 -1
  81. package/dist/models/buildSchema.js +100 -36
  82. package/dist/models/buildSchema.js.map +1 -1
  83. package/dist/models/schemaBuildContext.d.ts +21 -0
  84. package/dist/models/schemaBuildContext.d.ts.map +1 -0
  85. package/dist/models/schemaBuildContext.js +29 -0
  86. package/dist/models/schemaBuildContext.js.map +1 -0
  87. package/dist/predefinedMigrations/branching.d.ts +4 -0
  88. package/dist/predefinedMigrations/branching.d.ts.map +1 -0
  89. package/dist/predefinedMigrations/branching.js +9 -0
  90. package/dist/predefinedMigrations/branching.js.map +1 -0
  91. package/dist/predefinedMigrations/migrateBranching.d.ts +17 -0
  92. package/dist/predefinedMigrations/migrateBranching.d.ts.map +1 -0
  93. package/dist/predefinedMigrations/migrateBranching.js +90 -0
  94. package/dist/predefinedMigrations/migrateBranching.js.map +1 -0
  95. package/dist/predefinedMigrations/migrateRelationshipsV2_V3.d.ts.map +1 -1
  96. package/dist/predefinedMigrations/migrateRelationshipsV2_V3.js +4 -4
  97. package/dist/predefinedMigrations/migrateRelationshipsV2_V3.js.map +1 -1
  98. package/dist/predefinedMigrations/migrateSizesToVariants.d.ts +13 -0
  99. package/dist/predefinedMigrations/migrateSizesToVariants.d.ts.map +1 -0
  100. package/dist/predefinedMigrations/migrateSizesToVariants.js +368 -0
  101. package/dist/predefinedMigrations/migrateSizesToVariants.js.map +1 -0
  102. package/dist/predefinedMigrations/sizes-to-variants.d.ts +5 -0
  103. package/dist/predefinedMigrations/sizes-to-variants.d.ts.map +1 -0
  104. package/dist/predefinedMigrations/sizes-to-variants.js +8 -0
  105. package/dist/predefinedMigrations/sizes-to-variants.js.map +1 -0
  106. package/dist/queries/buildAndOrConditions.d.ts +4 -2
  107. package/dist/queries/buildAndOrConditions.d.ts.map +1 -1
  108. package/dist/queries/buildAndOrConditions.js +3 -1
  109. package/dist/queries/buildAndOrConditions.js.map +1 -1
  110. package/dist/queries/buildBranchVisibility.d.ts +11 -0
  111. package/dist/queries/buildBranchVisibility.d.ts.map +1 -0
  112. package/dist/queries/buildBranchVisibility.js +204 -0
  113. package/dist/queries/buildBranchVisibility.js.map +1 -0
  114. package/dist/queries/buildQuery.d.ts +4 -2
  115. package/dist/queries/buildQuery.d.ts.map +1 -1
  116. package/dist/queries/buildQuery.js +3 -1
  117. package/dist/queries/buildQuery.js.map +1 -1
  118. package/dist/queries/buildRelatedQueryPipeline.d.ts +7 -0
  119. package/dist/queries/buildRelatedQueryPipeline.d.ts.map +1 -0
  120. package/dist/queries/buildRelatedQueryPipeline.js +56 -0
  121. package/dist/queries/buildRelatedQueryPipeline.js.map +1 -0
  122. package/dist/queries/buildSearchParams.d.ts +4 -2
  123. package/dist/queries/buildSearchParams.d.ts.map +1 -1
  124. package/dist/queries/buildSearchParams.js +340 -25
  125. package/dist/queries/buildSearchParams.js.map +1 -1
  126. package/dist/queries/getBuildQueryPlugin.d.ts +3 -1
  127. package/dist/queries/getBuildQueryPlugin.d.ts.map +1 -1
  128. package/dist/queries/getBuildQueryPlugin.js +3 -1
  129. package/dist/queries/getBuildQueryPlugin.js.map +1 -1
  130. package/dist/queries/parseParams.d.ts +4 -2
  131. package/dist/queries/parseParams.d.ts.map +1 -1
  132. package/dist/queries/parseParams.js +5 -1
  133. package/dist/queries/parseParams.js.map +1 -1
  134. package/dist/queryDrafts.d.ts.map +1 -1
  135. package/dist/queryDrafts.js +39 -7
  136. package/dist/queryDrafts.js.map +1 -1
  137. package/dist/transactions/commitTransaction.d.ts.map +1 -1
  138. package/dist/transactions/commitTransaction.js +68 -7
  139. package/dist/transactions/commitTransaction.js.map +1 -1
  140. package/dist/transactions/rollbackTransaction.d.ts.map +1 -1
  141. package/dist/transactions/rollbackTransaction.js +10 -9
  142. package/dist/transactions/rollbackTransaction.js.map +1 -1
  143. package/dist/updateGlobal.d.ts.map +1 -1
  144. package/dist/updateGlobal.js +91 -9
  145. package/dist/updateGlobal.js.map +1 -1
  146. package/dist/updateGlobalVersion.d.ts.map +1 -1
  147. package/dist/updateGlobalVersion.js +3 -2
  148. package/dist/updateGlobalVersion.js.map +1 -1
  149. package/dist/updateJobs.js +1 -1
  150. package/dist/updateJobs.js.map +1 -1
  151. package/dist/updateMany.d.ts.map +1 -1
  152. package/dist/updateMany.js +3 -2
  153. package/dist/updateMany.js.map +1 -1
  154. package/dist/updateOne.d.ts.map +1 -1
  155. package/dist/updateOne.js +30 -4
  156. package/dist/updateOne.js.map +1 -1
  157. package/dist/updateVersion.d.ts.map +1 -1
  158. package/dist/updateVersion.js +3 -2
  159. package/dist/updateVersion.js.map +1 -1
  160. package/dist/upsertBranchGlobalChange.d.ts +3 -0
  161. package/dist/upsertBranchGlobalChange.d.ts.map +1 -0
  162. package/dist/upsertBranchGlobalChange.js +28 -0
  163. package/dist/upsertBranchGlobalChange.js.map +1 -0
  164. package/dist/utilities/aggregatePaginate.d.ts +2 -1
  165. package/dist/utilities/aggregatePaginate.d.ts.map +1 -1
  166. package/dist/utilities/aggregatePaginate.js +21 -5
  167. package/dist/utilities/aggregatePaginate.js.map +1 -1
  168. package/dist/utilities/buildJoinAggregation.d.ts +4 -2
  169. package/dist/utilities/buildJoinAggregation.d.ts.map +1 -1
  170. package/dist/utilities/buildJoinAggregation.js +160 -26
  171. package/dist/utilities/buildJoinAggregation.js.map +1 -1
  172. package/dist/utilities/resolveJoins.d.ts +6 -2
  173. package/dist/utilities/resolveJoins.d.ts.map +1 -1
  174. package/dist/utilities/resolveJoins.js +115 -26
  175. package/dist/utilities/resolveJoins.js.map +1 -1
  176. package/dist/utilities/transform.d.ts.map +1 -1
  177. package/dist/utilities/transform.js +15 -0
  178. package/dist/utilities/transform.js.map +1 -1
  179. package/package.json +18 -21
  180. package/dist/queries/buildSortParam.spec.js +0 -123
  181. package/dist/queries/buildSortParam.spec.js.map +0 -1
  182. package/dist/queries/getLocalizedSortProperty.spec.js +0 -215
  183. package/dist/queries/getLocalizedSortProperty.spec.js.map +0 -1
  184. package/dist/utilities/transform.spec.js +0 -479
  185. package/dist/utilities/transform.spec.js.map +0 -1
@@ -0,0 +1,29 @@
1
+ import mongoose from 'mongoose';
2
+ import { createSchemaBuildContext } from 'payload/internal';
3
+ const getMongoosePluginRegistry = ({ mongooseInstance })=>mongooseInstance.plugins;
4
+ const defaultMongoosePluginFunctions = new Set(getMongoosePluginRegistry({
5
+ mongooseInstance: new mongoose.Mongoose({
6
+ createInitialConnection: false
7
+ })
8
+ }).map(([plugin])=>plugin));
9
+ /**
10
+ * Connection and global plugins can keep state on each nested schema. Mongoose does not clone
11
+ * those nested schemas when it attaches a discriminator, so cached templates would change plugin
12
+ * application.
13
+ */ export const createMongoSchemaBuildContext = ({ connection })=>{
14
+ const hasCustomGlobalPlugins = getMongoosePluginRegistry({
15
+ mongooseInstance: connection.base
16
+ }).some(([plugin])=>!defaultMongoosePluginFunctions.has(plugin));
17
+ return createSchemaBuildContext({
18
+ isCacheEnabled: connection.plugins.length === 0 && !hasCustomGlobalPlugins
19
+ });
20
+ };
21
+ export const getBlockSchemaCacheKey = ({ blockSlug, buildSchemaOptions, fieldPath, isLocalized, isReference, isVersion })=>[
22
+ `${isReference ? `block:${blockSlug}` : `inline:${fieldPath}/block:${blockSlug}`}${isVersion ? '-version' : ''}`,
23
+ buildSchemaOptions.disableUnique && 'disableUnique:true',
24
+ buildSchemaOptions.draftsEnabled && 'draftsEnabled:true',
25
+ buildSchemaOptions.indexSortableFields && 'indexSortableFields:true',
26
+ isLocalized && 'isLocalized:true'
27
+ ].filter(Boolean).join('|');
28
+
29
+ //# sourceMappingURL=schemaBuildContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/models/schemaBuildContext.ts"],"sourcesContent":["import type { Connection, Schema } from 'mongoose'\nimport type { SchemaBuildContext } from 'payload/internal'\n\nimport mongoose from 'mongoose'\nimport { createSchemaBuildContext } from 'payload/internal'\n\nimport type { BuildSchemaOptions } from './buildSchema.js'\n\nexport type MongoSchemaBuildContext = SchemaBuildContext<Schema>\n\ntype MongoosePluginRegistry = Array<[Parameters<typeof mongoose.plugin>[0], unknown]>\n\nconst getMongoosePluginRegistry = ({\n mongooseInstance,\n}: {\n mongooseInstance: typeof mongoose\n}): MongoosePluginRegistry =>\n (mongooseInstance as { plugins: MongoosePluginRegistry } & typeof mongoose).plugins\n\nconst defaultMongoosePluginFunctions = new Set(\n getMongoosePluginRegistry({\n mongooseInstance: new mongoose.Mongoose({ createInitialConnection: false }),\n }).map(([plugin]) => plugin),\n)\n\n/**\n * Connection and global plugins can keep state on each nested schema. Mongoose does not clone\n * those nested schemas when it attaches a discriminator, so cached templates would change plugin\n * application.\n */\nexport const createMongoSchemaBuildContext = ({\n connection,\n}: {\n connection: Connection\n}): MongoSchemaBuildContext => {\n const hasCustomGlobalPlugins = getMongoosePluginRegistry({\n mongooseInstance: connection.base,\n }).some(([plugin]) => !defaultMongoosePluginFunctions.has(plugin))\n\n return createSchemaBuildContext<Schema>({\n isCacheEnabled: connection.plugins.length === 0 && !hasCustomGlobalPlugins,\n })\n}\n\nexport const getBlockSchemaCacheKey = ({\n blockSlug,\n buildSchemaOptions,\n fieldPath,\n isLocalized,\n isReference,\n isVersion,\n}: {\n blockSlug: string\n buildSchemaOptions: BuildSchemaOptions\n fieldPath: string\n isLocalized: boolean\n isReference: boolean\n isVersion: boolean\n}): string =>\n [\n `${isReference ? `block:${blockSlug}` : `inline:${fieldPath}/block:${blockSlug}`}${isVersion ? '-version' : ''}`,\n buildSchemaOptions.disableUnique && 'disableUnique:true',\n buildSchemaOptions.draftsEnabled && 'draftsEnabled:true',\n buildSchemaOptions.indexSortableFields && 'indexSortableFields:true',\n isLocalized && 'isLocalized:true',\n ]\n .filter(Boolean)\n .join('|')\n"],"names":["mongoose","createSchemaBuildContext","getMongoosePluginRegistry","mongooseInstance","plugins","defaultMongoosePluginFunctions","Set","Mongoose","createInitialConnection","map","plugin","createMongoSchemaBuildContext","connection","hasCustomGlobalPlugins","base","some","has","isCacheEnabled","length","getBlockSchemaCacheKey","blockSlug","buildSchemaOptions","fieldPath","isLocalized","isReference","isVersion","disableUnique","draftsEnabled","indexSortableFields","filter","Boolean","join"],"mappings":"AAGA,OAAOA,cAAc,WAAU;AAC/B,SAASC,wBAAwB,QAAQ,mBAAkB;AAQ3D,MAAMC,4BAA4B,CAAC,EACjCC,gBAAgB,EAGjB,GACC,AAACA,iBAA2EC,OAAO;AAErF,MAAMC,iCAAiC,IAAIC,IACzCJ,0BAA0B;IACxBC,kBAAkB,IAAIH,SAASO,QAAQ,CAAC;QAAEC,yBAAyB;IAAM;AAC3E,GAAGC,GAAG,CAAC,CAAC,CAACC,OAAO,GAAKA;AAGvB;;;;CAIC,GACD,OAAO,MAAMC,gCAAgC,CAAC,EAC5CC,UAAU,EAGX;IACC,MAAMC,yBAAyBX,0BAA0B;QACvDC,kBAAkBS,WAAWE,IAAI;IACnC,GAAGC,IAAI,CAAC,CAAC,CAACL,OAAO,GAAK,CAACL,+BAA+BW,GAAG,CAACN;IAE1D,OAAOT,yBAAiC;QACtCgB,gBAAgBL,WAAWR,OAAO,CAACc,MAAM,KAAK,KAAK,CAACL;IACtD;AACF,EAAC;AAED,OAAO,MAAMM,yBAAyB,CAAC,EACrCC,SAAS,EACTC,kBAAkB,EAClBC,SAAS,EACTC,WAAW,EACXC,WAAW,EACXC,SAAS,EAQV,GACC;QACE,GAAGD,cAAc,CAAC,MAAM,EAAEJ,WAAW,GAAG,CAAC,OAAO,EAAEE,UAAU,OAAO,EAAEF,WAAW,GAAGK,YAAY,aAAa,IAAI;QAChHJ,mBAAmBK,aAAa,IAAI;QACpCL,mBAAmBM,aAAa,IAAI;QACpCN,mBAAmBO,mBAAmB,IAAI;QAC1CL,eAAe;KAChB,CACEM,MAAM,CAACC,SACPC,IAAI,CAAC,KAAI"}
@@ -0,0 +1,4 @@
1
+ declare const imports = "import { migrateBranching } from '@payloadcms/db-mongodb/migration-utils'";
2
+ declare const upSQL = " // Index synchronization must run outside the migration transaction.\n await migrateBranching({\n payload,\n })\n";
3
+ export { imports, upSQL };
4
+ //# sourceMappingURL=branching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branching.d.ts","sourceRoot":"","sources":["../../src/predefinedMigrations/branching.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,OAAO,8EAA8E,CAAA;AAC3F,QAAA,MAAM,KAAK,6HAIV,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,9 @@
1
+ const imports = `import { migrateBranching } from '@payloadcms/db-mongodb/migration-utils'`;
2
+ const upSQL = ` // Index synchronization must run outside the migration transaction.
3
+ await migrateBranching({
4
+ payload,
5
+ })
6
+ `;
7
+ export { imports, upSQL };
8
+
9
+ //# sourceMappingURL=branching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/predefinedMigrations/branching.ts"],"sourcesContent":["const imports = `import { migrateBranching } from '@payloadcms/db-mongodb/migration-utils'`\nconst upSQL = ` // Index synchronization must run outside the migration transaction.\n await migrateBranching({\n payload,\n })\n`\n\nexport { imports, upSQL }\n"],"names":["imports","upSQL"],"mappings":"AAAA,MAAMA,UAAU,CAAC,yEAAyE,CAAC;AAC3F,MAAMC,QAAQ,CAAC;;;;AAIf,CAAC;AAED,SAASD,OAAO,EAAEC,KAAK,GAAE"}
@@ -0,0 +1,17 @@
1
+ import type { ClientSession } from 'mongoose';
2
+ import type { Payload } from 'payload';
3
+ type BranchingMigrationArgs = {
4
+ payload: Payload;
5
+ session?: ClientSession;
6
+ };
7
+ /**
8
+ * Backfills branch identity before replacing legacy indexes with the current schema indexes.
9
+ *
10
+ * Run this generated migration after enabling branching. Backfill errors stop the migration
11
+ * before any indexes are removed, so uniqueness conflicts remain visible and recoverable.
12
+ * Index synchronization removes indexes not declared in the configured Mongoose schema;
13
+ * declare user-managed indexes in that schema before running this migration.
14
+ */
15
+ export declare const migrateBranching: ({ payload, session, }: BranchingMigrationArgs) => Promise<void>;
16
+ export {};
17
+ //# sourceMappingURL=migrateBranching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateBranching.d.ts","sourceRoot":"","sources":["../../src/predefinedMigrations/migrateBranching.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAOtC,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB,CAAA;AAQD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,0BAG1B,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAqEvC,CAAA"}
@@ -0,0 +1,90 @@
1
+ import { branchField, MAIN_BRANCH } from 'payload';
2
+ const legacyMainFilter = {
3
+ $or: [
4
+ {
5
+ [branchField]: {
6
+ $exists: false
7
+ }
8
+ },
9
+ {
10
+ [branchField]: null
11
+ }
12
+ ]
13
+ };
14
+ /**
15
+ * Backfills branch identity before replacing legacy indexes with the current schema indexes.
16
+ *
17
+ * Run this generated migration after enabling branching. Backfill errors stop the migration
18
+ * before any indexes are removed, so uniqueness conflicts remain visible and recoverable.
19
+ * Index synchronization removes indexes not declared in the configured Mongoose schema;
20
+ * declare user-managed indexes in that schema before running this migration.
21
+ */ export const migrateBranching = async ({ payload, session })=>{
22
+ const branching = payload.config.branching;
23
+ if (!branching?.enabled) {
24
+ payload.logger.info({
25
+ msg: 'Branching is not enabled, skipping branching migration'
26
+ });
27
+ return;
28
+ }
29
+ const adapter = payload.db;
30
+ const modelsToSync = new Set();
31
+ const updateOptions = session ? {
32
+ session
33
+ } : {};
34
+ payload.logger.info({
35
+ msg: 'Starting branching data and index migration'
36
+ });
37
+ for (const collectionSlug of branching.branchableCollections){
38
+ const collectionModel = adapter.collections[collectionSlug];
39
+ const versionModel = adapter.versions[collectionSlug];
40
+ if (!collectionModel) {
41
+ throw new Error(`Could not find MongoDB model for branchable collection "${collectionSlug}".`);
42
+ }
43
+ await collectionModel.collection.updateMany(legacyMainFilter, {
44
+ $set: {
45
+ [branchField]: MAIN_BRANCH
46
+ }
47
+ }, updateOptions);
48
+ modelsToSync.add(collectionModel);
49
+ if (versionModel) {
50
+ await versionModel.collection.updateMany(legacyMainFilter, {
51
+ $set: {
52
+ [branchField]: MAIN_BRANCH
53
+ }
54
+ }, updateOptions);
55
+ modelsToSync.add(versionModel);
56
+ }
57
+ }
58
+ if (branching.branchableGlobals.size) {
59
+ await adapter.globals.collection.updateMany({
60
+ ...legacyMainFilter,
61
+ globalType: {
62
+ $in: Array.from(branching.branchableGlobals)
63
+ }
64
+ }, {
65
+ $set: {
66
+ [branchField]: MAIN_BRANCH
67
+ }
68
+ }, updateOptions);
69
+ modelsToSync.add(adapter.globals);
70
+ for (const globalSlug of branching.branchableGlobals){
71
+ const versionModel = adapter.versions[globalSlug];
72
+ if (versionModel) {
73
+ await versionModel.collection.updateMany(legacyMainFilter, {
74
+ $set: {
75
+ [branchField]: MAIN_BRANCH
76
+ }
77
+ }, updateOptions);
78
+ modelsToSync.add(versionModel);
79
+ }
80
+ }
81
+ }
82
+ for (const model of modelsToSync){
83
+ await model.syncIndexes();
84
+ }
85
+ payload.logger.info({
86
+ msg: 'Branching data and index migration completed successfully'
87
+ });
88
+ };
89
+
90
+ //# sourceMappingURL=migrateBranching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/predefinedMigrations/migrateBranching.ts"],"sourcesContent":["import type { ClientSession } from 'mongoose'\nimport type { Payload } from 'payload'\n\nimport { branchField, MAIN_BRANCH } from 'payload'\n\nimport type { MongooseAdapter } from '../index.js'\nimport type { CollectionModel, GlobalModel } from '../types.js'\n\ntype BranchingMigrationArgs = {\n payload: Payload\n session?: ClientSession\n}\n\ntype SyncableModel = CollectionModel | GlobalModel\n\nconst legacyMainFilter = {\n $or: [{ [branchField]: { $exists: false } }, { [branchField]: null }],\n}\n\n/**\n * Backfills branch identity before replacing legacy indexes with the current schema indexes.\n *\n * Run this generated migration after enabling branching. Backfill errors stop the migration\n * before any indexes are removed, so uniqueness conflicts remain visible and recoverable.\n * Index synchronization removes indexes not declared in the configured Mongoose schema;\n * declare user-managed indexes in that schema before running this migration.\n */\nexport const migrateBranching = async ({\n payload,\n session,\n}: BranchingMigrationArgs): Promise<void> => {\n const branching = payload.config.branching\n\n if (!branching?.enabled) {\n payload.logger.info({ msg: 'Branching is not enabled, skipping branching migration' })\n return\n }\n\n const adapter = payload.db as MongooseAdapter\n const modelsToSync = new Set<SyncableModel>()\n const updateOptions = session ? { session } : {}\n\n payload.logger.info({ msg: 'Starting branching data and index migration' })\n\n for (const collectionSlug of branching.branchableCollections) {\n const collectionModel = adapter.collections[collectionSlug]\n const versionModel = adapter.versions[collectionSlug]\n\n if (!collectionModel) {\n throw new Error(`Could not find MongoDB model for branchable collection \"${collectionSlug}\".`)\n }\n\n await collectionModel.collection.updateMany(\n legacyMainFilter,\n { $set: { [branchField]: MAIN_BRANCH } },\n updateOptions,\n )\n modelsToSync.add(collectionModel)\n\n if (versionModel) {\n await versionModel.collection.updateMany(\n legacyMainFilter,\n { $set: { [branchField]: MAIN_BRANCH } },\n updateOptions,\n )\n modelsToSync.add(versionModel)\n }\n }\n\n if (branching.branchableGlobals.size) {\n await adapter.globals.collection.updateMany(\n {\n ...legacyMainFilter,\n globalType: { $in: Array.from(branching.branchableGlobals) },\n },\n { $set: { [branchField]: MAIN_BRANCH } },\n updateOptions,\n )\n modelsToSync.add(adapter.globals)\n\n for (const globalSlug of branching.branchableGlobals) {\n const versionModel = adapter.versions[globalSlug]\n\n if (versionModel) {\n await versionModel.collection.updateMany(\n legacyMainFilter,\n { $set: { [branchField]: MAIN_BRANCH } },\n updateOptions,\n )\n modelsToSync.add(versionModel)\n }\n }\n }\n\n for (const model of modelsToSync) {\n await model.syncIndexes()\n }\n\n payload.logger.info({ msg: 'Branching data and index migration completed successfully' })\n}\n"],"names":["branchField","MAIN_BRANCH","legacyMainFilter","$or","$exists","migrateBranching","payload","session","branching","config","enabled","logger","info","msg","adapter","db","modelsToSync","Set","updateOptions","collectionSlug","branchableCollections","collectionModel","collections","versionModel","versions","Error","collection","updateMany","$set","add","branchableGlobals","size","globals","globalType","$in","Array","from","globalSlug","model","syncIndexes"],"mappings":"AAGA,SAASA,WAAW,EAAEC,WAAW,QAAQ,UAAS;AAYlD,MAAMC,mBAAmB;IACvBC,KAAK;QAAC;YAAE,CAACH,YAAY,EAAE;gBAAEI,SAAS;YAAM;QAAE;QAAG;YAAE,CAACJ,YAAY,EAAE;QAAK;KAAE;AACvE;AAEA;;;;;;;CAOC,GACD,OAAO,MAAMK,mBAAmB,OAAO,EACrCC,OAAO,EACPC,OAAO,EACgB;IACvB,MAAMC,YAAYF,QAAQG,MAAM,CAACD,SAAS;IAE1C,IAAI,CAACA,WAAWE,SAAS;QACvBJ,QAAQK,MAAM,CAACC,IAAI,CAAC;YAAEC,KAAK;QAAyD;QACpF;IACF;IAEA,MAAMC,UAAUR,QAAQS,EAAE;IAC1B,MAAMC,eAAe,IAAIC;IACzB,MAAMC,gBAAgBX,UAAU;QAAEA;IAAQ,IAAI,CAAC;IAE/CD,QAAQK,MAAM,CAACC,IAAI,CAAC;QAAEC,KAAK;IAA8C;IAEzE,KAAK,MAAMM,kBAAkBX,UAAUY,qBAAqB,CAAE;QAC5D,MAAMC,kBAAkBP,QAAQQ,WAAW,CAACH,eAAe;QAC3D,MAAMI,eAAeT,QAAQU,QAAQ,CAACL,eAAe;QAErD,IAAI,CAACE,iBAAiB;YACpB,MAAM,IAAII,MAAM,CAAC,wDAAwD,EAAEN,eAAe,EAAE,CAAC;QAC/F;QAEA,MAAME,gBAAgBK,UAAU,CAACC,UAAU,CACzCzB,kBACA;YAAE0B,MAAM;gBAAE,CAAC5B,YAAY,EAAEC;YAAY;QAAE,GACvCiB;QAEFF,aAAaa,GAAG,CAACR;QAEjB,IAAIE,cAAc;YAChB,MAAMA,aAAaG,UAAU,CAACC,UAAU,CACtCzB,kBACA;gBAAE0B,MAAM;oBAAE,CAAC5B,YAAY,EAAEC;gBAAY;YAAE,GACvCiB;YAEFF,aAAaa,GAAG,CAACN;QACnB;IACF;IAEA,IAAIf,UAAUsB,iBAAiB,CAACC,IAAI,EAAE;QACpC,MAAMjB,QAAQkB,OAAO,CAACN,UAAU,CAACC,UAAU,CACzC;YACE,GAAGzB,gBAAgB;YACnB+B,YAAY;gBAAEC,KAAKC,MAAMC,IAAI,CAAC5B,UAAUsB,iBAAiB;YAAE;QAC7D,GACA;YAAEF,MAAM;gBAAE,CAAC5B,YAAY,EAAEC;YAAY;QAAE,GACvCiB;QAEFF,aAAaa,GAAG,CAACf,QAAQkB,OAAO;QAEhC,KAAK,MAAMK,cAAc7B,UAAUsB,iBAAiB,CAAE;YACpD,MAAMP,eAAeT,QAAQU,QAAQ,CAACa,WAAW;YAEjD,IAAId,cAAc;gBAChB,MAAMA,aAAaG,UAAU,CAACC,UAAU,CACtCzB,kBACA;oBAAE0B,MAAM;wBAAE,CAAC5B,YAAY,EAAEC;oBAAY;gBAAE,GACvCiB;gBAEFF,aAAaa,GAAG,CAACN;YACnB;QACF;IACF;IAEA,KAAK,MAAMe,SAAStB,aAAc;QAChC,MAAMsB,MAAMC,WAAW;IACzB;IAEAjC,QAAQK,MAAM,CAACC,IAAI,CAAC;QAAEC,KAAK;IAA4D;AACzF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrateRelationshipsV2_V3.d.ts","sourceRoot":"","sources":["../../src/predefinedMigrations/migrateRelationshipsV2_V3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAS,cAAc,EAAE,MAAM,SAAS,CAAA;AA8GpD,wBAAsB,yBAAyB,CAAC,EAC9C,SAAS,EACT,GAAG,GACJ,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,cAAc,CAAA;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqGhB"}
1
+ {"version":3,"file":"migrateRelationshipsV2_V3.d.ts","sourceRoot":"","sources":["../../src/predefinedMigrations/migrateRelationshipsV2_V3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAS,cAAc,EAAE,MAAM,SAAS,CAAA;AA4GpD,wBAAsB,yBAAyB,CAAC,EAC9C,SAAS,EACT,GAAG,GACJ,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,cAAc,CAAA;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqGhB"}
@@ -28,8 +28,9 @@ const migrateModelWithBatching = async ({ batchSize, db, fields, Model, parentIs
28
28
  parentIsLocalized
29
29
  });
30
30
  }
31
- await Model.collection.bulkWrite(// @ts-expect-error bulkWrite has a weird type, insertOne, updateMany etc are required here as well.
32
- docs.map((doc)=>({
31
+ // Writing through the driver collection skips Mongoose timestamps entirely,
32
+ // which is what we want here - timestamps are added by the write transform above
33
+ await Model.collection.bulkWrite(docs.map((doc)=>({
33
34
  updateOne: {
34
35
  filter: {
35
36
  _id: doc._id
@@ -39,8 +40,7 @@ const migrateModelWithBatching = async ({ batchSize, db, fields, Model, parentIs
39
40
  }
40
41
  }
41
42
  })), {
42
- session,
43
- timestamps: false
43
+ session
44
44
  });
45
45
  skip += batchSize;
46
46
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/predefinedMigrations/migrateRelationshipsV2_V3.ts"],"sourcesContent":["import type { ClientSession, Model } from 'mongoose'\nimport type { Field, PayloadRequest } from 'payload'\n\nimport { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload'\n\nimport type { MongooseAdapter } from '../index.js'\n\nimport { getCollection, getGlobal } from '../utilities/getEntity.js'\nimport { getSession } from '../utilities/getSession.js'\nimport { transform } from '../utilities/transform.js'\n\nconst migrateModelWithBatching = async ({\n batchSize,\n db,\n fields,\n Model,\n parentIsLocalized,\n session,\n}: {\n batchSize: number\n db: MongooseAdapter\n fields: Field[]\n Model: Model<any>\n parentIsLocalized: boolean\n session?: ClientSession\n}): Promise<void> => {\n let hasNext = true\n let skip = 0\n\n while (hasNext) {\n const docs = await Model.find(\n {},\n {},\n {\n lean: true,\n limit: batchSize + 1,\n session,\n skip,\n },\n )\n\n if (docs.length === 0) {\n break\n }\n\n hasNext = docs.length > batchSize\n\n if (hasNext) {\n docs.pop()\n }\n\n for (const doc of docs) {\n transform({ adapter: db, data: doc, fields, operation: 'write', parentIsLocalized })\n }\n\n await Model.collection.bulkWrite(\n // @ts-expect-error bulkWrite has a weird type, insertOne, updateMany etc are required here as well.\n docs.map((doc) => ({\n updateOne: {\n filter: { _id: doc._id },\n update: {\n $set: doc,\n },\n },\n })),\n {\n session, // Timestamps are manually added by the write transform\n timestamps: false,\n },\n )\n\n skip += batchSize\n }\n}\n\nconst hasRelationshipOrUploadField = ({ fields }: { fields: Field[] }): boolean => {\n for (const field of fields) {\n if (field.type === 'relationship' || field.type === 'upload') {\n return true\n }\n\n if ('fields' in field) {\n if (hasRelationshipOrUploadField({ fields: field.fields })) {\n return true\n }\n }\n\n if ('blocks' in field) {\n for (const block of field.blocks) {\n if (typeof block === 'string') {\n // Skip - string blocks have been added in v3 and thus don't need to be migrated\n continue\n }\n if (hasRelationshipOrUploadField({ fields: block.fields })) {\n return true\n }\n }\n }\n\n if ('tabs' in field) {\n for (const tab of field.tabs) {\n if (hasRelationshipOrUploadField({ fields: tab.fields })) {\n return true\n }\n }\n }\n }\n\n return false\n}\n\nexport async function migrateRelationshipsV2_V3({\n batchSize,\n req,\n}: {\n batchSize: number\n req: PayloadRequest\n}): Promise<void> {\n const { payload } = req\n const db = payload.db as MongooseAdapter\n const config = payload.config\n\n const session = await getSession(db, req)\n\n for (const collection of payload.config.collections) {\n if (hasRelationshipOrUploadField(collection)) {\n payload.logger.info(`Migrating collection \"${collection.slug}\"`)\n\n const { Model } = getCollection({ adapter: db, collectionSlug: collection.slug })\n\n await migrateModelWithBatching({\n batchSize,\n db,\n fields: collection.fields,\n Model,\n parentIsLocalized: false,\n session,\n })\n\n payload.logger.info(`Migrated collection \"${collection.slug}\"`)\n }\n\n if (collection.versions) {\n payload.logger.info(`Migrating collection versions \"${collection.slug}\"`)\n\n const { Model } = getCollection({\n adapter: db,\n collectionSlug: collection.slug,\n versions: true,\n })\n\n await migrateModelWithBatching({\n batchSize,\n db,\n fields: buildVersionCollectionFields(config, collection),\n Model,\n parentIsLocalized: false,\n session,\n })\n\n payload.logger.info(`Migrated collection versions \"${collection.slug}\"`)\n }\n }\n\n const { globals: GlobalsModel } = db\n\n for (const global of payload.config.globals) {\n if (hasRelationshipOrUploadField(global)) {\n payload.logger.info(`Migrating global \"${global.slug}\"`)\n\n const doc = await GlobalsModel.findOne<Record<string, unknown>>(\n {\n globalType: {\n $eq: global.slug,\n },\n },\n {},\n { lean: true, session },\n )\n\n // in case if the global doesn't exist in the database yet (not saved)\n if (doc) {\n transform({\n adapter: db,\n data: doc,\n fields: global.fields,\n operation: 'write',\n })\n\n await GlobalsModel.collection.updateOne(\n {\n globalType: global.slug,\n },\n { $set: doc },\n { session },\n )\n }\n\n payload.logger.info(`Migrated global \"${global.slug}\"`)\n }\n\n if (global.versions) {\n payload.logger.info(`Migrating global versions \"${global.slug}\"`)\n\n const { Model } = getGlobal({ adapter: db, globalSlug: global.slug, versions: true })\n\n await migrateModelWithBatching({\n batchSize,\n db,\n fields: buildVersionGlobalFields(config, global),\n Model,\n parentIsLocalized: false,\n session,\n })\n\n payload.logger.info(`Migrated global versions \"${global.slug}\"`)\n }\n }\n}\n"],"names":["buildVersionCollectionFields","buildVersionGlobalFields","getCollection","getGlobal","getSession","transform","migrateModelWithBatching","batchSize","db","fields","Model","parentIsLocalized","session","hasNext","skip","docs","find","lean","limit","length","pop","doc","adapter","data","operation","collection","bulkWrite","map","updateOne","filter","_id","update","$set","timestamps","hasRelationshipOrUploadField","field","type","block","blocks","tab","tabs","migrateRelationshipsV2_V3","req","payload","config","collections","logger","info","slug","collectionSlug","versions","globals","GlobalsModel","global","findOne","globalType","$eq","globalSlug"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/predefinedMigrations/migrateRelationshipsV2_V3.ts"],"sourcesContent":["import type { ClientSession, Model } from 'mongoose'\nimport type { Field, PayloadRequest } from 'payload'\n\nimport { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload'\n\nimport type { MongooseAdapter } from '../index.js'\n\nimport { getCollection, getGlobal } from '../utilities/getEntity.js'\nimport { getSession } from '../utilities/getSession.js'\nimport { transform } from '../utilities/transform.js'\n\nconst migrateModelWithBatching = async ({\n batchSize,\n db,\n fields,\n Model,\n parentIsLocalized,\n session,\n}: {\n batchSize: number\n db: MongooseAdapter\n fields: Field[]\n Model: Model<any>\n parentIsLocalized: boolean\n session?: ClientSession\n}): Promise<void> => {\n let hasNext = true\n let skip = 0\n\n while (hasNext) {\n const docs = await Model.find(\n {},\n {},\n {\n lean: true,\n limit: batchSize + 1,\n session,\n skip,\n },\n )\n\n if (docs.length === 0) {\n break\n }\n\n hasNext = docs.length > batchSize\n\n if (hasNext) {\n docs.pop()\n }\n\n for (const doc of docs) {\n transform({ adapter: db, data: doc, fields, operation: 'write', parentIsLocalized })\n }\n\n // Writing through the driver collection skips Mongoose timestamps entirely,\n // which is what we want here - timestamps are added by the write transform above\n await Model.collection.bulkWrite(\n docs.map((doc) => ({\n updateOne: {\n filter: { _id: doc._id },\n update: {\n $set: doc,\n },\n },\n })),\n { session },\n )\n\n skip += batchSize\n }\n}\n\nconst hasRelationshipOrUploadField = ({ fields }: { fields: Field[] }): boolean => {\n for (const field of fields) {\n if (field.type === 'relationship' || field.type === 'upload') {\n return true\n }\n\n if ('fields' in field) {\n if (hasRelationshipOrUploadField({ fields: field.fields })) {\n return true\n }\n }\n\n if ('blocks' in field) {\n for (const block of field.blocks) {\n if (typeof block === 'string') {\n // Skip - string blocks have been added in v3 and thus don't need to be migrated\n continue\n }\n if (hasRelationshipOrUploadField({ fields: block.fields })) {\n return true\n }\n }\n }\n\n if ('tabs' in field) {\n for (const tab of field.tabs) {\n if (hasRelationshipOrUploadField({ fields: tab.fields })) {\n return true\n }\n }\n }\n }\n\n return false\n}\n\nexport async function migrateRelationshipsV2_V3({\n batchSize,\n req,\n}: {\n batchSize: number\n req: PayloadRequest\n}): Promise<void> {\n const { payload } = req\n const db = payload.db as MongooseAdapter\n const config = payload.config\n\n const session = await getSession(db, req)\n\n for (const collection of payload.config.collections) {\n if (hasRelationshipOrUploadField(collection)) {\n payload.logger.info(`Migrating collection \"${collection.slug}\"`)\n\n const { Model } = getCollection({ adapter: db, collectionSlug: collection.slug })\n\n await migrateModelWithBatching({\n batchSize,\n db,\n fields: collection.fields,\n Model,\n parentIsLocalized: false,\n session,\n })\n\n payload.logger.info(`Migrated collection \"${collection.slug}\"`)\n }\n\n if (collection.versions) {\n payload.logger.info(`Migrating collection versions \"${collection.slug}\"`)\n\n const { Model } = getCollection({\n adapter: db,\n collectionSlug: collection.slug,\n versions: true,\n })\n\n await migrateModelWithBatching({\n batchSize,\n db,\n fields: buildVersionCollectionFields(config, collection),\n Model,\n parentIsLocalized: false,\n session,\n })\n\n payload.logger.info(`Migrated collection versions \"${collection.slug}\"`)\n }\n }\n\n const { globals: GlobalsModel } = db\n\n for (const global of payload.config.globals) {\n if (hasRelationshipOrUploadField(global)) {\n payload.logger.info(`Migrating global \"${global.slug}\"`)\n\n const doc = (await GlobalsModel.findOne(\n {\n globalType: {\n $eq: global.slug,\n },\n },\n {},\n { lean: true, session },\n )) as null | Record<string, unknown>\n\n // in case if the global doesn't exist in the database yet (not saved)\n if (doc) {\n transform({\n adapter: db,\n data: doc,\n fields: global.fields,\n operation: 'write',\n })\n\n await GlobalsModel.collection.updateOne(\n {\n globalType: global.slug,\n },\n { $set: doc },\n { session },\n )\n }\n\n payload.logger.info(`Migrated global \"${global.slug}\"`)\n }\n\n if (global.versions) {\n payload.logger.info(`Migrating global versions \"${global.slug}\"`)\n\n const { Model } = getGlobal({ adapter: db, globalSlug: global.slug, versions: true })\n\n await migrateModelWithBatching({\n batchSize,\n db,\n fields: buildVersionGlobalFields(config, global),\n Model,\n parentIsLocalized: false,\n session,\n })\n\n payload.logger.info(`Migrated global versions \"${global.slug}\"`)\n }\n }\n}\n"],"names":["buildVersionCollectionFields","buildVersionGlobalFields","getCollection","getGlobal","getSession","transform","migrateModelWithBatching","batchSize","db","fields","Model","parentIsLocalized","session","hasNext","skip","docs","find","lean","limit","length","pop","doc","adapter","data","operation","collection","bulkWrite","map","updateOne","filter","_id","update","$set","hasRelationshipOrUploadField","field","type","block","blocks","tab","tabs","migrateRelationshipsV2_V3","req","payload","config","collections","logger","info","slug","collectionSlug","versions","globals","GlobalsModel","global","findOne","globalType","$eq","globalSlug"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Payload, PayloadRequest } from 'payload';
2
+ /**
3
+ * Moves every upload collection's stored image sizes between the legacy `sizes` field and
4
+ * `variants`, on each collection and its versions collection (`version.sizes`). Uses `$rename`,
5
+ * so no document is rewritten beyond the renamed key, and re-keys the indexes on those fields.
6
+ * Documents that are already renamed are left as they are, so it's safe to re-run.
7
+ */
8
+ export declare function migrateSizesToVariants({ direction, payload, req, }: {
9
+ direction?: 'down' | 'up';
10
+ payload: Payload;
11
+ req?: Partial<PayloadRequest>;
12
+ }): Promise<void>;
13
+ //# sourceMappingURL=migrateSizesToVariants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateSizesToVariants.d.ts","sourceRoot":"","sources":["../../src/predefinedMigrations/migrateSizesToVariants.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAqBtD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,SAAgB,EAChB,OAAO,EACP,GAAG,GACJ,EAAE;IACD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;CAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EhB"}
@@ -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