payload 4.0.0-internal.ea6e8f8 → 4.0.0-internal.ec73d44

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 (191) hide show
  1. package/dist/admin/adapters/router.d.ts +1 -1
  2. package/dist/admin/adapters/router.d.ts.map +1 -1
  3. package/dist/admin/adapters/router.js.map +1 -1
  4. package/dist/admin/forms/Diff.d.ts +0 -4
  5. package/dist/admin/forms/Diff.d.ts.map +1 -1
  6. package/dist/admin/forms/Diff.js.map +1 -1
  7. package/dist/admin/getAdminPreferences.js +1 -1
  8. package/dist/admin/getAdminPreferences.js.map +1 -1
  9. package/dist/admin/initAdminContext.js.map +1 -1
  10. package/dist/auth/getFieldsToSign.js.map +1 -1
  11. package/dist/auth/loginWithCookie.js.map +1 -1
  12. package/dist/auth/operations/resetPassword.d.ts.map +1 -1
  13. package/dist/auth/operations/resetPassword.js +50 -1
  14. package/dist/auth/operations/resetPassword.js.map +1 -1
  15. package/dist/auth/serverFunctions/cookies.js.map +1 -1
  16. package/dist/auth/serverFunctions/login.js.map +1 -1
  17. package/dist/auth/types.d.ts.map +1 -1
  18. package/dist/auth/types.js.map +1 -1
  19. package/dist/branching/discard.js +1 -1
  20. package/dist/branching/discard.js.map +1 -1
  21. package/dist/branching/merge/prepareMerge.js +1 -1
  22. package/dist/branching/merge/prepareMerge.js.map +1 -1
  23. package/dist/branching/merge/retryFailedCleanups.js.map +1 -1
  24. package/dist/branching/resolveBranchQuery.d.ts.map +1 -1
  25. package/dist/branching/resolveBranchQuery.js +0 -3
  26. package/dist/branching/resolveBranchQuery.js.map +1 -1
  27. package/dist/branching/sanitizeBranchingConfig.d.ts.map +1 -1
  28. package/dist/branching/sanitizeBranchingConfig.js +0 -3
  29. package/dist/branching/sanitizeBranchingConfig.js.map +1 -1
  30. package/dist/branching/schedule/job.d.ts.map +1 -1
  31. package/dist/branching/schedule/job.js +7 -0
  32. package/dist/branching/schedule/job.js.map +1 -1
  33. package/dist/branching/types.d.ts +4 -13
  34. package/dist/branching/types.d.ts.map +1 -1
  35. package/dist/branching/types.js.map +1 -1
  36. package/dist/cli/commands/data/utilities.d.ts +1 -1
  37. package/dist/cli/commands/data/utilities.d.ts.map +1 -1
  38. package/dist/cli/commands/data/utilities.js.map +1 -1
  39. package/dist/cli/defineCLICommand.js +1 -1
  40. package/dist/cli/defineCLICommand.js.map +1 -1
  41. package/dist/collections/config/client.js.map +1 -1
  42. package/dist/collections/config/types.d.ts +4 -1
  43. package/dist/collections/config/types.d.ts.map +1 -1
  44. package/dist/collections/config/types.js.map +1 -1
  45. package/dist/collections/operations/delete.js.map +1 -1
  46. package/dist/collections/operations/deleteByID.js.map +1 -1
  47. package/dist/collections/operations/findByID.js.map +1 -1
  48. package/dist/collections/operations/findVersionByID.d.ts.map +1 -1
  49. package/dist/collections/operations/findVersionByID.js +11 -0
  50. package/dist/collections/operations/findVersionByID.js.map +1 -1
  51. package/dist/collections/operations/findVersions.d.ts.map +1 -1
  52. package/dist/collections/operations/findVersions.js +11 -0
  53. package/dist/collections/operations/findVersions.js.map +1 -1
  54. package/dist/collections/operations/local/findDistinct.js.map +1 -1
  55. package/dist/collections/operations/renameFile.js +1 -1
  56. package/dist/collections/operations/renameFile.js.map +1 -1
  57. package/dist/collections/operations/update.js.map +1 -1
  58. package/dist/collections/operations/updateByID.js.map +1 -1
  59. package/dist/collections/operations/utilities/update.js +1 -1
  60. package/dist/collections/operations/utilities/update.js.map +1 -1
  61. package/dist/collections/operations/validate.js +4 -4
  62. package/dist/collections/operations/validate.js.map +1 -1
  63. package/dist/config/client.d.ts.map +1 -1
  64. package/dist/config/client.js +1 -0
  65. package/dist/config/client.js.map +1 -1
  66. package/dist/config/defaults.d.ts.map +1 -1
  67. package/dist/config/defaults.js +1 -0
  68. package/dist/config/defaults.js.map +1 -1
  69. package/dist/config/definePlugin.js.map +1 -1
  70. package/dist/config/sanitize.js +2 -2
  71. package/dist/config/sanitize.js.map +1 -1
  72. package/dist/config/types.d.ts +8 -1
  73. package/dist/config/types.d.ts.map +1 -1
  74. package/dist/config/types.js.map +1 -1
  75. package/dist/database/types.d.ts +4 -0
  76. package/dist/database/types.d.ts.map +1 -1
  77. package/dist/database/types.js.map +1 -1
  78. package/dist/exports/build-config.d.ts +9 -0
  79. package/dist/exports/build-config.d.ts.map +1 -0
  80. package/dist/exports/build-config.js +38 -0
  81. package/dist/exports/build-config.js.map +1 -0
  82. package/dist/fields/config/client.js.map +1 -1
  83. package/dist/fields/config/reservedFieldNames.d.ts.map +1 -1
  84. package/dist/fields/config/reservedFieldNames.js.map +1 -1
  85. package/dist/fields/config/types.d.ts.map +1 -1
  86. package/dist/fields/config/types.js.map +1 -1
  87. package/dist/fields/hooks/afterChange/promise.js.map +1 -1
  88. package/dist/fields/hooks/afterRead/promise.js.map +1 -1
  89. package/dist/fields/hooks/beforeChange/flattenValidationData.d.ts +14 -0
  90. package/dist/fields/hooks/beforeChange/flattenValidationData.d.ts.map +1 -0
  91. package/dist/fields/hooks/beforeChange/flattenValidationData.js +36 -0
  92. package/dist/fields/hooks/beforeChange/flattenValidationData.js.map +1 -0
  93. package/dist/fields/hooks/beforeChange/promise.d.ts +2 -1
  94. package/dist/fields/hooks/beforeChange/promise.d.ts.map +1 -1
  95. package/dist/fields/hooks/beforeChange/promise.js +96 -22
  96. package/dist/fields/hooks/beforeChange/promise.js.map +1 -1
  97. package/dist/fields/hooks/beforeChange/traverseFields.d.ts +2 -1
  98. package/dist/fields/hooks/beforeChange/traverseFields.d.ts.map +1 -1
  99. package/dist/fields/hooks/beforeChange/traverseFields.js +2 -1
  100. package/dist/fields/hooks/beforeChange/traverseFields.js.map +1 -1
  101. package/dist/fields/validations.d.ts.map +1 -1
  102. package/dist/fields/validations.js +4 -1
  103. package/dist/fields/validations.js.map +1 -1
  104. package/dist/globals/config/types.d.ts +2 -1
  105. package/dist/globals/config/types.d.ts.map +1 -1
  106. package/dist/globals/config/types.js.map +1 -1
  107. package/dist/globals/operations/findVersionByID.d.ts.map +1 -1
  108. package/dist/globals/operations/findVersionByID.js +7 -0
  109. package/dist/globals/operations/findVersionByID.js.map +1 -1
  110. package/dist/globals/operations/findVersions.d.ts.map +1 -1
  111. package/dist/globals/operations/findVersions.js +5 -0
  112. package/dist/globals/operations/findVersions.js.map +1 -1
  113. package/dist/globals/operations/local/findOne.js.map +1 -1
  114. package/dist/globals/operations/local/update.js.map +1 -1
  115. package/dist/globals/operations/restoreVersion.d.ts +2 -3
  116. package/dist/globals/operations/restoreVersion.d.ts.map +1 -1
  117. package/dist/globals/operations/restoreVersion.js +24 -20
  118. package/dist/globals/operations/restoreVersion.js.map +1 -1
  119. package/dist/globals/operations/validate.js +1 -1
  120. package/dist/globals/operations/validate.js.map +1 -1
  121. package/dist/hierarchy/addHierarchyToCollection.d.ts.map +1 -1
  122. package/dist/hierarchy/addHierarchyToCollection.js +32 -21
  123. package/dist/hierarchy/addHierarchyToCollection.js.map +1 -1
  124. package/dist/hierarchy/createFolderField.js.map +1 -1
  125. package/dist/hierarchy/resolveHierarchyCollections.js +9 -3
  126. package/dist/hierarchy/resolveHierarchyCollections.js.map +1 -1
  127. package/dist/hierarchy/utils/computePaths.d.ts.map +1 -1
  128. package/dist/hierarchy/utils/computePaths.js.map +1 -1
  129. package/dist/index.bundled.d.ts +47 -27
  130. package/dist/llm-instructions/getInstructionsCollection.d.ts.map +1 -1
  131. package/dist/llm-instructions/getInstructionsCollection.js +2 -0
  132. package/dist/llm-instructions/getInstructionsCollection.js.map +1 -1
  133. package/dist/preferences/keys.d.ts +3 -9
  134. package/dist/preferences/keys.d.ts.map +1 -1
  135. package/dist/preferences/keys.js +3 -9
  136. package/dist/preferences/keys.js.map +1 -1
  137. package/dist/preferences/types.d.ts +1 -1
  138. package/dist/preferences/types.js.map +1 -1
  139. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +1 -1
  140. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
  141. package/dist/types/index.d.ts +9 -3
  142. package/dist/types/index.d.ts.map +1 -1
  143. package/dist/types/index.js.map +1 -1
  144. package/dist/uploads/fileVersioning/archive.js.map +1 -1
  145. package/dist/uploads/fileVersioning/cloudStorage.js.map +1 -1
  146. package/dist/uploads/fileVersioning/resolveHistoricalFile.js.map +1 -1
  147. package/dist/uploads/formatFilesize.js +1 -1
  148. package/dist/uploads/formatFilesize.js.map +1 -1
  149. package/dist/uploads/generateFileData.d.ts.map +1 -1
  150. package/dist/uploads/generateFileData.js.map +1 -1
  151. package/dist/uploads/getFileContentRequirement.js.map +1 -1
  152. package/dist/uploads/getFileFromUploadInstructions.js.map +1 -1
  153. package/dist/uploads/safeFetch.js.map +1 -1
  154. package/dist/uploads/stagedUpload.js.map +1 -1
  155. package/dist/uploads/transformers/handleDynamicFileRequest.js +11 -2
  156. package/dist/uploads/transformers/handleDynamicFileRequest.js.map +1 -1
  157. package/dist/utilities/addSelectGenericsToGeneretedTypes.d.ts.map +1 -1
  158. package/dist/utilities/addSelectGenericsToGeneretedTypes.js +0 -1
  159. package/dist/utilities/addSelectGenericsToGeneretedTypes.js.map +1 -1
  160. package/dist/utilities/appendDateTimezoneSelectFields.js.map +1 -1
  161. package/dist/utilities/cloneValidationRequest.js.map +1 -1
  162. package/dist/utilities/createPayloadRequest.js.map +1 -1
  163. package/dist/utilities/deepCopyObject.js.map +1 -1
  164. package/dist/utilities/documentMatchingWhereExists.js +1 -1
  165. package/dist/utilities/documentMatchingWhereExists.js.map +1 -1
  166. package/dist/utilities/entityInputSchema/validateEntityData.d.ts.map +1 -1
  167. package/dist/utilities/entityInputSchema/validateEntityData.js.map +1 -1
  168. package/dist/utilities/filterDataToSelectedLocales.js.map +1 -1
  169. package/dist/utilities/getEntityPermissions/getEntityPermissions.d.ts.map +1 -1
  170. package/dist/utilities/getEntityPermissions/getEntityPermissions.js +1 -0
  171. package/dist/utilities/getEntityPermissions/getEntityPermissions.js.map +1 -1
  172. package/dist/utilities/getEntityPermissions/populateFieldPermissions.js.map +1 -1
  173. package/dist/utilities/getVersionsConfig.d.ts +4 -0
  174. package/dist/utilities/getVersionsConfig.d.ts.map +1 -1
  175. package/dist/utilities/getVersionsConfig.js +5 -0
  176. package/dist/utilities/getVersionsConfig.js.map +1 -1
  177. package/dist/utilities/parseParams/index.js.map +1 -1
  178. package/dist/utilities/parseValidationLocale.js.map +1 -1
  179. package/dist/utilities/sanitizePopulateParam.js.map +1 -1
  180. package/dist/utilities/telemetry/conf/index.d.ts +4 -1
  181. package/dist/utilities/telemetry/conf/index.d.ts.map +1 -1
  182. package/dist/utilities/telemetry/conf/index.js.map +1 -1
  183. package/dist/utilities/telemetry/featureInfo/getFeatureInfo.js.map +1 -1
  184. package/dist/versions/allLocalesPublicationStatus.js.map +1 -1
  185. package/dist/versions/isInheritedReadVersionsAccess.js.map +1 -1
  186. package/dist/versions/types.d.ts +2 -0
  187. package/dist/versions/types.d.ts.map +1 -1
  188. package/dist/versions/types.js.map +1 -1
  189. package/package.json +30 -28
  190. package/skills/payload/reference/ENDPOINTS.md +3 -9
  191. package/skills/payload/reference/PLUGIN-DEVELOPMENT.md +4 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/branching/discard.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from '../types/index.js'\nimport type { BranchOperation } from './types.js'\n\nimport { deleteUploadFilesExclusiveToDocument } from '../uploads/deleteUploadFilesExclusiveToDocument.js'\nimport {\n collectStoredFiles,\n scheduleUnreferencedFileCleanup,\n} from '../uploads/fileVersioning/cleanup.js'\nimport { commitTransaction } from '../utilities/commitTransaction.js'\nimport { createPayloadRequest } from '../utilities/createPayloadRequest.js'\nimport { initTransaction } from '../utilities/initTransaction.js'\nimport { killTransaction } from '../utilities/killTransaction.js'\nimport {\n beginDeferredCleanupScope,\n clearDeferredCleanupScope,\n flushDeferredCleanupScope,\n} from '../utilities/transactionCallbacks.js'\nimport { assertBranchActionAccess } from './assertBranchActionAccess.js'\nimport { assertBranchCreatedDocumentsUnreferenced } from './assertBranchCreatedDocumentsUnreferenced.js'\nimport { assertBranchWritable } from './assertBranchWritable.js'\nimport { refreshBranchState, resetBranchState, withoutBranch } from './resolveBranch.js'\nimport { selectBranchChanges } from './selectBranchChanges.js'\nimport {\n branchChangesCollectionSlug,\n branchDocIDField,\n branchesCollectionSlug,\n branchField,\n branchParentField,\n MAIN_BRANCH,\n} from './types.js'\nimport { deleteBranchGlobalVersionChain, deleteBranchVersionChain } from './versions.js'\n\nexport type DiscardedChange = {\n changeID: number | string\n /** Absent for a global. */\n collectionSlug?: string\n /** Absent for a global. */\n docID?: number | string\n entityType: 'collection' | 'global'\n globalSlug?: string\n operation: BranchOperation\n}\n\nexport type DiscardResult = {\n discarded: DiscardedChange[]\n}\n\nexport type DiscardOptions = {\n branch: string\n /** Change IDs to discard. Omit to discard everything pending on the branch. */\n changes?: (number | string)[]\n /**\n * Skip branch read and discard access checks.\n *\n * @default false\n */\n overrideAccess?: boolean\n req?: PayloadRequest\n user?: NonNullable<PayloadRequest['user']>\n}\n\ntype DiscardInternalOptions = {\n shouldCheckBranchWritable: boolean\n} & DiscardOptions\n\n/**\n * Throws away a branch's changes, returning the documents to main's state.\n *\n * The mirror of merge, and structurally simpler: merge has to reconcile with\n * production, while discard only has to forget. Every operation reduces to the same\n * act — drop the branch's row — because the branch's row *is* the change:\n *\n * - **create** — the row is the document, so dropping it removes it from the branch.\n * - **update** — the row is the branch's copy, so dropping it makes the branch read\n * through to main again.\n * - **delete** — the row is the tombstone, so dropping it un-hides main's document.\n *\n * Nothing on `main` is touched in any of the three, which is why this needs no\n * per-document preflight the way merge does (§13): a branch is a proposal, and\n * withdrawing a proposal is not a production write.\n *\n * Before a branch-created row is removed, reference checks verify that no surviving\n * document, global or version still points to it. Rows removed by the same discard\n * are excluded from that check.\n */\nexport const discardBranchChanges = async (\n payload: Payload,\n options: DiscardOptions,\n): Promise<DiscardResult> =>\n discardBranchChangesInternal(payload, { ...options, shouldCheckBranchWritable: true })\n\n/** Removes all state for a branch that its owning collection row is about to delete. */\nexport const discardBranchChangesBeforeBranchDeletion = async (\n payload: Payload,\n { branch, req }: Pick<DiscardOptions, 'branch' | 'req'>,\n): Promise<DiscardResult> =>\n discardBranchChangesInternal(payload, {\n branch,\n overrideAccess: true,\n req,\n shouldCheckBranchWritable: false,\n })\n\nconst discardBranchChangesInternal = async (\n payload: Payload,\n {\n branch,\n changes: selected,\n overrideAccess = false,\n req: incomingReq,\n shouldCheckBranchWritable,\n user,\n }: DiscardInternalOptions,\n): Promise<DiscardResult> => {\n // `branch: false` throughout, as with merge: the rows being dropped are addressed\n // by their real primary keys, so the read predicate must not be in the way.\n const req = incomingReq\n ? withoutBranch(incomingReq)\n : await createPayloadRequest({ branch: false, payload, user })\n\n if (user && !req.user) {\n req.user = user\n }\n\n const branchDocs = await payload.find({\n collection: branchesCollectionSlug,\n limit: 1,\n overrideAccess,\n pagination: false,\n req,\n where: { slug: { equals: branch } },\n })\n\n if (!branchDocs.docs[0]) {\n throw new Error(`Branch \"${branch}\" was not found.`)\n }\n\n const branchDoc = branchDocs.docs[0]\n\n if (!overrideAccess) {\n await assertBranchActionAccess({ action: 'discardBranch', branchDoc, req })\n }\n\n // Discarding is a write, so a closed branch refuses it — its archive is a record,\n // and a record that can be edited is not one.\n if (shouldCheckBranchWritable) {\n await assertBranchWritable({ branch, req })\n }\n\n const allChanges = await payload.find({\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n pagination: false,\n req,\n sort: 'createdAt',\n where: {\n branch: { equals: branch },\n },\n })\n\n const applicable = selectBranchChanges({ changes: allChanges.docs, selected })\n\n const result: DiscardResult = { discarded: [] }\n\n if (!applicable.length) {\n return result\n }\n\n // Gated on `req.transactionID`, not on whether a `req` was passed in: a discard\n // triggered over HTTP hands in a `req` of its own that has no transaction on it\n // yet, and it must get one just as much as a Local API call would.\n const shouldCommit = await initTransaction(req)\n const cleanupScope = await beginDeferredCleanupScope({ req })\n const uploadCleanupPlans: {\n collectionSlug: string\n retainedDoc: null | Record<string, unknown>\n sourceDoc: Record<string, unknown>\n }[] = []\n const plannedUploadIdentities = new Set<string>()\n\n try {\n const shadowsByChangeID = new Map<string, null | Record<string, unknown>>()\n const ignoredGlobalOwnerBranches = new Map<string, Set<string>>()\n const ignoredOwnerRowIDs = new Map<string, Set<number | string>>()\n\n for (const change of applicable) {\n if (change.entityType === 'global') {\n if (typeof change.globalSlug === 'string') {\n ignoredGlobalOwnerBranches.set(change.globalSlug, new Set([branch]))\n }\n\n continue\n }\n\n const collectionSlug = change.collectionSlug as string\n const docID = (change.doc as { value?: number | string })?.value ?? change.doc\n const shadow = (await payload.db.findOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: {\n and: [\n { [branchField]: { equals: branch } },\n { or: [{ id: { equals: docID } }, { [branchDocIDField]: { equals: docID } }] },\n ],\n },\n })) as null | Record<string, unknown>\n\n shadowsByChangeID.set(String(change.id), shadow)\n\n if (shadow?.id !== undefined && shadow.id !== null) {\n const ignoredIDs = ignoredOwnerRowIDs.get(collectionSlug) ?? new Set<number | string>()\n\n ignoredIDs.add(shadow.id as number | string)\n ignoredOwnerRowIDs.set(collectionSlug, ignoredIDs)\n }\n }\n\n await assertBranchCreatedDocumentsUnreferenced({\n ignoredGlobalOwnerBranches,\n ignoredOwnerBranch: selected ? undefined : branch,\n ignoredOwnerRowIDs,\n req,\n targets: applicable.flatMap((change) => {\n if (\n change.entityType === 'global' ||\n change.operation !== 'create' ||\n typeof change.collectionSlug !== 'string'\n ) {\n return []\n }\n\n const docID = (change.doc as { value?: number | string })?.value ?? change.doc\n\n return typeof docID === 'number' || typeof docID === 'string'\n ? [{ collectionSlug: change.collectionSlug, docID }]\n : []\n }),\n })\n\n for (const change of applicable) {\n // A global has no shadow row to look up and no tombstone to undo: its branch copy\n // *is* the change, so dropping the copy is the entire discard, and the branch reads\n // through to main again immediately.\n if (change.entityType === 'global') {\n const globalSlug = change.globalSlug as string\n\n if (!payload.db.deleteBranchGlobal) {\n throw new Error(\n `The database adapter cannot remove a branch's copy of a global, so \"${globalSlug}\" cannot be discarded.`,\n )\n }\n\n await deleteBranchGlobalVersionChain({ branch, globalSlug, payload, req })\n await payload.db.deleteBranchGlobal({ branch, globalSlug, req })\n\n await payload.delete({\n id: change.id,\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n req,\n })\n\n result.discarded.push({\n changeID: change.id,\n entityType: 'global',\n globalSlug,\n operation: 'update',\n })\n\n continue\n }\n\n const collectionSlug = change.collectionSlug as string\n const docID = (change.doc as { value?: number | string })?.value ?? change.doc\n const shadow = shadowsByChangeID.get(String(change.id))\n\n if (shadow) {\n const collectionConfig = payload.collections[collectionSlug]!.config\n\n if (collectionConfig.upload) {\n const retainedDoc =\n change.operation === 'create'\n ? null\n : ((await payload.db.findOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: {\n and: [{ [branchField]: { equals: MAIN_BRANCH } }, { id: { equals: docID } }],\n },\n })) as null | Record<string, unknown>)\n const versionDocuments = await readBranchVersionDocuments({\n branch,\n collectionSlug,\n payload,\n req,\n rowID: shadow.id as number | string,\n })\n const sourceDocuments =\n change.operation === 'create' ? versionDocuments : [shadow, ...versionDocuments]\n\n if (change.operation === 'create') {\n plannedUploadIdentities.add(`${collectionSlug}:${getUploadIdentity(shadow)}`)\n }\n\n for (const sourceDoc of sourceDocuments) {\n const identity = `${collectionSlug}:${getUploadIdentity(sourceDoc)}`\n\n if (!plannedUploadIdentities.has(identity)) {\n plannedUploadIdentities.add(identity)\n uploadCleanupPlans.push({ collectionSlug, retainedDoc, sourceDoc })\n }\n }\n }\n\n if (change.operation === 'create') {\n await payload.delete({\n id: shadow.id as number | string,\n branch: false,\n collection: collectionSlug,\n overrideAccess: true,\n req,\n trash: true,\n })\n } else {\n await deleteBranchVersionChain({\n branch,\n collectionSlug,\n payload,\n req,\n rowID: shadow.id as number | string,\n })\n\n await payload.db.deleteOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: { id: { equals: shadow.id } },\n })\n }\n }\n\n await payload.delete({\n id: change.id,\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n req,\n })\n\n result.discarded.push({\n changeID: change.id,\n collectionSlug,\n docID: docID as number | string,\n entityType: 'collection',\n operation: change.operation as BranchOperation,\n })\n }\n\n for (const { collectionSlug, retainedDoc, sourceDoc } of uploadCleanupPlans) {\n const collectionConfig = payload.collections[collectionSlug]!.config\n const candidates = await collectStoredFiles({\n collection: collectionConfig,\n doc: sourceDoc,\n req,\n })\n\n if (candidates.length) {\n await scheduleUnreferencedFileCleanup({ candidates, collection: collectionConfig, req })\n\n if (!collectionConfig.upload.fileOperations) {\n await collectionConfig.upload.deleteFiles?.({ req, retainedDoc, sourceDoc })\n }\n } else {\n await deleteUploadFilesExclusiveToDocument({\n collectionConfig,\n config: payload.config,\n req,\n retainedDoc,\n sourceDoc,\n })\n }\n }\n\n if (cleanupScope) {\n await flushDeferredCleanupScope({ req, scope: cleanupScope })\n }\n if (shouldCommit) {\n await commitTransaction(req)\n }\n } catch (error) {\n if (cleanupScope) {\n clearDeferredCleanupScope({ req, scope: cleanupScope })\n }\n\n if (shouldCommit) {\n await killTransaction(req)\n }\n throw error\n } finally {\n if (incomingReq) {\n refreshBranchState(incomingReq)\n }\n }\n\n // The manifest this request memoized still lists the discarded documents as\n // shadowed, which would hide main's copies from any later read on this request.\n resetBranchState(req)\n\n return result\n}\n\nconst readBranchVersionDocuments = async ({\n branch,\n collectionSlug,\n payload,\n req,\n rowID,\n}: {\n branch: string\n collectionSlug: string\n payload: Payload\n req: PayloadRequest\n rowID: number | string\n}): Promise<Record<string, unknown>[]> => {\n if (!payload.collections[collectionSlug]?.config.versions) {\n return []\n }\n\n const { docs } = await payload.db.findVersions({\n branch: false,\n collection: collectionSlug,\n limit: 0,\n pagination: false,\n req,\n where: {\n and: [\n { parent: { equals: rowID } },\n { [branchField]: { equals: branch } },\n { [branchParentField]: { exists: true } },\n ],\n },\n })\n\n return docs.flatMap((version) =>\n version.version && typeof version.version === 'object' && !Array.isArray(version.version)\n ? [version.version as Record<string, unknown>]\n : [],\n )\n}\n\nconst getUploadIdentity = (doc: Record<string, unknown>): string => {\n const variantFilenames =\n doc.variants && typeof doc.variants === 'object' && !Array.isArray(doc.variants)\n ? Object.entries(doc.variants)\n .flatMap(([name, variant]) => {\n if (!variant || typeof variant !== 'object' || Array.isArray(variant)) {\n return []\n }\n\n const filename = (variant as Record<string, unknown>).filename\n\n return typeof filename === 'string' ? [[name, filename] as [string, string]] : []\n })\n .sort(([left], [right]) => left.localeCompare(right))\n : []\n\n return JSON.stringify({\n filename: doc.filename,\n objectKey: doc._objectKey,\n prefix: doc.prefix,\n variants: variantFilenames,\n })\n}\n"],"names":["deleteUploadFilesExclusiveToDocument","collectStoredFiles","scheduleUnreferencedFileCleanup","commitTransaction","createPayloadRequest","initTransaction","killTransaction","beginDeferredCleanupScope","clearDeferredCleanupScope","flushDeferredCleanupScope","assertBranchActionAccess","assertBranchCreatedDocumentsUnreferenced","assertBranchWritable","refreshBranchState","resetBranchState","withoutBranch","selectBranchChanges","branchChangesCollectionSlug","branchDocIDField","branchesCollectionSlug","branchField","branchParentField","MAIN_BRANCH","deleteBranchGlobalVersionChain","deleteBranchVersionChain","discardBranchChanges","payload","options","discardBranchChangesInternal","shouldCheckBranchWritable","discardBranchChangesBeforeBranchDeletion","branch","req","overrideAccess","changes","selected","incomingReq","user","branchDocs","find","collection","limit","pagination","where","slug","equals","docs","Error","branchDoc","action","allChanges","sort","applicable","result","discarded","length","shouldCommit","cleanupScope","uploadCleanupPlans","plannedUploadIdentities","Set","shadowsByChangeID","Map","ignoredGlobalOwnerBranches","ignoredOwnerRowIDs","change","entityType","globalSlug","set","collectionSlug","docID","doc","value","shadow","db","findOne","and","or","id","String","undefined","ignoredIDs","get","add","ignoredOwnerBranch","targets","flatMap","operation","deleteBranchGlobal","delete","push","changeID","collectionConfig","collections","config","upload","retainedDoc","versionDocuments","readBranchVersionDocuments","rowID","sourceDocuments","getUploadIdentity","sourceDoc","identity","has","trash","deleteOne","candidates","fileOperations","deleteFiles","scope","error","versions","findVersions","parent","exists","version","Array","isArray","variantFilenames","variants","Object","entries","name","variant","filename","left","right","localeCompare","JSON","stringify","objectKey","_objectKey","prefix"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/branching/discard.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from '../types/index.js'\nimport type { BranchOperation } from './types.js'\n\nimport { deleteUploadFilesExclusiveToDocument } from '../uploads/deleteUploadFilesExclusiveToDocument.js'\nimport {\n collectStoredFiles,\n scheduleUnreferencedFileCleanup,\n} from '../uploads/fileVersioning/cleanup.js'\nimport { commitTransaction } from '../utilities/commitTransaction.js'\nimport { createPayloadRequest } from '../utilities/createPayloadRequest.js'\nimport { initTransaction } from '../utilities/initTransaction.js'\nimport { killTransaction } from '../utilities/killTransaction.js'\nimport {\n beginDeferredCleanupScope,\n clearDeferredCleanupScope,\n flushDeferredCleanupScope,\n} from '../utilities/transactionCallbacks.js'\nimport { assertBranchActionAccess } from './assertBranchActionAccess.js'\nimport { assertBranchCreatedDocumentsUnreferenced } from './assertBranchCreatedDocumentsUnreferenced.js'\nimport { assertBranchWritable } from './assertBranchWritable.js'\nimport { refreshBranchState, resetBranchState, withoutBranch } from './resolveBranch.js'\nimport { selectBranchChanges } from './selectBranchChanges.js'\nimport {\n branchChangesCollectionSlug,\n branchDocIDField,\n branchesCollectionSlug,\n branchField,\n branchParentField,\n MAIN_BRANCH,\n} from './types.js'\nimport { deleteBranchGlobalVersionChain, deleteBranchVersionChain } from './versions.js'\n\nexport type DiscardedChange = {\n changeID: number | string\n /** Absent for a global. */\n collectionSlug?: string\n /** Absent for a global. */\n docID?: number | string\n entityType: 'collection' | 'global'\n globalSlug?: string\n operation: BranchOperation\n}\n\nexport type DiscardResult = {\n discarded: DiscardedChange[]\n}\n\nexport type DiscardOptions = {\n branch: string\n /** Change IDs to discard. Omit to discard everything pending on the branch. */\n changes?: (number | string)[]\n /**\n * Skip branch read and discard access checks.\n *\n * @default false\n */\n overrideAccess?: boolean\n req?: PayloadRequest\n user?: NonNullable<PayloadRequest['user']>\n}\n\ntype DiscardInternalOptions = {\n shouldCheckBranchWritable: boolean\n} & DiscardOptions\n\n/**\n * Throws away a branch's changes, returning the documents to main's state.\n *\n * The mirror of merge, and structurally simpler: merge has to reconcile with\n * production, while discard only has to forget. Every operation reduces to the same\n * act — drop the branch's row — because the branch's row *is* the change:\n *\n * - **create** — the row is the document, so dropping it removes it from the branch.\n * - **update** — the row is the branch's copy, so dropping it makes the branch read\n * through to main again.\n * - **delete** — the row is the tombstone, so dropping it un-hides main's document.\n *\n * Nothing on `main` is touched in any of the three, which is why this needs no\n * per-document preflight the way merge does (§13): a branch is a proposal, and\n * withdrawing a proposal is not a production write.\n *\n * Before a branch-created row is removed, reference checks verify that no surviving\n * document, global or version still points to it. Rows removed by the same discard\n * are excluded from that check.\n */\nexport const discardBranchChanges = async (\n payload: Payload,\n options: DiscardOptions,\n): Promise<DiscardResult> =>\n discardBranchChangesInternal(payload, { ...options, shouldCheckBranchWritable: true })\n\n/** Removes all state for a branch that its owning collection row is about to delete. */\nexport const discardBranchChangesBeforeBranchDeletion = async (\n payload: Payload,\n { branch, req }: Pick<DiscardOptions, 'branch' | 'req'>,\n): Promise<DiscardResult> =>\n discardBranchChangesInternal(payload, {\n branch,\n overrideAccess: true,\n req,\n shouldCheckBranchWritable: false,\n })\n\nconst discardBranchChangesInternal = async (\n payload: Payload,\n {\n branch,\n changes: selected,\n overrideAccess = false,\n req: incomingReq,\n shouldCheckBranchWritable,\n user,\n }: DiscardInternalOptions,\n): Promise<DiscardResult> => {\n // `branch: false` throughout, as with merge: the rows being dropped are addressed\n // by their real primary keys, so the read predicate must not be in the way.\n const req = incomingReq\n ? withoutBranch(incomingReq)\n : await createPayloadRequest({ branch: false, payload, user })\n\n if (user) {\n req.user = user\n }\n\n const branchDocs = await payload.find({\n collection: branchesCollectionSlug,\n limit: 1,\n overrideAccess,\n pagination: false,\n req,\n where: { slug: { equals: branch } },\n })\n\n if (!branchDocs.docs[0]) {\n throw new Error(`Branch \"${branch}\" was not found.`)\n }\n\n const branchDoc = branchDocs.docs[0]\n\n if (!overrideAccess) {\n await assertBranchActionAccess({ action: 'discardBranch', branchDoc, req })\n }\n\n // Discarding is a write, so a closed branch refuses it — its archive is a record,\n // and a record that can be edited is not one.\n if (shouldCheckBranchWritable) {\n await assertBranchWritable({ branch, req })\n }\n\n const allChanges = await payload.find({\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n pagination: false,\n req,\n sort: 'createdAt',\n where: {\n branch: { equals: branch },\n },\n })\n\n const applicable = selectBranchChanges({ changes: allChanges.docs, selected })\n\n const result: DiscardResult = { discarded: [] }\n\n if (!applicable.length) {\n return result\n }\n\n // Gated on `req.transactionID`, not on whether a `req` was passed in: a discard\n // triggered over HTTP hands in a `req` of its own that has no transaction on it\n // yet, and it must get one just as much as a Local API call would.\n const shouldCommit = await initTransaction(req)\n const cleanupScope = await beginDeferredCleanupScope({ req })\n const uploadCleanupPlans: {\n collectionSlug: string\n retainedDoc: null | Record<string, unknown>\n sourceDoc: Record<string, unknown>\n }[] = []\n const plannedUploadIdentities = new Set<string>()\n\n try {\n const shadowsByChangeID = new Map<string, null | Record<string, unknown>>()\n const ignoredGlobalOwnerBranches = new Map<string, Set<string>>()\n const ignoredOwnerRowIDs = new Map<string, Set<number | string>>()\n\n for (const change of applicable) {\n if (change.entityType === 'global') {\n if (typeof change.globalSlug === 'string') {\n ignoredGlobalOwnerBranches.set(change.globalSlug, new Set([branch]))\n }\n\n continue\n }\n\n const collectionSlug = change.collectionSlug as string\n const docID = (change.doc as { value?: number | string })?.value ?? change.doc\n const shadow = (await payload.db.findOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: {\n and: [\n { [branchField]: { equals: branch } },\n { or: [{ id: { equals: docID } }, { [branchDocIDField]: { equals: docID } }] },\n ],\n },\n })) as null | Record<string, unknown>\n\n shadowsByChangeID.set(String(change.id), shadow)\n\n if (shadow?.id !== undefined && shadow.id !== null) {\n const ignoredIDs = ignoredOwnerRowIDs.get(collectionSlug) ?? new Set<number | string>()\n\n ignoredIDs.add(shadow.id as number | string)\n ignoredOwnerRowIDs.set(collectionSlug, ignoredIDs)\n }\n }\n\n await assertBranchCreatedDocumentsUnreferenced({\n ignoredGlobalOwnerBranches,\n ignoredOwnerBranch: selected ? undefined : branch,\n ignoredOwnerRowIDs,\n req,\n targets: applicable.flatMap((change) => {\n if (\n change.entityType === 'global' ||\n change.operation !== 'create' ||\n typeof change.collectionSlug !== 'string'\n ) {\n return []\n }\n\n const docID = (change.doc as { value?: number | string })?.value ?? change.doc\n\n return typeof docID === 'number' || typeof docID === 'string'\n ? [{ collectionSlug: change.collectionSlug, docID }]\n : []\n }),\n })\n\n for (const change of applicable) {\n // A global has no shadow row to look up and no tombstone to undo: its branch copy\n // *is* the change, so dropping the copy is the entire discard, and the branch reads\n // through to main again immediately.\n if (change.entityType === 'global') {\n const globalSlug = change.globalSlug as string\n\n if (!payload.db.deleteBranchGlobal) {\n throw new Error(\n `The database adapter cannot remove a branch's copy of a global, so \"${globalSlug}\" cannot be discarded.`,\n )\n }\n\n await deleteBranchGlobalVersionChain({ branch, globalSlug, payload, req })\n await payload.db.deleteBranchGlobal({ branch, globalSlug, req })\n\n await payload.delete({\n id: change.id,\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n req,\n })\n\n result.discarded.push({\n changeID: change.id,\n entityType: 'global',\n globalSlug,\n operation: 'update',\n })\n\n continue\n }\n\n const collectionSlug = change.collectionSlug as string\n const docID = (change.doc as { value?: number | string })?.value ?? change.doc\n const shadow = shadowsByChangeID.get(String(change.id))\n\n if (shadow) {\n const collectionConfig = payload.collections[collectionSlug]!.config\n\n if (collectionConfig.upload) {\n const retainedDoc =\n change.operation === 'create'\n ? null\n : ((await payload.db.findOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: {\n and: [{ [branchField]: { equals: MAIN_BRANCH } }, { id: { equals: docID } }],\n },\n })) as null | Record<string, unknown>)\n const versionDocuments = await readBranchVersionDocuments({\n branch,\n collectionSlug,\n payload,\n req,\n rowID: shadow.id as number | string,\n })\n const sourceDocuments =\n change.operation === 'create' ? versionDocuments : [shadow, ...versionDocuments]\n\n if (change.operation === 'create') {\n plannedUploadIdentities.add(`${collectionSlug}:${getUploadIdentity(shadow)}`)\n }\n\n for (const sourceDoc of sourceDocuments) {\n const identity = `${collectionSlug}:${getUploadIdentity(sourceDoc)}`\n\n if (!plannedUploadIdentities.has(identity)) {\n plannedUploadIdentities.add(identity)\n uploadCleanupPlans.push({ collectionSlug, retainedDoc, sourceDoc })\n }\n }\n }\n\n if (change.operation === 'create') {\n await payload.delete({\n id: shadow.id as number | string,\n branch: false,\n collection: collectionSlug,\n overrideAccess: true,\n req,\n trash: true,\n })\n } else {\n await deleteBranchVersionChain({\n branch,\n collectionSlug,\n payload,\n req,\n rowID: shadow.id as number | string,\n })\n\n await payload.db.deleteOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: { id: { equals: shadow.id } },\n })\n }\n }\n\n await payload.delete({\n id: change.id,\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n req,\n })\n\n result.discarded.push({\n changeID: change.id,\n collectionSlug,\n docID: docID as number | string,\n entityType: 'collection',\n operation: change.operation as BranchOperation,\n })\n }\n\n for (const { collectionSlug, retainedDoc, sourceDoc } of uploadCleanupPlans) {\n const collectionConfig = payload.collections[collectionSlug]!.config\n const candidates = await collectStoredFiles({\n collection: collectionConfig,\n doc: sourceDoc,\n req,\n })\n\n if (candidates.length) {\n await scheduleUnreferencedFileCleanup({ candidates, collection: collectionConfig, req })\n\n if (!collectionConfig.upload.fileOperations) {\n await collectionConfig.upload.deleteFiles?.({ req, retainedDoc, sourceDoc })\n }\n } else {\n await deleteUploadFilesExclusiveToDocument({\n collectionConfig,\n config: payload.config,\n req,\n retainedDoc,\n sourceDoc,\n })\n }\n }\n\n if (cleanupScope) {\n await flushDeferredCleanupScope({ req, scope: cleanupScope })\n }\n if (shouldCommit) {\n await commitTransaction(req)\n }\n } catch (error) {\n if (cleanupScope) {\n clearDeferredCleanupScope({ req, scope: cleanupScope })\n }\n\n if (shouldCommit) {\n await killTransaction(req)\n }\n throw error\n } finally {\n if (incomingReq) {\n refreshBranchState(incomingReq)\n }\n }\n\n // The manifest this request memoized still lists the discarded documents as\n // shadowed, which would hide main's copies from any later read on this request.\n resetBranchState(req)\n\n return result\n}\n\nconst readBranchVersionDocuments = async ({\n branch,\n collectionSlug,\n payload,\n req,\n rowID,\n}: {\n branch: string\n collectionSlug: string\n payload: Payload\n req: PayloadRequest\n rowID: number | string\n}): Promise<Record<string, unknown>[]> => {\n if (!payload.collections[collectionSlug]?.config.versions) {\n return []\n }\n\n const { docs } = await payload.db.findVersions({\n branch: false,\n collection: collectionSlug,\n limit: 0,\n pagination: false,\n req,\n where: {\n and: [\n { parent: { equals: rowID } },\n { [branchField]: { equals: branch } },\n { [branchParentField]: { exists: true } },\n ],\n },\n })\n\n return docs.flatMap((version) =>\n version.version && typeof version.version === 'object' && !Array.isArray(version.version)\n ? [version.version as Record<string, unknown>]\n : [],\n )\n}\n\nconst getUploadIdentity = (doc: Record<string, unknown>): string => {\n const variantFilenames =\n doc.variants && typeof doc.variants === 'object' && !Array.isArray(doc.variants)\n ? Object.entries(doc.variants)\n .flatMap(([name, variant]) => {\n if (!variant || typeof variant !== 'object' || Array.isArray(variant)) {\n return []\n }\n\n const filename = (variant as Record<string, unknown>).filename\n\n return typeof filename === 'string' ? [[name, filename] as [string, string]] : []\n })\n .sort(([left], [right]) => left.localeCompare(right))\n : []\n\n return JSON.stringify({\n filename: doc.filename,\n objectKey: doc._objectKey,\n prefix: doc.prefix,\n variants: variantFilenames,\n })\n}\n"],"names":["deleteUploadFilesExclusiveToDocument","collectStoredFiles","scheduleUnreferencedFileCleanup","commitTransaction","createPayloadRequest","initTransaction","killTransaction","beginDeferredCleanupScope","clearDeferredCleanupScope","flushDeferredCleanupScope","assertBranchActionAccess","assertBranchCreatedDocumentsUnreferenced","assertBranchWritable","refreshBranchState","resetBranchState","withoutBranch","selectBranchChanges","branchChangesCollectionSlug","branchDocIDField","branchesCollectionSlug","branchField","branchParentField","MAIN_BRANCH","deleteBranchGlobalVersionChain","deleteBranchVersionChain","discardBranchChanges","payload","options","discardBranchChangesInternal","shouldCheckBranchWritable","discardBranchChangesBeforeBranchDeletion","branch","req","overrideAccess","changes","selected","incomingReq","user","branchDocs","find","collection","limit","pagination","where","slug","equals","docs","Error","branchDoc","action","allChanges","sort","applicable","result","discarded","length","shouldCommit","cleanupScope","uploadCleanupPlans","plannedUploadIdentities","Set","shadowsByChangeID","Map","ignoredGlobalOwnerBranches","ignoredOwnerRowIDs","change","entityType","globalSlug","set","collectionSlug","docID","doc","value","shadow","db","findOne","and","or","id","String","undefined","ignoredIDs","get","add","ignoredOwnerBranch","targets","flatMap","operation","deleteBranchGlobal","delete","push","changeID","collectionConfig","collections","config","upload","retainedDoc","versionDocuments","readBranchVersionDocuments","rowID","sourceDocuments","getUploadIdentity","sourceDoc","identity","has","trash","deleteOne","candidates","fileOperations","deleteFiles","scope","error","versions","findVersions","parent","exists","version","Array","isArray","variantFilenames","variants","Object","entries","name","variant","filename","left","right","localeCompare","JSON","stringify","objectKey","_objectKey","prefix"],"mappings":"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"}
@@ -14,7 +14,7 @@ export const prepareMerge = async ({ branch, dryRun, incomingReq, overrideAccess
14
14
  payload,
15
15
  user
16
16
  });
17
- if (user && !req.user) {
17
+ if (user) {
18
18
  req.user = user;
19
19
  }
20
20
  const branchDocs = await payload.find({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/branching/merge/prepareMerge.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from '../../types/index.js'\nimport type { MergeResult } from '../merge.js'\nimport type { BranchOperation, MergeableChange, MergeWarning } from '../types.js'\nimport type { BranchMergeValidationError } from '../validation.js'\n\nimport { createPayloadRequest } from '../../utilities/createPayloadRequest.js'\nimport { assertBranchActionAccess } from '../assertBranchActionAccess.js'\nimport { resolveEffectiveOperations } from '../effectiveOperations.js'\nimport {\n runGlobalMergePreflight,\n runMergeDependencyPreflight,\n runMergePreflight,\n} from '../preflight.js'\nimport { withoutBranch } from '../resolveBranch.js'\nimport { selectBranchChanges } from '../selectBranchChanges.js'\nimport {\n branchChangesCollectionSlug,\n branchesCollectionSlug,\n branchField,\n MAIN_BRANCH,\n} from '../types.js'\nimport {\n createBranchMergeValidationRequest,\n createMainBranchRequest,\n prepareBranchMergeValidationCandidates,\n} from '../validation.js'\nimport { inspectFailedCleanups } from './retryFailedCleanups.js'\nimport { changeDocID } from './utilities.js'\n\nexport type PreparedBranchChange = {\n doc?: unknown\n id: number | string\n} & Record<string, unknown>\n\nexport type PreparedMerge = {\n applicable: PreparedBranchChange[]\n applicableGlobals: PreparedBranchChange[]\n branchDoc: { id: number | string }\n mergeable: MergeableChange[]\n req: PayloadRequest\n result: MergeResult\n retryableCleanups: MergeableChange[]\n}\n\nexport const prepareMerge = async ({\n branch,\n dryRun,\n incomingReq,\n overrideAccess,\n payload,\n selected,\n user,\n}: {\n branch: string\n dryRun: boolean\n incomingReq?: PayloadRequest\n overrideAccess: boolean\n payload: Payload\n selected?: (number | string)[]\n user?: NonNullable<PayloadRequest['user']>\n}): Promise<PreparedMerge> => {\n const req = incomingReq\n ? withoutBranch(incomingReq)\n : await createPayloadRequest({ branch: false, payload, user })\n\n if (user && !req.user) {\n req.user = user\n }\n\n const branchDocs = await payload.find({\n collection: branchesCollectionSlug,\n limit: 1,\n overrideAccess,\n pagination: false,\n req,\n where: { slug: { equals: branch } },\n })\n const branchDoc = branchDocs.docs[0]\n\n if (!branchDoc) {\n throw new Error(`Branch \"${branch}\" was not found.`)\n }\n\n if (!overrideAccess) {\n await assertBranchActionAccess({ action: 'mergeBranch', branchDoc, req })\n }\n\n const cleanupRetry = dryRun\n ? { handledChangeIDs: new Set<string>(), retryable: [] }\n : await inspectFailedCleanups({ branch, payload, req, selected })\n const retryableCleanups = cleanupRetry.retryable\n const allChanges = await payload.find({\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n pagination: false,\n req,\n sort: 'createdAt',\n where: { branch: { equals: branch } },\n })\n const selectedChanges = selectBranchChanges({\n changes: allChanges.docs,\n excluded: cleanupRetry.handledChangeIDs,\n selected,\n })\n const pending = selectedChanges.filter(\n (change) => change.entityType !== 'global',\n ) as PreparedBranchChange[]\n const pendingGlobals = selectedChanges.filter(\n (change) => change.entityType === 'global',\n ) as PreparedBranchChange[]\n const resolved = await resolveEffectiveOperations({ branch, changes: pending, payload, req })\n const targetReq = createMainBranchRequest({ req })\n const blocked = overrideAccess\n ? []\n : await runMergePreflight({ payload, pending: resolved, req: targetReq })\n const blockedGlobals = overrideAccess\n ? []\n : await runGlobalMergePreflight({ payload, pending: pendingGlobals, req: targetReq })\n\n blocked.push(...blockedGlobals)\n blocked.push(\n ...(await runMergeDependencyPreflight({\n initiallyBlocked: blocked,\n payload,\n pending: resolved,\n pendingGlobals,\n req: targetReq,\n })),\n )\n\n const validationCandidates = await prepareBranchMergeValidationCandidates({\n payload,\n pending: resolved,\n pendingGlobals,\n req: targetReq,\n })\n const validation = await payload.config.branching.validate({\n branch,\n candidates: validationCandidates,\n req: createBranchMergeValidationRequest({ req: targetReq }),\n target: MAIN_BRANCH,\n })\n const hasPreflightErrors = blocked.length > 0 || !validation.valid\n const applicable = hasPreflightErrors ? [] : pending\n const applicableGlobals = hasPreflightErrors ? [] : pendingGlobals\n const mergeable: MergeableChange[] = [\n ...retryableCleanups,\n ...applicable.map((change) => ({\n changeID: change.id,\n collectionSlug: change.collectionSlug as string,\n docID: changeDocID(change),\n entityType: 'collection' as const,\n operation: change.operation as BranchOperation,\n })),\n ]\n\n mergeable.push(\n ...applicableGlobals.map((change) => ({\n changeID: change.id,\n entityType: 'global' as const,\n globalSlug: change.globalSlug as string,\n operation: 'update' as const,\n })),\n )\n\n const warnings: MergeWarning[] = []\n\n for (const change of applicable) {\n if (change.operation === 'create' || !change.baseUpdatedAt) {\n continue\n }\n\n const collectionSlug = change.collectionSlug as string\n const docID = changeDocID(change)\n const mainDoc = (await payload.db.findOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: {\n and: [{ [branchField]: { equals: MAIN_BRANCH } }, { id: { equals: docID } }],\n },\n })) as null | Record<string, unknown>\n\n if (\n mainDoc?.updatedAt &&\n new Date(mainDoc.updatedAt as string) > new Date(change.baseUpdatedAt as string)\n ) {\n warnings.push({\n changeID: change.id,\n collectionSlug,\n docID,\n message: `\"${collectionSlug}\" document ${docID} changed on main after it was branched. Merging will overwrite that change.`,\n reason: 'main-moved',\n })\n }\n }\n\n return {\n applicable,\n applicableGlobals,\n branchDoc,\n mergeable,\n req,\n result: {\n blocked,\n canMerge: mergeable.length > 0,\n mergeable,\n merged: [],\n validationErrors: validation.errors,\n warnings,\n },\n retryableCleanups,\n }\n}\n\nexport const revalidatePreparedMerge = async ({\n applicable,\n applicableGlobals,\n branch,\n overrideAccess,\n payload,\n req,\n}: {\n applicable: PreparedBranchChange[]\n applicableGlobals: PreparedBranchChange[]\n branch: string\n overrideAccess: boolean\n payload: Payload\n req: PayloadRequest\n}): Promise<{\n blocked: MergeResult['blocked']\n isValid: boolean\n validationErrors: BranchMergeValidationError[]\n}> => {\n const refreshedResolved = await resolveEffectiveOperations({\n branch,\n changes: applicable,\n payload,\n req,\n })\n const targetReq = createMainBranchRequest({ req })\n const blocked = overrideAccess\n ? []\n : await runMergePreflight({ payload, pending: refreshedResolved, req: targetReq })\n const blockedGlobals = overrideAccess\n ? []\n : await runGlobalMergePreflight({\n payload,\n pending: applicableGlobals,\n req: targetReq,\n })\n\n blocked.push(...blockedGlobals)\n blocked.push(\n ...(await runMergeDependencyPreflight({\n initiallyBlocked: blocked,\n payload,\n pending: refreshedResolved,\n pendingGlobals: applicableGlobals,\n req: targetReq,\n })),\n )\n\n const validationCandidates = await prepareBranchMergeValidationCandidates({\n payload,\n pending: refreshedResolved,\n pendingGlobals: applicableGlobals,\n req: targetReq,\n })\n const validation = await payload.config.branching.validate({\n branch,\n candidates: validationCandidates,\n req: createBranchMergeValidationRequest({ req: targetReq }),\n target: MAIN_BRANCH,\n })\n\n return {\n blocked,\n isValid: blocked.length === 0 && validation.valid,\n validationErrors: validation.errors,\n }\n}\n"],"names":["createPayloadRequest","assertBranchActionAccess","resolveEffectiveOperations","runGlobalMergePreflight","runMergeDependencyPreflight","runMergePreflight","withoutBranch","selectBranchChanges","branchChangesCollectionSlug","branchesCollectionSlug","branchField","MAIN_BRANCH","createBranchMergeValidationRequest","createMainBranchRequest","prepareBranchMergeValidationCandidates","inspectFailedCleanups","changeDocID","prepareMerge","branch","dryRun","incomingReq","overrideAccess","payload","selected","user","req","branchDocs","find","collection","limit","pagination","where","slug","equals","branchDoc","docs","Error","action","cleanupRetry","handledChangeIDs","Set","retryable","retryableCleanups","allChanges","sort","selectedChanges","changes","excluded","pending","filter","change","entityType","pendingGlobals","resolved","targetReq","blocked","blockedGlobals","push","initiallyBlocked","validationCandidates","validation","config","branching","validate","candidates","target","hasPreflightErrors","length","valid","applicable","applicableGlobals","mergeable","map","changeID","id","collectionSlug","docID","operation","globalSlug","warnings","baseUpdatedAt","mainDoc","db","findOne","and","updatedAt","Date","message","reason","result","canMerge","merged","validationErrors","errors","revalidatePreparedMerge","refreshedResolved","isValid"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/branching/merge/prepareMerge.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from '../../types/index.js'\nimport type { MergeResult } from '../merge.js'\nimport type { BranchOperation, MergeableChange, MergeWarning } from '../types.js'\nimport type { BranchMergeValidationError } from '../validation.js'\n\nimport { createPayloadRequest } from '../../utilities/createPayloadRequest.js'\nimport { assertBranchActionAccess } from '../assertBranchActionAccess.js'\nimport { resolveEffectiveOperations } from '../effectiveOperations.js'\nimport {\n runGlobalMergePreflight,\n runMergeDependencyPreflight,\n runMergePreflight,\n} from '../preflight.js'\nimport { withoutBranch } from '../resolveBranch.js'\nimport { selectBranchChanges } from '../selectBranchChanges.js'\nimport {\n branchChangesCollectionSlug,\n branchesCollectionSlug,\n branchField,\n MAIN_BRANCH,\n} from '../types.js'\nimport {\n createBranchMergeValidationRequest,\n createMainBranchRequest,\n prepareBranchMergeValidationCandidates,\n} from '../validation.js'\nimport { inspectFailedCleanups } from './retryFailedCleanups.js'\nimport { changeDocID } from './utilities.js'\n\nexport type PreparedBranchChange = {\n doc?: unknown\n id: number | string\n} & Record<string, unknown>\n\nexport type PreparedMerge = {\n applicable: PreparedBranchChange[]\n applicableGlobals: PreparedBranchChange[]\n branchDoc: { id: number | string }\n mergeable: MergeableChange[]\n req: PayloadRequest\n result: MergeResult\n retryableCleanups: MergeableChange[]\n}\n\nexport const prepareMerge = async ({\n branch,\n dryRun,\n incomingReq,\n overrideAccess,\n payload,\n selected,\n user,\n}: {\n branch: string\n dryRun: boolean\n incomingReq?: PayloadRequest\n overrideAccess: boolean\n payload: Payload\n selected?: (number | string)[]\n user?: NonNullable<PayloadRequest['user']>\n}): Promise<PreparedMerge> => {\n const req = incomingReq\n ? withoutBranch(incomingReq)\n : await createPayloadRequest({ branch: false, payload, user })\n\n if (user) {\n req.user = user\n }\n\n const branchDocs = await payload.find({\n collection: branchesCollectionSlug,\n limit: 1,\n overrideAccess,\n pagination: false,\n req,\n where: { slug: { equals: branch } },\n })\n const branchDoc = branchDocs.docs[0]\n\n if (!branchDoc) {\n throw new Error(`Branch \"${branch}\" was not found.`)\n }\n\n if (!overrideAccess) {\n await assertBranchActionAccess({ action: 'mergeBranch', branchDoc, req })\n }\n\n const cleanupRetry = dryRun\n ? { handledChangeIDs: new Set<string>(), retryable: [] }\n : await inspectFailedCleanups({ branch, payload, req, selected })\n const retryableCleanups = cleanupRetry.retryable\n const allChanges = await payload.find({\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n pagination: false,\n req,\n sort: 'createdAt',\n where: { branch: { equals: branch } },\n })\n const selectedChanges = selectBranchChanges({\n changes: allChanges.docs,\n excluded: cleanupRetry.handledChangeIDs,\n selected,\n })\n const pending = selectedChanges.filter(\n (change) => change.entityType !== 'global',\n ) as PreparedBranchChange[]\n const pendingGlobals = selectedChanges.filter(\n (change) => change.entityType === 'global',\n ) as PreparedBranchChange[]\n const resolved = await resolveEffectiveOperations({ branch, changes: pending, payload, req })\n const targetReq = createMainBranchRequest({ req })\n const blocked = overrideAccess\n ? []\n : await runMergePreflight({ payload, pending: resolved, req: targetReq })\n const blockedGlobals = overrideAccess\n ? []\n : await runGlobalMergePreflight({ payload, pending: pendingGlobals, req: targetReq })\n\n blocked.push(...blockedGlobals)\n blocked.push(\n ...(await runMergeDependencyPreflight({\n initiallyBlocked: blocked,\n payload,\n pending: resolved,\n pendingGlobals,\n req: targetReq,\n })),\n )\n\n const validationCandidates = await prepareBranchMergeValidationCandidates({\n payload,\n pending: resolved,\n pendingGlobals,\n req: targetReq,\n })\n const validation = await payload.config.branching.validate({\n branch,\n candidates: validationCandidates,\n req: createBranchMergeValidationRequest({ req: targetReq }),\n target: MAIN_BRANCH,\n })\n const hasPreflightErrors = blocked.length > 0 || !validation.valid\n const applicable = hasPreflightErrors ? [] : pending\n const applicableGlobals = hasPreflightErrors ? [] : pendingGlobals\n const mergeable: MergeableChange[] = [\n ...retryableCleanups,\n ...applicable.map((change) => ({\n changeID: change.id,\n collectionSlug: change.collectionSlug as string,\n docID: changeDocID(change),\n entityType: 'collection' as const,\n operation: change.operation as BranchOperation,\n })),\n ]\n\n mergeable.push(\n ...applicableGlobals.map((change) => ({\n changeID: change.id,\n entityType: 'global' as const,\n globalSlug: change.globalSlug as string,\n operation: 'update' as const,\n })),\n )\n\n const warnings: MergeWarning[] = []\n\n for (const change of applicable) {\n if (change.operation === 'create' || !change.baseUpdatedAt) {\n continue\n }\n\n const collectionSlug = change.collectionSlug as string\n const docID = changeDocID(change)\n const mainDoc = (await payload.db.findOne({\n branch: false,\n collection: collectionSlug,\n req,\n where: {\n and: [{ [branchField]: { equals: MAIN_BRANCH } }, { id: { equals: docID } }],\n },\n })) as null | Record<string, unknown>\n\n if (\n mainDoc?.updatedAt &&\n new Date(mainDoc.updatedAt as string) > new Date(change.baseUpdatedAt as string)\n ) {\n warnings.push({\n changeID: change.id,\n collectionSlug,\n docID,\n message: `\"${collectionSlug}\" document ${docID} changed on main after it was branched. Merging will overwrite that change.`,\n reason: 'main-moved',\n })\n }\n }\n\n return {\n applicable,\n applicableGlobals,\n branchDoc,\n mergeable,\n req,\n result: {\n blocked,\n canMerge: mergeable.length > 0,\n mergeable,\n merged: [],\n validationErrors: validation.errors,\n warnings,\n },\n retryableCleanups,\n }\n}\n\nexport const revalidatePreparedMerge = async ({\n applicable,\n applicableGlobals,\n branch,\n overrideAccess,\n payload,\n req,\n}: {\n applicable: PreparedBranchChange[]\n applicableGlobals: PreparedBranchChange[]\n branch: string\n overrideAccess: boolean\n payload: Payload\n req: PayloadRequest\n}): Promise<{\n blocked: MergeResult['blocked']\n isValid: boolean\n validationErrors: BranchMergeValidationError[]\n}> => {\n const refreshedResolved = await resolveEffectiveOperations({\n branch,\n changes: applicable,\n payload,\n req,\n })\n const targetReq = createMainBranchRequest({ req })\n const blocked = overrideAccess\n ? []\n : await runMergePreflight({ payload, pending: refreshedResolved, req: targetReq })\n const blockedGlobals = overrideAccess\n ? []\n : await runGlobalMergePreflight({\n payload,\n pending: applicableGlobals,\n req: targetReq,\n })\n\n blocked.push(...blockedGlobals)\n blocked.push(\n ...(await runMergeDependencyPreflight({\n initiallyBlocked: blocked,\n payload,\n pending: refreshedResolved,\n pendingGlobals: applicableGlobals,\n req: targetReq,\n })),\n )\n\n const validationCandidates = await prepareBranchMergeValidationCandidates({\n payload,\n pending: refreshedResolved,\n pendingGlobals: applicableGlobals,\n req: targetReq,\n })\n const validation = await payload.config.branching.validate({\n branch,\n candidates: validationCandidates,\n req: createBranchMergeValidationRequest({ req: targetReq }),\n target: MAIN_BRANCH,\n })\n\n return {\n blocked,\n isValid: blocked.length === 0 && validation.valid,\n validationErrors: validation.errors,\n }\n}\n"],"names":["createPayloadRequest","assertBranchActionAccess","resolveEffectiveOperations","runGlobalMergePreflight","runMergeDependencyPreflight","runMergePreflight","withoutBranch","selectBranchChanges","branchChangesCollectionSlug","branchesCollectionSlug","branchField","MAIN_BRANCH","createBranchMergeValidationRequest","createMainBranchRequest","prepareBranchMergeValidationCandidates","inspectFailedCleanups","changeDocID","prepareMerge","branch","dryRun","incomingReq","overrideAccess","payload","selected","user","req","branchDocs","find","collection","limit","pagination","where","slug","equals","branchDoc","docs","Error","action","cleanupRetry","handledChangeIDs","Set","retryable","retryableCleanups","allChanges","sort","selectedChanges","changes","excluded","pending","filter","change","entityType","pendingGlobals","resolved","targetReq","blocked","blockedGlobals","push","initiallyBlocked","validationCandidates","validation","config","branching","validate","candidates","target","hasPreflightErrors","length","valid","applicable","applicableGlobals","mergeable","map","changeID","id","collectionSlug","docID","operation","globalSlug","warnings","baseUpdatedAt","mainDoc","db","findOne","and","updatedAt","Date","message","reason","result","canMerge","merged","validationErrors","errors","revalidatePreparedMerge","refreshedResolved","isValid"],"mappings":"AAKA,SAASA,oBAAoB,QAAQ,0CAAyC;AAC9E,SAASC,wBAAwB,QAAQ,iCAAgC;AACzE,SAASC,0BAA0B,QAAQ,4BAA2B;AACtE,SACEC,uBAAuB,EACvBC,2BAA2B,EAC3BC,iBAAiB,QACZ,kBAAiB;AACxB,SAASC,aAAa,QAAQ,sBAAqB;AACnD,SAASC,mBAAmB,QAAQ,4BAA2B;AAC/D,SACEC,2BAA2B,EAC3BC,sBAAsB,EACtBC,WAAW,EACXC,WAAW,QACN,cAAa;AACpB,SACEC,kCAAkC,EAClCC,uBAAuB,EACvBC,sCAAsC,QACjC,mBAAkB;AACzB,SAASC,qBAAqB,QAAQ,2BAA0B;AAChE,SAASC,WAAW,QAAQ,iBAAgB;AAiB5C,OAAO,MAAMC,eAAe,OAAO,EACjCC,MAAM,EACNC,MAAM,EACNC,WAAW,EACXC,cAAc,EACdC,OAAO,EACPC,QAAQ,EACRC,IAAI,EASL;IACC,MAAMC,MAAML,cACRd,cAAcc,eACd,MAAMpB,qBAAqB;QAAEkB,QAAQ;QAAOI;QAASE;IAAK;IAE9D,IAAIA,MAAM;QACRC,IAAID,IAAI,GAAGA;IACb;IAEA,MAAME,aAAa,MAAMJ,QAAQK,IAAI,CAAC;QACpCC,YAAYnB;QACZoB,OAAO;QACPR;QACAS,YAAY;QACZL;QACAM,OAAO;YAAEC,MAAM;gBAAEC,QAAQf;YAAO;QAAE;IACpC;IACA,MAAMgB,YAAYR,WAAWS,IAAI,CAAC,EAAE;IAEpC,IAAI,CAACD,WAAW;QACd,MAAM,IAAIE,MAAM,CAAC,QAAQ,EAAElB,OAAO,gBAAgB,CAAC;IACrD;IAEA,IAAI,CAACG,gBAAgB;QACnB,MAAMpB,yBAAyB;YAAEoC,QAAQ;YAAeH;YAAWT;QAAI;IACzE;IAEA,MAAMa,eAAenB,SACjB;QAAEoB,kBAAkB,IAAIC;QAAeC,WAAW,EAAE;IAAC,IACrD,MAAM1B,sBAAsB;QAAEG;QAAQI;QAASG;QAAKF;IAAS;IACjE,MAAMmB,oBAAoBJ,aAAaG,SAAS;IAChD,MAAME,aAAa,MAAMrB,QAAQK,IAAI,CAAC;QACpCC,YAAYpB;QACZa,gBAAgB;QAChBS,YAAY;QACZL;QACAmB,MAAM;QACNb,OAAO;YAAEb,QAAQ;gBAAEe,QAAQf;YAAO;QAAE;IACtC;IACA,MAAM2B,kBAAkBtC,oBAAoB;QAC1CuC,SAASH,WAAWR,IAAI;QACxBY,UAAUT,aAAaC,gBAAgB;QACvChB;IACF;IACA,MAAMyB,UAAUH,gBAAgBI,MAAM,CACpC,CAACC,SAAWA,OAAOC,UAAU,KAAK;IAEpC,MAAMC,iBAAiBP,gBAAgBI,MAAM,CAC3C,CAACC,SAAWA,OAAOC,UAAU,KAAK;IAEpC,MAAME,WAAW,MAAMnD,2BAA2B;QAAEgB;QAAQ4B,SAASE;QAAS1B;QAASG;IAAI;IAC3F,MAAM6B,YAAYzC,wBAAwB;QAAEY;IAAI;IAChD,MAAM8B,UAAUlC,iBACZ,EAAE,GACF,MAAMhB,kBAAkB;QAAEiB;QAAS0B,SAASK;QAAU5B,KAAK6B;IAAU;IACzE,MAAME,iBAAiBnC,iBACnB,EAAE,GACF,MAAMlB,wBAAwB;QAAEmB;QAAS0B,SAASI;QAAgB3B,KAAK6B;IAAU;IAErFC,QAAQE,IAAI,IAAID;IAChBD,QAAQE,IAAI,IACN,MAAMrD,4BAA4B;QACpCsD,kBAAkBH;QAClBjC;QACA0B,SAASK;QACTD;QACA3B,KAAK6B;IACP;IAGF,MAAMK,uBAAuB,MAAM7C,uCAAuC;QACxEQ;QACA0B,SAASK;QACTD;QACA3B,KAAK6B;IACP;IACA,MAAMM,aAAa,MAAMtC,QAAQuC,MAAM,CAACC,SAAS,CAACC,QAAQ,CAAC;QACzD7C;QACA8C,YAAYL;QACZlC,KAAKb,mCAAmC;YAAEa,KAAK6B;QAAU;QACzDW,QAAQtD;IACV;IACA,MAAMuD,qBAAqBX,QAAQY,MAAM,GAAG,KAAK,CAACP,WAAWQ,KAAK;IAClE,MAAMC,aAAaH,qBAAqB,EAAE,GAAGlB;IAC7C,MAAMsB,oBAAoBJ,qBAAqB,EAAE,GAAGd;IACpD,MAAMmB,YAA+B;WAChC7B;WACA2B,WAAWG,GAAG,CAAC,CAACtB,SAAY,CAAA;gBAC7BuB,UAAUvB,OAAOwB,EAAE;gBACnBC,gBAAgBzB,OAAOyB,cAAc;gBACrCC,OAAO5D,YAAYkC;gBACnBC,YAAY;gBACZ0B,WAAW3B,OAAO2B,SAAS;YAC7B,CAAA;KACD;IAEDN,UAAUd,IAAI,IACTa,kBAAkBE,GAAG,CAAC,CAACtB,SAAY,CAAA;YACpCuB,UAAUvB,OAAOwB,EAAE;YACnBvB,YAAY;YACZ2B,YAAY5B,OAAO4B,UAAU;YAC7BD,WAAW;QACb,CAAA;IAGF,MAAME,WAA2B,EAAE;IAEnC,KAAK,MAAM7B,UAAUmB,WAAY;QAC/B,IAAInB,OAAO2B,SAAS,KAAK,YAAY,CAAC3B,OAAO8B,aAAa,EAAE;YAC1D;QACF;QAEA,MAAML,iBAAiBzB,OAAOyB,cAAc;QAC5C,MAAMC,QAAQ5D,YAAYkC;QAC1B,MAAM+B,UAAW,MAAM3D,QAAQ4D,EAAE,CAACC,OAAO,CAAC;YACxCjE,QAAQ;YACRU,YAAY+C;YACZlD;YACAM,OAAO;gBACLqD,KAAK;oBAAC;wBAAE,CAAC1E,YAAY,EAAE;4BAAEuB,QAAQtB;wBAAY;oBAAE;oBAAG;wBAAE+D,IAAI;4BAAEzC,QAAQ2C;wBAAM;oBAAE;iBAAE;YAC9E;QACF;QAEA,IACEK,SAASI,aACT,IAAIC,KAAKL,QAAQI,SAAS,IAAc,IAAIC,KAAKpC,OAAO8B,aAAa,GACrE;YACAD,SAAStB,IAAI,CAAC;gBACZgB,UAAUvB,OAAOwB,EAAE;gBACnBC;gBACAC;gBACAW,SAAS,CAAC,CAAC,EAAEZ,eAAe,WAAW,EAAEC,MAAM,2EAA2E,CAAC;gBAC3HY,QAAQ;YACV;QACF;IACF;IAEA,OAAO;QACLnB;QACAC;QACApC;QACAqC;QACA9C;QACAgE,QAAQ;YACNlC;YACAmC,UAAUnB,UAAUJ,MAAM,GAAG;YAC7BI;YACAoB,QAAQ,EAAE;YACVC,kBAAkBhC,WAAWiC,MAAM;YACnCd;QACF;QACArC;IACF;AACF,EAAC;AAED,OAAO,MAAMoD,0BAA0B,OAAO,EAC5CzB,UAAU,EACVC,iBAAiB,EACjBpD,MAAM,EACNG,cAAc,EACdC,OAAO,EACPG,GAAG,EAQJ;IAKC,MAAMsE,oBAAoB,MAAM7F,2BAA2B;QACzDgB;QACA4B,SAASuB;QACT/C;QACAG;IACF;IACA,MAAM6B,YAAYzC,wBAAwB;QAAEY;IAAI;IAChD,MAAM8B,UAAUlC,iBACZ,EAAE,GACF,MAAMhB,kBAAkB;QAAEiB;QAAS0B,SAAS+C;QAAmBtE,KAAK6B;IAAU;IAClF,MAAME,iBAAiBnC,iBACnB,EAAE,GACF,MAAMlB,wBAAwB;QAC5BmB;QACA0B,SAASsB;QACT7C,KAAK6B;IACP;IAEJC,QAAQE,IAAI,IAAID;IAChBD,QAAQE,IAAI,IACN,MAAMrD,4BAA4B;QACpCsD,kBAAkBH;QAClBjC;QACA0B,SAAS+C;QACT3C,gBAAgBkB;QAChB7C,KAAK6B;IACP;IAGF,MAAMK,uBAAuB,MAAM7C,uCAAuC;QACxEQ;QACA0B,SAAS+C;QACT3C,gBAAgBkB;QAChB7C,KAAK6B;IACP;IACA,MAAMM,aAAa,MAAMtC,QAAQuC,MAAM,CAACC,SAAS,CAACC,QAAQ,CAAC;QACzD7C;QACA8C,YAAYL;QACZlC,KAAKb,mCAAmC;YAAEa,KAAK6B;QAAU;QACzDW,QAAQtD;IACV;IAEA,OAAO;QACL4C;QACAyC,SAASzC,QAAQY,MAAM,KAAK,KAAKP,WAAWQ,KAAK;QACjDwB,kBAAkBhC,WAAWiC,MAAM;IACrC;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/branching/merge/retryFailedCleanups.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from '../../types/index.js'\nimport type { MergeableChange, MergeEventChange } from '../types.js'\n\nimport { getVersionsMax } from '../../utilities/getVersionsConfig.js'\nimport { enforceMaxVersions } from '../../versions/enforceMaxVersions.js'\nimport {\n branchChangesCollectionSlug,\n branchDocIDField,\n branchField,\n branchMergesCollectionSlug,\n} from '../types.js'\nimport { deleteBranchGlobalVersionChain, deleteBranchVersionChain } from '../versions.js'\nimport { deleteVersionsByID } from './applyMergeChange.js'\nimport {\n getGlobalSourceRevision,\n getMergeErrorMessage,\n getTimestamp,\n readSerializedGlobalSourceStates,\n} from './utilities.js'\n\ntype PersistedMergeEvent = {\n changes?: MergeEventChange[]\n completedAt?: string\n error?: string\n id: number | string\n}\n\ntype RetryableCleanupCandidate = {\n change: MergeEventChange\n event: PersistedMergeEvent\n}\n\nconst updateMergeEventChange = ({\n changeID,\n changes,\n update,\n}: {\n changeID: number | string\n changes: MergeEventChange[]\n update: Partial<MergeEventChange>\n}): MergeEventChange[] =>\n changes.map((change) =>\n change.changeID === String(changeID) ? { ...change, ...update } : change,\n )\n\nconst toMergeableChange = ({ change }: { change: MergeEventChange }): MergeableChange | null => {\n if (change.globalSlug) {\n return {\n changeID: change.changeID,\n entityType: 'global',\n globalSlug: change.globalSlug,\n operation: change.operation,\n }\n }\n\n if (!change.collectionSlug || change.docID === undefined) {\n return null\n }\n\n return {\n changeID: change.changeID,\n collectionSlug: change.collectionSlug,\n docID: change.docID,\n entityType: 'collection',\n operation: change.operation,\n }\n}\n\nconst findRetryableCleanupCandidates = async ({\n branch,\n payload,\n req,\n selected,\n}: {\n branch: string\n payload: Payload\n req: PayloadRequest\n selected?: (number | string)[]\n}): Promise<RetryableCleanupCandidate[]> => {\n const failedEvents = await payload.find({\n collection: branchMergesCollectionSlug,\n depth: 0,\n overrideAccess: true,\n pagination: false,\n req,\n sort: '-startedAt',\n where: {\n and: [{ branch: { equals: branch } }, { status: { equals: 'cleanupFailed' } }],\n },\n })\n const selectedChangeIDs = selected ? new Set(selected.map(String)) : null\n const candidateChangeIDs = new Set<string>()\n const candidates: RetryableCleanupCandidate[] = []\n\n for (const eventDocument of failedEvents.docs) {\n const event = eventDocument as unknown as PersistedMergeEvent\n\n for (const change of event.changes ?? []) {\n const canRetryCollection = Boolean(\n change.collectionSlug &&\n change.sourceID &&\n change.sourceUpdatedAt &&\n change.operation !== 'create',\n )\n const canRetryGlobal = Boolean(change.globalSlug && change.sourceRevision)\n const canRetryCreatedCollection = Boolean(\n change.collectionSlug &&\n change.operation === 'create' &&\n change.sourceID &&\n change.sourceVersionIDs,\n )\n\n if (\n candidateChangeIDs.has(change.changeID) ||\n (selectedChangeIDs && !selectedChangeIDs.has(change.changeID)) ||\n change.applicationOutcome !== 'committed' ||\n change.cleanupOutcome !== 'failed' ||\n (!canRetryCollection && !canRetryCreatedCollection && !canRetryGlobal)\n ) {\n continue\n }\n\n candidateChangeIDs.add(change.changeID)\n candidates.push({ change, event })\n }\n }\n\n return candidates\n}\n\n/**\n * Finds cleanup recovery work without changing persisted state.\n *\n * Merge preparation uses this result to exclude already-committed changes from\n * normal target writes. The actual cleanup starts only after the branch has\n * been conditionally claimed as `merging`.\n */\nexport const inspectFailedCleanups = async ({\n branch,\n payload,\n req,\n selected,\n}: {\n branch: string\n payload: Payload\n req: PayloadRequest\n selected?: (number | string)[]\n}): Promise<{ handledChangeIDs: Set<string>; retryable: MergeableChange[] }> => {\n const candidates = await findRetryableCleanupCandidates({ branch, payload, req, selected })\n const retryable = candidates.flatMap(({ change }) => {\n const mergeableChange = toMergeableChange({ change })\n\n return mergeableChange ? [mergeableChange] : []\n })\n\n return {\n handledChangeIDs: new Set(retryable.map(({ changeID }) => String(changeID))),\n retryable,\n }\n}\n\nconst persistRetriedMergeEvent = async ({\n event,\n payload,\n req,\n}: {\n event: PersistedMergeEvent\n payload: Payload\n req: PayloadRequest\n}): Promise<void> => {\n const changes = event.changes ?? []\n const hasUnresolvedCleanup = changes.some(({ cleanupOutcome }) =>\n ['failed', 'pending', 'unknown'].includes(cleanupOutcome),\n )\n\n await payload.update({\n id: event.id,\n collection: branchMergesCollectionSlug,\n data: {\n changes,\n completedAt: hasUnresolvedCleanup ? event.completedAt : new Date().toISOString(),\n error: hasUnresolvedCleanup ? event.error : null,\n status: hasUnresolvedCleanup ? 'cleanupFailed' : 'succeeded',\n },\n overrideAccess: true,\n req,\n })\n}\n\n/**\n * Retries only the source cleanup recorded by a committed merge event.\n *\n * The target write is already durable. Replaying it would run hooks and create\n * versions again, so cleanup uses the stored source row identity and revision.\n * A changed source row belongs to newer branch work and is left for the normal\n * merge path.\n */\nexport const retryFailedCleanups = async ({\n branch,\n payload,\n req,\n selected,\n}: {\n branch: string\n payload: Payload\n req: PayloadRequest\n selected?: (number | string)[]\n}): Promise<{ handledChangeIDs: Set<string>; retried: MergeableChange[] }> => {\n const candidates = await findRetryableCleanupCandidates({ branch, payload, req, selected })\n const handledChangeIDs = new Set<string>()\n const retried: MergeableChange[] = []\n\n for (const { change, event } of candidates) {\n const canRetryGlobal = Boolean(change.globalSlug && change.sourceRevision)\n const canRetryCreatedCollection = Boolean(\n change.collectionSlug &&\n change.operation === 'create' &&\n change.sourceID &&\n change.sourceVersionIDs,\n )\n\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes ?? [],\n update: { cleanupError: undefined, cleanupOutcome: 'pending' },\n })\n await persistRetriedMergeEvent({ event, payload, req })\n\n try {\n let isSuperseded = false\n\n if (canRetryGlobal) {\n const currentSourceStates = await readSerializedGlobalSourceStates({\n branch,\n globalSlug: change.globalSlug!,\n payload,\n req,\n })\n\n isSuperseded =\n currentSourceStates.length > 0 &&\n getGlobalSourceRevision({ sourceStates: currentSourceStates }) !== change.sourceRevision\n\n if (!isSuperseded) {\n await deleteBranchGlobalVersionChain({\n branch,\n globalSlug: change.globalSlug!,\n payload,\n req,\n })\n await payload.db.deleteBranchGlobal?.({\n branch,\n globalSlug: change.globalSlug!,\n req,\n })\n }\n } else if (canRetryCreatedCollection) {\n const newerSource = await payload.db.findOne({\n branch: false,\n collection: change.collectionSlug!,\n req,\n where: {\n and: [\n { [branchField]: { equals: branch } },\n { [branchDocIDField]: { equals: change.targetID } },\n ],\n },\n })\n\n isSuperseded = Boolean(newerSource)\n\n if (!isSuperseded) {\n await deleteVersionsByID({\n collectionSlug: change.collectionSlug!,\n ids: change.sourceVersionIDs!,\n payload,\n req,\n })\n\n const collection = payload.collections[change.collectionSlug!]!.config\n const maxVersions = getVersionsMax(collection)\n\n if (maxVersions > 0) {\n await enforceMaxVersions({\n id: change.sourceID!,\n collection,\n max: maxVersions,\n payload,\n req,\n })\n }\n }\n } else {\n const source = (await payload.db.findOne({\n branch: false,\n collection: change.collectionSlug!,\n req,\n where: { id: { equals: change.sourceID! } },\n })) as null | Record<string, unknown>\n const currentSourceUpdatedAt = getTimestamp({ value: source?.updatedAt })\n const mergedSourceUpdatedAt = getTimestamp({ value: change.sourceUpdatedAt })\n\n isSuperseded = Boolean(\n source &&\n currentSourceUpdatedAt !== undefined &&\n mergedSourceUpdatedAt !== undefined &&\n currentSourceUpdatedAt !== mergedSourceUpdatedAt,\n )\n\n if (!isSuperseded && source) {\n await deleteBranchVersionChain({\n branch,\n collectionSlug: change.collectionSlug!,\n payload,\n req,\n rowID: change.sourceID!,\n })\n await payload.db.deleteOne({\n branch: false,\n collection: change.collectionSlug!,\n req,\n where: { id: { equals: change.sourceID! } },\n })\n }\n }\n\n if (isSuperseded) {\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes,\n update: { cleanupOutcome: 'superseded' },\n })\n await persistRetriedMergeEvent({ event, payload, req })\n handledChangeIDs.add(change.changeID)\n continue\n }\n\n const changeRecord = await payload.db.findOne({\n collection: branchChangesCollectionSlug,\n req,\n where: { id: { equals: change.changeID } },\n })\n\n if (changeRecord) {\n await payload.delete({\n id: change.changeID,\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n req,\n })\n }\n\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes,\n update: { cleanupOutcome: 'completed' },\n })\n await persistRetriedMergeEvent({ event, payload, req })\n\n const mergeableChange = toMergeableChange({ change })\n\n if (mergeableChange) {\n retried.push(mergeableChange)\n }\n handledChangeIDs.add(change.changeID)\n } catch (error) {\n const cleanupError = getMergeErrorMessage({ error })\n\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes,\n update: { cleanupError, cleanupOutcome: 'failed' },\n })\n event.error = cleanupError\n await persistRetriedMergeEvent({ event, payload, req })\n\n throw error\n }\n }\n\n return { handledChangeIDs, retried }\n}\n"],"names":["getVersionsMax","enforceMaxVersions","branchChangesCollectionSlug","branchDocIDField","branchField","branchMergesCollectionSlug","deleteBranchGlobalVersionChain","deleteBranchVersionChain","deleteVersionsByID","getGlobalSourceRevision","getMergeErrorMessage","getTimestamp","readSerializedGlobalSourceStates","updateMergeEventChange","changeID","changes","update","map","change","String","toMergeableChange","globalSlug","entityType","operation","collectionSlug","docID","undefined","findRetryableCleanupCandidates","branch","payload","req","selected","failedEvents","find","collection","depth","overrideAccess","pagination","sort","where","and","equals","status","selectedChangeIDs","Set","candidateChangeIDs","candidates","eventDocument","docs","event","canRetryCollection","Boolean","sourceID","sourceUpdatedAt","canRetryGlobal","sourceRevision","canRetryCreatedCollection","sourceVersionIDs","has","applicationOutcome","cleanupOutcome","add","push","inspectFailedCleanups","retryable","flatMap","mergeableChange","handledChangeIDs","persistRetriedMergeEvent","hasUnresolvedCleanup","some","includes","id","data","completedAt","Date","toISOString","error","retryFailedCleanups","retried","cleanupError","isSuperseded","currentSourceStates","length","sourceStates","db","deleteBranchGlobal","newerSource","findOne","targetID","ids","collections","config","maxVersions","max","source","currentSourceUpdatedAt","value","updatedAt","mergedSourceUpdatedAt","rowID","deleteOne","changeRecord","delete"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/branching/merge/retryFailedCleanups.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from '../../types/index.js'\nimport type { MergeableChange, MergeEventChange } from '../types.js'\n\nimport { getVersionsMax } from '../../utilities/getVersionsConfig.js'\nimport { enforceMaxVersions } from '../../versions/enforceMaxVersions.js'\nimport {\n branchChangesCollectionSlug,\n branchDocIDField,\n branchField,\n branchMergesCollectionSlug,\n} from '../types.js'\nimport { deleteBranchGlobalVersionChain, deleteBranchVersionChain } from '../versions.js'\nimport { deleteVersionsByID } from './applyMergeChange.js'\nimport {\n getGlobalSourceRevision,\n getMergeErrorMessage,\n getTimestamp,\n readSerializedGlobalSourceStates,\n} from './utilities.js'\n\ntype PersistedMergeEvent = {\n changes?: MergeEventChange[]\n completedAt?: string\n error?: string\n id: number | string\n}\n\ntype RetryableCleanupCandidate = {\n change: MergeEventChange\n event: PersistedMergeEvent\n}\n\nconst updateMergeEventChange = ({\n changeID,\n changes,\n update,\n}: {\n changeID: number | string\n changes: MergeEventChange[]\n update: Partial<MergeEventChange>\n}): MergeEventChange[] =>\n changes.map((change) =>\n change.changeID === String(changeID) ? { ...change, ...update } : change,\n )\n\nconst toMergeableChange = ({ change }: { change: MergeEventChange }): MergeableChange | null => {\n if (change.globalSlug) {\n return {\n changeID: change.changeID,\n entityType: 'global',\n globalSlug: change.globalSlug,\n operation: change.operation,\n }\n }\n\n if (!change.collectionSlug || change.docID === undefined) {\n return null\n }\n\n return {\n changeID: change.changeID,\n collectionSlug: change.collectionSlug,\n docID: change.docID,\n entityType: 'collection',\n operation: change.operation,\n }\n}\n\nconst findRetryableCleanupCandidates = async ({\n branch,\n payload,\n req,\n selected,\n}: {\n branch: string\n payload: Payload\n req: PayloadRequest\n selected?: (number | string)[]\n}): Promise<RetryableCleanupCandidate[]> => {\n const failedEvents = await payload.find({\n collection: branchMergesCollectionSlug,\n depth: 0,\n overrideAccess: true,\n pagination: false,\n req,\n sort: '-startedAt',\n where: {\n and: [{ branch: { equals: branch } }, { status: { equals: 'cleanupFailed' } }],\n },\n })\n const selectedChangeIDs = selected ? new Set(selected.map(String)) : null\n const candidateChangeIDs = new Set<string>()\n const candidates: RetryableCleanupCandidate[] = []\n\n for (const eventDocument of failedEvents.docs) {\n const event = eventDocument as unknown as PersistedMergeEvent\n\n for (const change of event.changes ?? []) {\n const canRetryCollection = Boolean(\n change.collectionSlug &&\n change.sourceID &&\n change.sourceUpdatedAt &&\n change.operation !== 'create',\n )\n const canRetryGlobal = Boolean(change.globalSlug && change.sourceRevision)\n const canRetryCreatedCollection = Boolean(\n change.collectionSlug &&\n change.operation === 'create' &&\n change.sourceID &&\n change.sourceVersionIDs,\n )\n\n if (\n candidateChangeIDs.has(change.changeID) ||\n (selectedChangeIDs && !selectedChangeIDs.has(change.changeID)) ||\n change.applicationOutcome !== 'committed' ||\n change.cleanupOutcome !== 'failed' ||\n (!canRetryCollection && !canRetryCreatedCollection && !canRetryGlobal)\n ) {\n continue\n }\n\n candidateChangeIDs.add(change.changeID)\n candidates.push({ change, event })\n }\n }\n\n return candidates\n}\n\n/**\n * Finds cleanup recovery work without changing persisted state.\n *\n * Merge preparation uses this result to exclude already-committed changes from\n * normal target writes. The actual cleanup starts only after the branch has\n * been conditionally claimed as `merging`.\n */\nexport const inspectFailedCleanups = async ({\n branch,\n payload,\n req,\n selected,\n}: {\n branch: string\n payload: Payload\n req: PayloadRequest\n selected?: (number | string)[]\n}): Promise<{ handledChangeIDs: Set<string>; retryable: MergeableChange[] }> => {\n const candidates = await findRetryableCleanupCandidates({ branch, payload, req, selected })\n const retryable = candidates.flatMap(({ change }) => {\n const mergeableChange = toMergeableChange({ change })\n\n return mergeableChange ? [mergeableChange] : []\n })\n\n return {\n handledChangeIDs: new Set(retryable.map(({ changeID }) => String(changeID))),\n retryable,\n }\n}\n\nconst persistRetriedMergeEvent = async ({\n event,\n payload,\n req,\n}: {\n event: PersistedMergeEvent\n payload: Payload\n req: PayloadRequest\n}): Promise<void> => {\n const changes = event.changes ?? []\n const hasUnresolvedCleanup = changes.some(({ cleanupOutcome }) =>\n ['failed', 'pending', 'unknown'].includes(cleanupOutcome),\n )\n\n await payload.update({\n id: event.id,\n collection: branchMergesCollectionSlug,\n data: {\n changes,\n completedAt: hasUnresolvedCleanup ? event.completedAt : new Date().toISOString(),\n error: hasUnresolvedCleanup ? event.error : null,\n status: hasUnresolvedCleanup ? 'cleanupFailed' : 'succeeded',\n },\n overrideAccess: true,\n req,\n })\n}\n\n/**\n * Retries only the source cleanup recorded by a committed merge event.\n *\n * The target write is already durable. Replaying it would run hooks and create\n * versions again, so cleanup uses the stored source row identity and revision.\n * A changed source row belongs to newer branch work and is left for the normal\n * merge path.\n */\nexport const retryFailedCleanups = async ({\n branch,\n payload,\n req,\n selected,\n}: {\n branch: string\n payload: Payload\n req: PayloadRequest\n selected?: (number | string)[]\n}): Promise<{ handledChangeIDs: Set<string>; retried: MergeableChange[] }> => {\n const candidates = await findRetryableCleanupCandidates({ branch, payload, req, selected })\n const handledChangeIDs = new Set<string>()\n const retried: MergeableChange[] = []\n\n for (const { change, event } of candidates) {\n const canRetryGlobal = Boolean(change.globalSlug && change.sourceRevision)\n const canRetryCreatedCollection = Boolean(\n change.collectionSlug &&\n change.operation === 'create' &&\n change.sourceID &&\n change.sourceVersionIDs,\n )\n\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes ?? [],\n update: { cleanupError: undefined, cleanupOutcome: 'pending' },\n })\n await persistRetriedMergeEvent({ event, payload, req })\n\n try {\n let isSuperseded = false\n\n if (canRetryGlobal) {\n const currentSourceStates = await readSerializedGlobalSourceStates({\n branch,\n globalSlug: change.globalSlug!,\n payload,\n req,\n })\n\n isSuperseded =\n currentSourceStates.length > 0 &&\n getGlobalSourceRevision({ sourceStates: currentSourceStates }) !== change.sourceRevision\n\n if (!isSuperseded) {\n await deleteBranchGlobalVersionChain({\n branch,\n globalSlug: change.globalSlug!,\n payload,\n req,\n })\n await payload.db.deleteBranchGlobal?.({\n branch,\n globalSlug: change.globalSlug!,\n req,\n })\n }\n } else if (canRetryCreatedCollection) {\n const newerSource = await payload.db.findOne({\n branch: false,\n collection: change.collectionSlug!,\n req,\n where: {\n and: [\n { [branchField]: { equals: branch } },\n { [branchDocIDField]: { equals: change.targetID } },\n ],\n },\n })\n\n isSuperseded = Boolean(newerSource)\n\n if (!isSuperseded) {\n await deleteVersionsByID({\n collectionSlug: change.collectionSlug!,\n ids: change.sourceVersionIDs!,\n payload,\n req,\n })\n\n const collection = payload.collections[change.collectionSlug!]!.config\n const maxVersions = getVersionsMax(collection)\n\n if (maxVersions > 0) {\n await enforceMaxVersions({\n id: change.sourceID!,\n collection,\n max: maxVersions,\n payload,\n req,\n })\n }\n }\n } else {\n const source = (await payload.db.findOne({\n branch: false,\n collection: change.collectionSlug!,\n req,\n where: { id: { equals: change.sourceID! } },\n })) as null | Record<string, unknown>\n const currentSourceUpdatedAt = getTimestamp({ value: source?.updatedAt })\n const mergedSourceUpdatedAt = getTimestamp({ value: change.sourceUpdatedAt })\n\n isSuperseded = Boolean(\n source &&\n currentSourceUpdatedAt !== undefined &&\n mergedSourceUpdatedAt !== undefined &&\n currentSourceUpdatedAt !== mergedSourceUpdatedAt,\n )\n\n if (!isSuperseded && source) {\n await deleteBranchVersionChain({\n branch,\n collectionSlug: change.collectionSlug!,\n payload,\n req,\n rowID: change.sourceID!,\n })\n await payload.db.deleteOne({\n branch: false,\n collection: change.collectionSlug!,\n req,\n where: { id: { equals: change.sourceID! } },\n })\n }\n }\n\n if (isSuperseded) {\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes,\n update: { cleanupOutcome: 'superseded' },\n })\n await persistRetriedMergeEvent({ event, payload, req })\n handledChangeIDs.add(change.changeID)\n continue\n }\n\n const changeRecord = await payload.db.findOne({\n collection: branchChangesCollectionSlug,\n req,\n where: { id: { equals: change.changeID } },\n })\n\n if (changeRecord) {\n await payload.delete({\n id: change.changeID,\n collection: branchChangesCollectionSlug,\n overrideAccess: true,\n req,\n })\n }\n\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes,\n update: { cleanupOutcome: 'completed' },\n })\n await persistRetriedMergeEvent({ event, payload, req })\n\n const mergeableChange = toMergeableChange({ change })\n\n if (mergeableChange) {\n retried.push(mergeableChange)\n }\n handledChangeIDs.add(change.changeID)\n } catch (error) {\n const cleanupError = getMergeErrorMessage({ error })\n\n event.changes = updateMergeEventChange({\n changeID: change.changeID,\n changes: event.changes,\n update: { cleanupError, cleanupOutcome: 'failed' },\n })\n event.error = cleanupError\n await persistRetriedMergeEvent({ event, payload, req })\n\n throw error\n }\n }\n\n return { handledChangeIDs, retried }\n}\n"],"names":["getVersionsMax","enforceMaxVersions","branchChangesCollectionSlug","branchDocIDField","branchField","branchMergesCollectionSlug","deleteBranchGlobalVersionChain","deleteBranchVersionChain","deleteVersionsByID","getGlobalSourceRevision","getMergeErrorMessage","getTimestamp","readSerializedGlobalSourceStates","updateMergeEventChange","changeID","changes","update","map","change","String","toMergeableChange","globalSlug","entityType","operation","collectionSlug","docID","undefined","findRetryableCleanupCandidates","branch","payload","req","selected","failedEvents","find","collection","depth","overrideAccess","pagination","sort","where","and","equals","status","selectedChangeIDs","Set","candidateChangeIDs","candidates","eventDocument","docs","event","canRetryCollection","Boolean","sourceID","sourceUpdatedAt","canRetryGlobal","sourceRevision","canRetryCreatedCollection","sourceVersionIDs","has","applicationOutcome","cleanupOutcome","add","push","inspectFailedCleanups","retryable","flatMap","mergeableChange","handledChangeIDs","persistRetriedMergeEvent","hasUnresolvedCleanup","some","includes","id","data","completedAt","Date","toISOString","error","retryFailedCleanups","retried","cleanupError","isSuperseded","currentSourceStates","length","sourceStates","db","deleteBranchGlobal","newerSource","findOne","targetID","ids","collections","config","maxVersions","max","source","currentSourceUpdatedAt","value","updatedAt","mergedSourceUpdatedAt","rowID","deleteOne","changeRecord","delete"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveBranchQuery.d.ts","sourceRoot":"","sources":["../../src/branching/resolveBranchQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAa9D,KAAK,IAAI,GAAG;IACV;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAC7B,KAAK,EAAE,SAAS,GAAG,KAAK,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,sBAAsB,iEAKhC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,KAAG,eAkCxB,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,wEAM5B,IAAI,KAAG,OAAO,CAAC,SAAS,GAAG,KAAK,CA+DlC,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,qDAIhC;IACD,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;CAC9B,KAAG,IAAI,GAAG,KA2BV,CAAA"}
1
+ {"version":3,"file":"resolveBranchQuery.d.ts","sourceRoot":"","sources":["../../src/branching/resolveBranchQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAa9D,KAAK,IAAI,GAAG;IACV;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAC7B,KAAK,EAAE,SAAS,GAAG,KAAK,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,sBAAsB,iEAKhC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,KAAG,eAkCxB,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,wEAM5B,IAAI,KAAG,OAAO,CAAC,SAAS,GAAG,KAAK,CAyDlC,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,qDAIhC;IACD,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;CAC9B,KAAG,IAAI,GAAG,KA2BV,CAAA"}
@@ -68,9 +68,6 @@ export const resolveBranchReadState = ({ branch: branchOverride, collectionSlug,
68
68
  // A shadow row's primary key is not the document's canonical ID, so any `id`
69
69
  // constraint has to be redirected before the branch predicate is applied.
70
70
  const rewritten = rewriteBranchIDs(where ?? {});
71
- if (shadowedIDs.length > branching.maxShadowedIDs) {
72
- req.payload.logger.warn(`Branch "${branch}" has shadowed ${shadowedIDs.length} documents in "${collectionSlug}", above maxShadowedIDs (${branching.maxShadowedIDs}). Read performance will degrade.`);
73
- }
74
71
  return appendBranchFilter({
75
72
  branch,
76
73
  deletedIDs,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/branching/resolveBranchQuery.ts"],"sourcesContent":["import type { PayloadRequest, Where } from '../types/index.js'\n\nimport { appendBranchFilter } from './appendBranchFilter.js'\nimport { rewriteBranchIDs } from './branchIDs.js'\nimport {\n loadBranchDeletions,\n loadBranchManifest,\n peekBranchDeletions,\n peekBranchManifest,\n resolveBranch,\n} from './resolveBranch.js'\nimport { MAIN_BRANCH } from './types.js'\n\ntype Args = {\n /**\n * Explicit override. `false` bypasses branching entirely — used by the merge\n * engine, which must reach shadow rows by their real primary key, and by\n * cross-branch reads such as diff views.\n */\n branch?: false | string\n collectionSlug?: string\n globalSlug?: string\n req?: Partial<PayloadRequest>\n where: undefined | Where\n}\n\nexport type BranchReadState = {\n branch: string\n useBranching: boolean\n}\n\nexport const resolveBranchReadState = ({\n branch: branchOverride,\n collectionSlug,\n globalSlug,\n req,\n}: Omit<Args, 'where'>): BranchReadState => {\n const branching = req?.payload?.config?.branching\n const isBranchable = collectionSlug\n ? Boolean(branching?.branchableCollections.has(collectionSlug))\n : globalSlug\n ? Boolean(branching?.branchableGlobals.has(globalSlug))\n : false\n const isRequestBypassed = Boolean(\n (req?.context as Record<string, unknown> | undefined)?._branchBypass,\n )\n const isBypassed = branchOverride === false || isRequestBypassed\n\n if (isRequestBypassed && req?.payload) {\n resolveBranch(req as PayloadRequest)\n }\n\n if (!branching?.enabled || !isBranchable || isBypassed) {\n return {\n branch: typeof branchOverride === 'string' ? branchOverride : MAIN_BRANCH,\n useBranching: false,\n }\n }\n\n const branch =\n typeof branchOverride === 'string'\n ? branchOverride\n : req?.payload\n ? resolveBranch(req as PayloadRequest)\n : MAIN_BRANCH\n\n return {\n branch,\n useBranching: branch !== MAIN_BRANCH,\n }\n}\n\n/**\n * The single entry point adapters call to make a read branch-aware.\n *\n * Lives in `payload` rather than in each adapter so that Mongo and Drizzle\n * cannot drift apart on branch semantics — adapters supply only the query\n * translation they already do.\n *\n * Returns `where` untouched when branching is off, when the entity is not\n * branch-enabled, or when the caller opted out, so a branching-disabled config\n * takes the same code path it does today.\n */\nexport const resolveBranchQuery = async ({\n branch: branchOverride,\n collectionSlug,\n globalSlug,\n req,\n where,\n}: Args): Promise<undefined | Where> => {\n if (branchOverride === false || !req?.payload) {\n return where\n }\n\n // Local API `branch: false` bypass, carried on context so it survives the\n // hop from operation options into the adapter.\n if ((req.context as Record<string, unknown> | undefined)?._branchBypass) {\n return where\n }\n\n const branching = req.payload.config?.branching\n\n if (!branching?.enabled) {\n return where\n }\n\n const isBranchable = collectionSlug\n ? branching.branchableCollections.has(collectionSlug)\n : globalSlug\n ? branching.branchableGlobals.has(globalSlug)\n : false\n\n if (!isBranchable) {\n return where\n }\n\n const branch = branchOverride ?? resolveBranch(req as PayloadRequest)\n\n if (branch === MAIN_BRANCH) {\n return appendBranchFilter({\n branch,\n deletedIDs: [],\n enabled: true,\n shadowedIDs: [],\n where: where ?? {},\n })\n }\n\n const [manifest, deletions] = await Promise.all([\n loadBranchManifest(req as PayloadRequest),\n loadBranchDeletions(req as PayloadRequest),\n ])\n const shadowedIDs = collectionSlug ? (manifest.get(collectionSlug) ?? []) : []\n const deletedIDs = collectionSlug ? (deletions.get(collectionSlug) ?? []) : []\n\n // A shadow row's primary key is not the document's canonical ID, so any `id`\n // constraint has to be redirected before the branch predicate is applied.\n const rewritten = rewriteBranchIDs(where ?? {})\n\n if (shadowedIDs.length > branching.maxShadowedIDs) {\n req.payload.logger.warn(\n `Branch \"${branch}\" has shadowed ${shadowedIDs.length} documents in \"${collectionSlug}\", above maxShadowedIDs (${branching.maxShadowedIDs}). Read performance will degrade.`,\n )\n }\n\n return appendBranchFilter({\n branch,\n deletedIDs,\n enabled: true,\n shadowedIDs,\n where: rewritten ?? {},\n })\n}\n\n/**\n * Synchronous branch predicate, for query builders that are not async.\n *\n * Reads the change manifest that `resolveBranchQuery` has already loaded and\n * memoized on the request earlier in the same read. Returns `null` when\n * branching is inactive for the entity, so callers can skip cleanly.\n *\n * Join subqueries need this: they are assembled inside synchronous query\n * builders, but must carry the same branch predicate as the top-level read or\n * a branch would see main's related documents.\n */\nexport const getBranchPredicateSync = ({\n branch: branchOverride,\n collectionSlug,\n req,\n}: {\n branch?: false | string\n collectionSlug: string\n req?: Partial<PayloadRequest>\n}): null | Where => {\n if (branchOverride === false || !req?.payload) {\n return null\n }\n\n if ((req.context as Record<string, unknown> | undefined)?._branchBypass) {\n return null\n }\n\n const branching = req.payload.config?.branching\n\n if (!branching?.enabled || !branching.branchableCollections.has(collectionSlug)) {\n return null\n }\n\n const branch = branchOverride ?? resolveBranch(req as PayloadRequest)\n\n const shadowedIDs =\n branch === MAIN_BRANCH\n ? []\n : (peekBranchManifest(req as PayloadRequest).get(collectionSlug) ?? [])\n const deletedIDs =\n branch === MAIN_BRANCH\n ? []\n : (peekBranchDeletions(req as PayloadRequest).get(collectionSlug) ?? [])\n\n return appendBranchFilter({ branch, deletedIDs, enabled: true, shadowedIDs, where: {} })\n}\n"],"names":["appendBranchFilter","rewriteBranchIDs","loadBranchDeletions","loadBranchManifest","peekBranchDeletions","peekBranchManifest","resolveBranch","MAIN_BRANCH","resolveBranchReadState","branch","branchOverride","collectionSlug","globalSlug","req","branching","payload","config","isBranchable","Boolean","branchableCollections","has","branchableGlobals","isRequestBypassed","context","_branchBypass","isBypassed","enabled","useBranching","resolveBranchQuery","where","deletedIDs","shadowedIDs","manifest","deletions","Promise","all","get","rewritten","length","maxShadowedIDs","logger","warn","getBranchPredicateSync"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/branching/resolveBranchQuery.ts"],"sourcesContent":["import type { PayloadRequest, Where } from '../types/index.js'\n\nimport { appendBranchFilter } from './appendBranchFilter.js'\nimport { rewriteBranchIDs } from './branchIDs.js'\nimport {\n loadBranchDeletions,\n loadBranchManifest,\n peekBranchDeletions,\n peekBranchManifest,\n resolveBranch,\n} from './resolveBranch.js'\nimport { MAIN_BRANCH } from './types.js'\n\ntype Args = {\n /**\n * Explicit override. `false` bypasses branching entirely — used by the merge\n * engine, which must reach shadow rows by their real primary key, and by\n * cross-branch reads such as diff views.\n */\n branch?: false | string\n collectionSlug?: string\n globalSlug?: string\n req?: Partial<PayloadRequest>\n where: undefined | Where\n}\n\nexport type BranchReadState = {\n branch: string\n useBranching: boolean\n}\n\nexport const resolveBranchReadState = ({\n branch: branchOverride,\n collectionSlug,\n globalSlug,\n req,\n}: Omit<Args, 'where'>): BranchReadState => {\n const branching = req?.payload?.config?.branching\n const isBranchable = collectionSlug\n ? Boolean(branching?.branchableCollections.has(collectionSlug))\n : globalSlug\n ? Boolean(branching?.branchableGlobals.has(globalSlug))\n : false\n const isRequestBypassed = Boolean(\n (req?.context as Record<string, unknown> | undefined)?._branchBypass,\n )\n const isBypassed = branchOverride === false || isRequestBypassed\n\n if (isRequestBypassed && req?.payload) {\n resolveBranch(req as PayloadRequest)\n }\n\n if (!branching?.enabled || !isBranchable || isBypassed) {\n return {\n branch: typeof branchOverride === 'string' ? branchOverride : MAIN_BRANCH,\n useBranching: false,\n }\n }\n\n const branch =\n typeof branchOverride === 'string'\n ? branchOverride\n : req?.payload\n ? resolveBranch(req as PayloadRequest)\n : MAIN_BRANCH\n\n return {\n branch,\n useBranching: branch !== MAIN_BRANCH,\n }\n}\n\n/**\n * The single entry point adapters call to make a read branch-aware.\n *\n * Lives in `payload` rather than in each adapter so that Mongo and Drizzle\n * cannot drift apart on branch semantics — adapters supply only the query\n * translation they already do.\n *\n * Returns `where` untouched when branching is off, when the entity is not\n * branch-enabled, or when the caller opted out, so a branching-disabled config\n * takes the same code path it does today.\n */\nexport const resolveBranchQuery = async ({\n branch: branchOverride,\n collectionSlug,\n globalSlug,\n req,\n where,\n}: Args): Promise<undefined | Where> => {\n if (branchOverride === false || !req?.payload) {\n return where\n }\n\n // Local API `branch: false` bypass, carried on context so it survives the\n // hop from operation options into the adapter.\n if ((req.context as Record<string, unknown> | undefined)?._branchBypass) {\n return where\n }\n\n const branching = req.payload.config?.branching\n\n if (!branching?.enabled) {\n return where\n }\n\n const isBranchable = collectionSlug\n ? branching.branchableCollections.has(collectionSlug)\n : globalSlug\n ? branching.branchableGlobals.has(globalSlug)\n : false\n\n if (!isBranchable) {\n return where\n }\n\n const branch = branchOverride ?? resolveBranch(req as PayloadRequest)\n\n if (branch === MAIN_BRANCH) {\n return appendBranchFilter({\n branch,\n deletedIDs: [],\n enabled: true,\n shadowedIDs: [],\n where: where ?? {},\n })\n }\n\n const [manifest, deletions] = await Promise.all([\n loadBranchManifest(req as PayloadRequest),\n loadBranchDeletions(req as PayloadRequest),\n ])\n const shadowedIDs = collectionSlug ? (manifest.get(collectionSlug) ?? []) : []\n const deletedIDs = collectionSlug ? (deletions.get(collectionSlug) ?? []) : []\n\n // A shadow row's primary key is not the document's canonical ID, so any `id`\n // constraint has to be redirected before the branch predicate is applied.\n const rewritten = rewriteBranchIDs(where ?? {})\n\n return appendBranchFilter({\n branch,\n deletedIDs,\n enabled: true,\n shadowedIDs,\n where: rewritten ?? {},\n })\n}\n\n/**\n * Synchronous branch predicate, for query builders that are not async.\n *\n * Reads the change manifest that `resolveBranchQuery` has already loaded and\n * memoized on the request earlier in the same read. Returns `null` when\n * branching is inactive for the entity, so callers can skip cleanly.\n *\n * Join subqueries need this: they are assembled inside synchronous query\n * builders, but must carry the same branch predicate as the top-level read or\n * a branch would see main's related documents.\n */\nexport const getBranchPredicateSync = ({\n branch: branchOverride,\n collectionSlug,\n req,\n}: {\n branch?: false | string\n collectionSlug: string\n req?: Partial<PayloadRequest>\n}): null | Where => {\n if (branchOverride === false || !req?.payload) {\n return null\n }\n\n if ((req.context as Record<string, unknown> | undefined)?._branchBypass) {\n return null\n }\n\n const branching = req.payload.config?.branching\n\n if (!branching?.enabled || !branching.branchableCollections.has(collectionSlug)) {\n return null\n }\n\n const branch = branchOverride ?? resolveBranch(req as PayloadRequest)\n\n const shadowedIDs =\n branch === MAIN_BRANCH\n ? []\n : (peekBranchManifest(req as PayloadRequest).get(collectionSlug) ?? [])\n const deletedIDs =\n branch === MAIN_BRANCH\n ? []\n : (peekBranchDeletions(req as PayloadRequest).get(collectionSlug) ?? [])\n\n return appendBranchFilter({ branch, deletedIDs, enabled: true, shadowedIDs, where: {} })\n}\n"],"names":["appendBranchFilter","rewriteBranchIDs","loadBranchDeletions","loadBranchManifest","peekBranchDeletions","peekBranchManifest","resolveBranch","MAIN_BRANCH","resolveBranchReadState","branch","branchOverride","collectionSlug","globalSlug","req","branching","payload","config","isBranchable","Boolean","branchableCollections","has","branchableGlobals","isRequestBypassed","context","_branchBypass","isBypassed","enabled","useBranching","resolveBranchQuery","where","deletedIDs","shadowedIDs","manifest","deletions","Promise","all","get","rewritten","getBranchPredicateSync"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizeBranchingConfig.d.ts","sourceRoot":"","sources":["../../src/branching/sanitizeBranchingConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAS1D;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,YACrC,cAAc,EACd,YAAY,EACZ,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,CACf,CAAA;AAEV;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,kFAIpB,CAAA;AAIV;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB,WAAY,MAAM,KAAG,wBAiGxD,CAAA"}
1
+ {"version":3,"file":"sanitizeBranchingConfig.d.ts","sourceRoot":"","sources":["../../src/branching/sanitizeBranchingConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAS1D;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,YACrC,cAAc,EACd,YAAY,EACZ,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,CACf,CAAA;AAEV;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,kFAIpB,CAAA;AAEV;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB,WAAY,MAAM,KAAG,wBA+FxD,CAAA"}
@@ -22,7 +22,6 @@ import { defaultBranchMergeValidation } from './validation.js';
22
22
  branchesCollectionSlug,
23
23
  branchMergesCollectionSlug
24
24
  ];
25
- const DEFAULT_MAX_SHADOWED_IDS = 2000;
26
25
  /**
27
26
  * Resolves which collections and globals branching is active for.
28
27
  *
@@ -44,7 +43,6 @@ const DEFAULT_MAX_SHADOWED_IDS = 2000;
44
43
  branchableCollections: new Set(),
45
44
  branchableGlobals: new Set(),
46
45
  enabled: false,
47
- maxShadowedIDs: branching.maxShadowedIDs ?? DEFAULT_MAX_SHADOWED_IDS,
48
46
  validate: branching.validate ?? defaultBranchMergeValidation
49
47
  };
50
48
  if (!enabled) {
@@ -102,7 +100,6 @@ const DEFAULT_MAX_SHADOWED_IDS = 2000;
102
100
  branchableGlobals,
103
101
  enabled: true,
104
102
  hooks: branching.hooks,
105
- maxShadowedIDs: branching.maxShadowedIDs ?? DEFAULT_MAX_SHADOWED_IDS,
106
103
  validate: branching.validate ?? defaultBranchMergeValidation
107
104
  };
108
105
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/branching/sanitizeBranchingConfig.ts"],"sourcesContent":["import type { Config } from '../config/types.js'\nimport type { SanitizedBranchingConfig } from './types.js'\n\nimport {\n branchChangesCollectionSlug,\n branchesCollectionSlug,\n branchMergesCollectionSlug,\n} from './types.js'\nimport { defaultBranchMergeValidation } from './validation.js'\n\n/**\n * Built-in Payload collections. Branching is off for these by default because\n * none of them hold authored content, but each can opt in with `branching: true`\n * — except collections that store branch state itself, which cannot be branched\n * at all (see `hardExcludedSlugs`).\n */\nexport const corePayloadCollectionSlugs = [\n 'payload-jobs',\n 'payload-kv',\n 'payload-locked-documents',\n 'payload-migrations',\n 'payload-preferences',\n 'payload-query-presets',\n] as const\n\n/**\n * Branching these is circular: resolving which documents are shadowed on a\n * branch would require already knowing the active branch in order to read the\n * registry that answers exactly that question.\n */\nexport const hardExcludedSlugs = [\n branchChangesCollectionSlug,\n branchesCollectionSlug,\n branchMergesCollectionSlug,\n] as const\n\nconst DEFAULT_MAX_SHADOWED_IDS = 2000\n\n/**\n * Resolves which collections and globals branching is active for.\n *\n * Must run during `sanitizeConfig` rather than per-collection sanitization,\n * and the ordering is load-bearing in both directions:\n *\n * - **after** the default-user-collection injection, or an auto-created `users`\n * collection is missed;\n * - **before** the `sanitizeCollection` loop, which performs `_branch` field\n * injection and unique-index rewriting and needs the resolved set.\n *\n * Plugins have already run by this point (`buildConfig` executes them before\n * `sanitizeConfig`), so plugin-added auth collections are included.\n */\nexport const sanitizeBranchingConfig = (config: Config): SanitizedBranchingConfig => {\n const incoming = config.branching\n const enabled = Boolean(incoming)\n\n const branching = typeof incoming === 'object' ? incoming : {}\n\n const disabled: SanitizedBranchingConfig = {\n branchableCollections: new Set<string>(),\n branchableGlobals: new Set<string>(),\n enabled: false,\n maxShadowedIDs: branching.maxShadowedIDs ?? DEFAULT_MAX_SHADOWED_IDS,\n validate: branching.validate ?? defaultBranchMergeValidation,\n }\n\n if (!enabled) {\n return disabled\n }\n\n const isMultiTenantPluginEnabled = config.plugins?.some(\n (plugin) =>\n plugin.slug === '@payloadcms/plugin-multi-tenant' && plugin.options?.enabled !== false,\n )\n\n if (isMultiTenantPluginEnabled) {\n console.warn(\n '[Payload] Content branching and @payloadcms/plugin-multi-tenant are enabled together. This combination is not supported and does not provide tenant isolation.',\n )\n }\n\n const explicitlyExcluded = new Set<string>(branching.exclude ?? [])\n const offByDefault = new Set<string>(corePayloadCollectionSlugs)\n\n // The KV collection's slug is configurable, so the literal above only covers\n // the default. Branching it is meaningless — it is a key-value store, not\n // content — and actively harmful: its `key` is unique, so the rewrite turns\n // that into a branch-scoped compound index, and `ensureIndexes` then refuses to\n // reconcile it against a database that already has the unique one. That fails\n // at connect time, which takes the whole instance down rather than degrading.\n const kvCollectionSlug = config.kv?.kvCollection?.slug\n\n if (kvCollectionSlug) {\n offByDefault.add(kvCollectionSlug)\n }\n\n const branchableCollections = new Set<string>()\n\n for (const collection of config.collections ?? []) {\n const { slug } = collection\n\n if ((hardExcludedSlugs as readonly string[]).includes(slug)) {\n if (collection.branching === true) {\n throw new Error(\n `Collection \"${slug}\" stores branch state and cannot itself be branched. Remove \\`branching: true\\` from it.`,\n )\n }\n continue\n }\n\n if (collection.auth) {\n if (collection.branching === true) {\n throw new Error(\n `Collection \"${slug}\" has authentication enabled and cannot be branched. Remove \\`branching: true\\` from it.`,\n )\n }\n continue\n }\n\n if (explicitlyExcluded.has(slug) || collection.branching === false) {\n continue\n }\n\n if (offByDefault.has(slug) && collection.branching !== true) {\n continue\n }\n\n branchableCollections.add(slug)\n }\n\n const branchableGlobals = new Set<string>()\n\n for (const global of config.globals ?? []) {\n if (explicitlyExcluded.has(global.slug) || global.branching === false) {\n continue\n }\n\n branchableGlobals.add(global.slug)\n }\n\n return {\n access: branching.access,\n branchableCollections,\n branchableGlobals,\n enabled: true,\n hooks: branching.hooks,\n maxShadowedIDs: branching.maxShadowedIDs ?? DEFAULT_MAX_SHADOWED_IDS,\n validate: branching.validate ?? defaultBranchMergeValidation,\n }\n}\n"],"names":["branchChangesCollectionSlug","branchesCollectionSlug","branchMergesCollectionSlug","defaultBranchMergeValidation","corePayloadCollectionSlugs","hardExcludedSlugs","DEFAULT_MAX_SHADOWED_IDS","sanitizeBranchingConfig","config","incoming","branching","enabled","Boolean","disabled","branchableCollections","Set","branchableGlobals","maxShadowedIDs","validate","isMultiTenantPluginEnabled","plugins","some","plugin","slug","options","console","warn","explicitlyExcluded","exclude","offByDefault","kvCollectionSlug","kv","kvCollection","add","collection","collections","includes","Error","auth","has","global","globals","access","hooks"],"mappings":"AAGA,SACEA,2BAA2B,EAC3BC,sBAAsB,EACtBC,0BAA0B,QACrB,aAAY;AACnB,SAASC,4BAA4B,QAAQ,kBAAiB;AAE9D;;;;;CAKC,GACD,OAAO,MAAMC,6BAA6B;IACxC;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAEV;;;;CAIC,GACD,OAAO,MAAMC,oBAAoB;IAC/BL;IACAC;IACAC;CACD,CAAS;AAEV,MAAMI,2BAA2B;AAEjC;;;;;;;;;;;;;CAaC,GACD,OAAO,MAAMC,0BAA0B,CAACC;IACtC,MAAMC,WAAWD,OAAOE,SAAS;IACjC,MAAMC,UAAUC,QAAQH;IAExB,MAAMC,YAAY,OAAOD,aAAa,WAAWA,WAAW,CAAC;IAE7D,MAAMI,WAAqC;QACzCC,uBAAuB,IAAIC;QAC3BC,mBAAmB,IAAID;QACvBJ,SAAS;QACTM,gBAAgBP,UAAUO,cAAc,IAAIX;QAC5CY,UAAUR,UAAUQ,QAAQ,IAAIf;IAClC;IAEA,IAAI,CAACQ,SAAS;QACZ,OAAOE;IACT;IAEA,MAAMM,6BAA6BX,OAAOY,OAAO,EAAEC,KACjD,CAACC,SACCA,OAAOC,IAAI,KAAK,qCAAqCD,OAAOE,OAAO,EAAEb,YAAY;IAGrF,IAAIQ,4BAA4B;QAC9BM,QAAQC,IAAI,CACV;IAEJ;IAEA,MAAMC,qBAAqB,IAAIZ,IAAYL,UAAUkB,OAAO,IAAI,EAAE;IAClE,MAAMC,eAAe,IAAId,IAAYX;IAErC,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,gFAAgF;IAChF,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAM0B,mBAAmBtB,OAAOuB,EAAE,EAAEC,cAAcT;IAElD,IAAIO,kBAAkB;QACpBD,aAAaI,GAAG,CAACH;IACnB;IAEA,MAAMhB,wBAAwB,IAAIC;IAElC,KAAK,MAAMmB,cAAc1B,OAAO2B,WAAW,IAAI,EAAE,CAAE;QACjD,MAAM,EAAEZ,IAAI,EAAE,GAAGW;QAEjB,IAAI,AAAC7B,kBAAwC+B,QAAQ,CAACb,OAAO;YAC3D,IAAIW,WAAWxB,SAAS,KAAK,MAAM;gBACjC,MAAM,IAAI2B,MACR,CAAC,YAAY,EAAEd,KAAK,wFAAwF,CAAC;YAEjH;YACA;QACF;QAEA,IAAIW,WAAWI,IAAI,EAAE;YACnB,IAAIJ,WAAWxB,SAAS,KAAK,MAAM;gBACjC,MAAM,IAAI2B,MACR,CAAC,YAAY,EAAEd,KAAK,wFAAwF,CAAC;YAEjH;YACA;QACF;QAEA,IAAII,mBAAmBY,GAAG,CAAChB,SAASW,WAAWxB,SAAS,KAAK,OAAO;YAClE;QACF;QAEA,IAAImB,aAAaU,GAAG,CAAChB,SAASW,WAAWxB,SAAS,KAAK,MAAM;YAC3D;QACF;QAEAI,sBAAsBmB,GAAG,CAACV;IAC5B;IAEA,MAAMP,oBAAoB,IAAID;IAE9B,KAAK,MAAMyB,UAAUhC,OAAOiC,OAAO,IAAI,EAAE,CAAE;QACzC,IAAId,mBAAmBY,GAAG,CAACC,OAAOjB,IAAI,KAAKiB,OAAO9B,SAAS,KAAK,OAAO;YACrE;QACF;QAEAM,kBAAkBiB,GAAG,CAACO,OAAOjB,IAAI;IACnC;IAEA,OAAO;QACLmB,QAAQhC,UAAUgC,MAAM;QACxB5B;QACAE;QACAL,SAAS;QACTgC,OAAOjC,UAAUiC,KAAK;QACtB1B,gBAAgBP,UAAUO,cAAc,IAAIX;QAC5CY,UAAUR,UAAUQ,QAAQ,IAAIf;IAClC;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/branching/sanitizeBranchingConfig.ts"],"sourcesContent":["import type { Config } from '../config/types.js'\nimport type { SanitizedBranchingConfig } from './types.js'\n\nimport {\n branchChangesCollectionSlug,\n branchesCollectionSlug,\n branchMergesCollectionSlug,\n} from './types.js'\nimport { defaultBranchMergeValidation } from './validation.js'\n\n/**\n * Built-in Payload collections. Branching is off for these by default because\n * none of them hold authored content, but each can opt in with `branching: true`\n * — except collections that store branch state itself, which cannot be branched\n * at all (see `hardExcludedSlugs`).\n */\nexport const corePayloadCollectionSlugs = [\n 'payload-jobs',\n 'payload-kv',\n 'payload-locked-documents',\n 'payload-migrations',\n 'payload-preferences',\n 'payload-query-presets',\n] as const\n\n/**\n * Branching these is circular: resolving which documents are shadowed on a\n * branch would require already knowing the active branch in order to read the\n * registry that answers exactly that question.\n */\nexport const hardExcludedSlugs = [\n branchChangesCollectionSlug,\n branchesCollectionSlug,\n branchMergesCollectionSlug,\n] as const\n\n/**\n * Resolves which collections and globals branching is active for.\n *\n * Must run during `sanitizeConfig` rather than per-collection sanitization,\n * and the ordering is load-bearing in both directions:\n *\n * - **after** the default-user-collection injection, or an auto-created `users`\n * collection is missed;\n * - **before** the `sanitizeCollection` loop, which performs `_branch` field\n * injection and unique-index rewriting and needs the resolved set.\n *\n * Plugins have already run by this point (`buildConfig` executes them before\n * `sanitizeConfig`), so plugin-added auth collections are included.\n */\nexport const sanitizeBranchingConfig = (config: Config): SanitizedBranchingConfig => {\n const incoming = config.branching\n const enabled = Boolean(incoming)\n\n const branching = typeof incoming === 'object' ? incoming : {}\n\n const disabled: SanitizedBranchingConfig = {\n branchableCollections: new Set<string>(),\n branchableGlobals: new Set<string>(),\n enabled: false,\n validate: branching.validate ?? defaultBranchMergeValidation,\n }\n\n if (!enabled) {\n return disabled\n }\n\n const isMultiTenantPluginEnabled = config.plugins?.some(\n (plugin) =>\n plugin.slug === '@payloadcms/plugin-multi-tenant' && plugin.options?.enabled !== false,\n )\n\n if (isMultiTenantPluginEnabled) {\n console.warn(\n '[Payload] Content branching and @payloadcms/plugin-multi-tenant are enabled together. This combination is not supported and does not provide tenant isolation.',\n )\n }\n\n const explicitlyExcluded = new Set<string>(branching.exclude ?? [])\n const offByDefault = new Set<string>(corePayloadCollectionSlugs)\n\n // The KV collection's slug is configurable, so the literal above only covers\n // the default. Branching it is meaningless — it is a key-value store, not\n // content — and actively harmful: its `key` is unique, so the rewrite turns\n // that into a branch-scoped compound index, and `ensureIndexes` then refuses to\n // reconcile it against a database that already has the unique one. That fails\n // at connect time, which takes the whole instance down rather than degrading.\n const kvCollectionSlug = config.kv?.kvCollection?.slug\n\n if (kvCollectionSlug) {\n offByDefault.add(kvCollectionSlug)\n }\n\n const branchableCollections = new Set<string>()\n\n for (const collection of config.collections ?? []) {\n const { slug } = collection\n\n if ((hardExcludedSlugs as readonly string[]).includes(slug)) {\n if (collection.branching === true) {\n throw new Error(\n `Collection \"${slug}\" stores branch state and cannot itself be branched. Remove \\`branching: true\\` from it.`,\n )\n }\n continue\n }\n\n if (collection.auth) {\n if (collection.branching === true) {\n throw new Error(\n `Collection \"${slug}\" has authentication enabled and cannot be branched. Remove \\`branching: true\\` from it.`,\n )\n }\n continue\n }\n\n if (explicitlyExcluded.has(slug) || collection.branching === false) {\n continue\n }\n\n if (offByDefault.has(slug) && collection.branching !== true) {\n continue\n }\n\n branchableCollections.add(slug)\n }\n\n const branchableGlobals = new Set<string>()\n\n for (const global of config.globals ?? []) {\n if (explicitlyExcluded.has(global.slug) || global.branching === false) {\n continue\n }\n\n branchableGlobals.add(global.slug)\n }\n\n return {\n access: branching.access,\n branchableCollections,\n branchableGlobals,\n enabled: true,\n hooks: branching.hooks,\n validate: branching.validate ?? defaultBranchMergeValidation,\n }\n}\n"],"names":["branchChangesCollectionSlug","branchesCollectionSlug","branchMergesCollectionSlug","defaultBranchMergeValidation","corePayloadCollectionSlugs","hardExcludedSlugs","sanitizeBranchingConfig","config","incoming","branching","enabled","Boolean","disabled","branchableCollections","Set","branchableGlobals","validate","isMultiTenantPluginEnabled","plugins","some","plugin","slug","options","console","warn","explicitlyExcluded","exclude","offByDefault","kvCollectionSlug","kv","kvCollection","add","collection","collections","includes","Error","auth","has","global","globals","access","hooks"],"mappings":"AAGA,SACEA,2BAA2B,EAC3BC,sBAAsB,EACtBC,0BAA0B,QACrB,aAAY;AACnB,SAASC,4BAA4B,QAAQ,kBAAiB;AAE9D;;;;;CAKC,GACD,OAAO,MAAMC,6BAA6B;IACxC;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAEV;;;;CAIC,GACD,OAAO,MAAMC,oBAAoB;IAC/BL;IACAC;IACAC;CACD,CAAS;AAEV;;;;;;;;;;;;;CAaC,GACD,OAAO,MAAMI,0BAA0B,CAACC;IACtC,MAAMC,WAAWD,OAAOE,SAAS;IACjC,MAAMC,UAAUC,QAAQH;IAExB,MAAMC,YAAY,OAAOD,aAAa,WAAWA,WAAW,CAAC;IAE7D,MAAMI,WAAqC;QACzCC,uBAAuB,IAAIC;QAC3BC,mBAAmB,IAAID;QACvBJ,SAAS;QACTM,UAAUP,UAAUO,QAAQ,IAAIb;IAClC;IAEA,IAAI,CAACO,SAAS;QACZ,OAAOE;IACT;IAEA,MAAMK,6BAA6BV,OAAOW,OAAO,EAAEC,KACjD,CAACC,SACCA,OAAOC,IAAI,KAAK,qCAAqCD,OAAOE,OAAO,EAAEZ,YAAY;IAGrF,IAAIO,4BAA4B;QAC9BM,QAAQC,IAAI,CACV;IAEJ;IAEA,MAAMC,qBAAqB,IAAIX,IAAYL,UAAUiB,OAAO,IAAI,EAAE;IAClE,MAAMC,eAAe,IAAIb,IAAYV;IAErC,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,gFAAgF;IAChF,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAMwB,mBAAmBrB,OAAOsB,EAAE,EAAEC,cAAcT;IAElD,IAAIO,kBAAkB;QACpBD,aAAaI,GAAG,CAACH;IACnB;IAEA,MAAMf,wBAAwB,IAAIC;IAElC,KAAK,MAAMkB,cAAczB,OAAO0B,WAAW,IAAI,EAAE,CAAE;QACjD,MAAM,EAAEZ,IAAI,EAAE,GAAGW;QAEjB,IAAI,AAAC3B,kBAAwC6B,QAAQ,CAACb,OAAO;YAC3D,IAAIW,WAAWvB,SAAS,KAAK,MAAM;gBACjC,MAAM,IAAI0B,MACR,CAAC,YAAY,EAAEd,KAAK,wFAAwF,CAAC;YAEjH;YACA;QACF;QAEA,IAAIW,WAAWI,IAAI,EAAE;YACnB,IAAIJ,WAAWvB,SAAS,KAAK,MAAM;gBACjC,MAAM,IAAI0B,MACR,CAAC,YAAY,EAAEd,KAAK,wFAAwF,CAAC;YAEjH;YACA;QACF;QAEA,IAAII,mBAAmBY,GAAG,CAAChB,SAASW,WAAWvB,SAAS,KAAK,OAAO;YAClE;QACF;QAEA,IAAIkB,aAAaU,GAAG,CAAChB,SAASW,WAAWvB,SAAS,KAAK,MAAM;YAC3D;QACF;QAEAI,sBAAsBkB,GAAG,CAACV;IAC5B;IAEA,MAAMN,oBAAoB,IAAID;IAE9B,KAAK,MAAMwB,UAAU/B,OAAOgC,OAAO,IAAI,EAAE,CAAE;QACzC,IAAId,mBAAmBY,GAAG,CAACC,OAAOjB,IAAI,KAAKiB,OAAO7B,SAAS,KAAK,OAAO;YACrE;QACF;QAEAM,kBAAkBgB,GAAG,CAACO,OAAOjB,IAAI;IACnC;IAEA,OAAO;QACLmB,QAAQ/B,UAAU+B,MAAM;QACxB3B;QACAE;QACAL,SAAS;QACT+B,OAAOhC,UAAUgC,KAAK;QACtBzB,UAAUP,UAAUO,QAAQ,IAAIb;IAClC;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/branching/schedule/job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,gBAAgB,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAO9C,MAAM,MAAM,sBAAsB,GAAG;IACnC,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAA;IACd,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,0EAA0E;IAC1E,IAAI,CAAC,EACD;QACE,UAAU,EAAE,cAAc,CAAA;QAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;KACvB,GACD,MAAM,GACN,MAAM,CAAA;CACX,CAAA;AAED,KAAK,IAAI,GAAG;IACV,mBAAmB,EAAE,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,oBAAoB,6BAE9B,IAAI,KAAG,UAAU,CAAC;IACnB,KAAK,EAAE,sBAAsB,CAAA;IAC7B,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,CAAA;KAAE,CAAA;CAC9D,CA6HC,CAAA"}
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/branching/schedule/job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,gBAAgB,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAO9C,MAAM,MAAM,sBAAsB,GAAG;IACnC,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAA;IACd,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,0EAA0E;IAC1E,IAAI,CAAC,EACD;QACE,UAAU,EAAE,cAAc,CAAA;QAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;KACvB,GACD,MAAM,GACN,MAAM,CAAA;CACX,CAAA;AAED,KAAK,IAAI,GAAG;IACV,mBAAmB,EAAE,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,oBAAoB,6BAE9B,IAAI,KAAG,UAAU,CAAC;IACnB,KAAK,EAAE,sBAAsB,CAAA;IAC7B,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,CAAA;KAAE,CAAA;CAC9D,CAuIC,CAAA"}
@@ -99,6 +99,13 @@ import { branchesCollectionSlug } from '../types.js';
99
99
  req,
100
100
  user
101
101
  });
102
+ const problems = [
103
+ ...result.blocked,
104
+ ...result.validationErrors
105
+ ];
106
+ if (problems.length) {
107
+ throw new Error(`Scheduled merge of branch "${input.branch}" was refused: ${problems.map(({ message })=>message).join('; ')}`);
108
+ }
102
109
  } catch (error) {
103
110
  try {
104
111
  await writeProgress({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/branching/schedule/job.ts"],"sourcesContent":["import type { CollectionSlug, User } from '../../index.js'\nimport type { TaskConfig } from '../../queues/config/types/taskTypes.js'\nimport type { MergeResult } from '../merge.js'\n\nimport { isolateObjectProperty } from '../../utilities/isolateObjectProperty.js'\nimport { createIsolatedDeferredCleanupContext } from '../../utilities/transactionCallbacks.js'\nimport { mergeBranch } from '../merge.js'\nimport { branchesCollectionSlug } from '../types.js'\n\nexport type ScheduleMergeTaskInput = {\n /** Branch slug. Stored rather than the document ID: the slug is what `_branch` holds. */\n branch: string\n /** Change IDs to apply, or empty to apply whatever is pending when the job fires. */\n changes?: string[]\n closeBranch?: boolean\n /** The user whose production permissions the merge is checked against. */\n user?:\n | {\n relationTo: CollectionSlug\n value: number | string\n }\n | number\n | string\n}\n\ntype Args = {\n authCollectionSlugs: string[]\n}\n\n/**\n * The `scheduleMerge` task: applies a branch to main at an appointed time.\n *\n * Modelled on `schedulePublish`, and identical in shape — a job carrying the intent,\n * the user who formed it, and a `waitUntil`. Merging raises three questions that\n * publishing one document does not, and the answers are the substance of this task:\n *\n * **Whose permissions?** The queueing user's, re-resolved at fire time and applied\n * through the ordinary preflight (`overrideAccess: false`). This deliberately differs\n * from `schedulePublish`, which falls back to `overrideAccess: user === null` when the\n * user has since been deleted. A merge writes across production, so the same fallback\n * would turn a deleted account into an unchecked one — the job fails instead, and a\n * failed job is a signal someone can act on.\n *\n * **What if the branch moved?** Queued change IDs that no longer exist are skipped:\n * `mergeBranch` matches the selection against what is pending, so a discarded or\n * already-merged change simply does not match. A schedule with no selection applies\n * whatever is pending when it fires, which is what \"merge this branch at 9am\" means.\n *\n * **What if main moved?** It proceeds. `main-moved` is advisory even interactively —\n * branch data wins outright (§16) — and failing would leave the branch unmerged with\n * nobody watching either. The warnings are returned as task output so they remain\n * inspectable on the job afterwards.\n */\nexport const getScheduleMergeTask = ({\n authCollectionSlugs,\n}: Args): TaskConfig<{\n input: ScheduleMergeTaskInput\n output: { merged: number; warnings: MergeResult['warnings'] }\n}> => ({\n slug: 'scheduleMerge',\n handler: async ({ input, req }) => {\n let user: null | User = null\n\n if (input.user != null) {\n if (typeof input.user !== 'object') {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" is missing the scheduling user auth collection and cannot run.`,\n )\n }\n\n if (\n typeof input.user.relationTo !== 'string' ||\n !authCollectionSlugs.includes(input.user.relationTo) ||\n (typeof input.user.value !== 'number' && typeof input.user.value !== 'string')\n ) {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" has an invalid scheduling user relationship and cannot run.`,\n )\n }\n\n user = (await req.payload.findByID({\n id: input.user.value,\n collection: input.user.relationTo,\n depth: 0,\n disableErrors: true,\n overrideAccess: true,\n req,\n })) as null | User\n\n if (user) {\n user.collection = input.user.relationTo\n }\n }\n\n if (!user) {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" has no resolvable user, so its permissions cannot be checked. Re-schedule it as a current user.`,\n )\n }\n\n const branchDoc = (\n await req.payload.find({\n collection: branchesCollectionSlug,\n depth: 0,\n limit: 1,\n overrideAccess: true,\n pagination: false,\n req,\n where: { slug: { equals: input.branch } },\n })\n ).docs[0]\n\n const progressReq = isolateObjectProperty(req, ['context', 'transactionID'])\n\n progressReq.context = createIsolatedDeferredCleanupContext({ req })\n delete progressReq.transactionID\n\n const writeProgress = async ({ mergeProgress }: { mergeProgress: null | string }) => {\n if (branchDoc) {\n await req.payload.update({\n id: branchDoc.id,\n collection: branchesCollectionSlug,\n data: { mergeProgress },\n depth: 0,\n overrideAccess: true,\n req: progressReq,\n })\n }\n }\n\n await writeProgress({ mergeProgress: 'running' })\n\n let result: MergeResult\n\n try {\n result = await mergeBranch(req.payload, {\n branch: input.branch,\n changes: input.changes?.length ? input.changes : undefined,\n closeBranch: Boolean(input.closeBranch),\n overrideAccess: false,\n req,\n user,\n })\n } catch (error) {\n try {\n await writeProgress({ mergeProgress: null })\n } catch (err) {\n req.payload.logger.error({ err, msg: 'Failed to clear scheduled merge progress.' })\n }\n\n throw error\n }\n\n // Cleared after a successful merge too: a stale \"running\" outlives the run and reads as a\n // merge still in flight. A cleanup failure now fails the job because there is no primary merge\n // error to preserve.\n await writeProgress({ mergeProgress: null })\n\n return {\n output: { merged: result.merged.length, warnings: result.warnings },\n }\n },\n inputSchema: [\n {\n name: 'branch',\n type: 'text',\n required: true,\n },\n {\n name: 'changes',\n type: 'text',\n hasMany: true,\n },\n {\n name: 'closeBranch',\n type: 'checkbox',\n },\n {\n name: 'user',\n type: 'relationship',\n relationTo: authCollectionSlugs,\n },\n ],\n})\n"],"names":["isolateObjectProperty","createIsolatedDeferredCleanupContext","mergeBranch","branchesCollectionSlug","getScheduleMergeTask","authCollectionSlugs","slug","handler","input","req","user","Error","branch","relationTo","includes","value","payload","findByID","id","collection","depth","disableErrors","overrideAccess","branchDoc","find","limit","pagination","where","equals","docs","progressReq","context","transactionID","writeProgress","mergeProgress","update","data","result","changes","length","undefined","closeBranch","Boolean","error","err","logger","msg","output","merged","warnings","inputSchema","name","type","required","hasMany"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/branching/schedule/job.ts"],"sourcesContent":["import type { CollectionSlug, User } from '../../index.js'\nimport type { TaskConfig } from '../../queues/config/types/taskTypes.js'\nimport type { MergeResult } from '../merge.js'\n\nimport { isolateObjectProperty } from '../../utilities/isolateObjectProperty.js'\nimport { createIsolatedDeferredCleanupContext } from '../../utilities/transactionCallbacks.js'\nimport { mergeBranch } from '../merge.js'\nimport { branchesCollectionSlug } from '../types.js'\n\nexport type ScheduleMergeTaskInput = {\n /** Branch slug. Stored rather than the document ID: the slug is what `_branch` holds. */\n branch: string\n /** Change IDs to apply, or empty to apply whatever is pending when the job fires. */\n changes?: string[]\n closeBranch?: boolean\n /** The user whose production permissions the merge is checked against. */\n user?:\n | {\n relationTo: CollectionSlug\n value: number | string\n }\n | number\n | string\n}\n\ntype Args = {\n authCollectionSlugs: string[]\n}\n\n/**\n * The `scheduleMerge` task: applies a branch to main at an appointed time.\n *\n * Modelled on `schedulePublish`, and identical in shape — a job carrying the intent,\n * the user who formed it, and a `waitUntil`. Merging raises three questions that\n * publishing one document does not, and the answers are the substance of this task:\n *\n * **Whose permissions?** The queueing user's, re-resolved at fire time and applied\n * through the ordinary preflight (`overrideAccess: false`). This deliberately differs\n * from `schedulePublish`, which falls back to `overrideAccess: user === null` when the\n * user has since been deleted. A merge writes across production, so the same fallback\n * would turn a deleted account into an unchecked one — the job fails instead, and a\n * failed job is a signal someone can act on.\n *\n * **What if the branch moved?** Queued change IDs that no longer exist are skipped:\n * `mergeBranch` matches the selection against what is pending, so a discarded or\n * already-merged change simply does not match. A schedule with no selection applies\n * whatever is pending when it fires, which is what \"merge this branch at 9am\" means.\n *\n * **What if main moved?** It proceeds. `main-moved` is advisory even interactively —\n * branch data wins outright (§16) — and failing would leave the branch unmerged with\n * nobody watching either. The warnings are returned as task output so they remain\n * inspectable on the job afterwards.\n */\nexport const getScheduleMergeTask = ({\n authCollectionSlugs,\n}: Args): TaskConfig<{\n input: ScheduleMergeTaskInput\n output: { merged: number; warnings: MergeResult['warnings'] }\n}> => ({\n slug: 'scheduleMerge',\n handler: async ({ input, req }) => {\n let user: null | User = null\n\n if (input.user != null) {\n if (typeof input.user !== 'object') {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" is missing the scheduling user auth collection and cannot run.`,\n )\n }\n\n if (\n typeof input.user.relationTo !== 'string' ||\n !authCollectionSlugs.includes(input.user.relationTo) ||\n (typeof input.user.value !== 'number' && typeof input.user.value !== 'string')\n ) {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" has an invalid scheduling user relationship and cannot run.`,\n )\n }\n\n user = (await req.payload.findByID({\n id: input.user.value,\n collection: input.user.relationTo,\n depth: 0,\n disableErrors: true,\n overrideAccess: true,\n req,\n })) as null | User\n\n if (user) {\n user.collection = input.user.relationTo\n }\n }\n\n if (!user) {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" has no resolvable user, so its permissions cannot be checked. Re-schedule it as a current user.`,\n )\n }\n\n const branchDoc = (\n await req.payload.find({\n collection: branchesCollectionSlug,\n depth: 0,\n limit: 1,\n overrideAccess: true,\n pagination: false,\n req,\n where: { slug: { equals: input.branch } },\n })\n ).docs[0]\n\n const progressReq = isolateObjectProperty(req, ['context', 'transactionID'])\n\n progressReq.context = createIsolatedDeferredCleanupContext({ req })\n delete progressReq.transactionID\n\n const writeProgress = async ({ mergeProgress }: { mergeProgress: null | string }) => {\n if (branchDoc) {\n await req.payload.update({\n id: branchDoc.id,\n collection: branchesCollectionSlug,\n data: { mergeProgress },\n depth: 0,\n overrideAccess: true,\n req: progressReq,\n })\n }\n }\n\n await writeProgress({ mergeProgress: 'running' })\n\n let result: MergeResult\n\n try {\n result = await mergeBranch(req.payload, {\n branch: input.branch,\n changes: input.changes?.length ? input.changes : undefined,\n closeBranch: Boolean(input.closeBranch),\n overrideAccess: false,\n req,\n user,\n })\n\n const problems = [...result.blocked, ...result.validationErrors]\n\n if (problems.length) {\n throw new Error(\n `Scheduled merge of branch \"${input.branch}\" was refused: ${problems\n .map(({ message }) => message)\n .join('; ')}`,\n )\n }\n } catch (error) {\n try {\n await writeProgress({ mergeProgress: null })\n } catch (err) {\n req.payload.logger.error({ err, msg: 'Failed to clear scheduled merge progress.' })\n }\n\n throw error\n }\n\n // Cleared after a successful merge too: a stale \"running\" outlives the run and reads as a\n // merge still in flight. A cleanup failure now fails the job because there is no primary merge\n // error to preserve.\n await writeProgress({ mergeProgress: null })\n\n return {\n output: { merged: result.merged.length, warnings: result.warnings },\n }\n },\n inputSchema: [\n {\n name: 'branch',\n type: 'text',\n required: true,\n },\n {\n name: 'changes',\n type: 'text',\n hasMany: true,\n },\n {\n name: 'closeBranch',\n type: 'checkbox',\n },\n {\n name: 'user',\n type: 'relationship',\n relationTo: authCollectionSlugs,\n },\n ],\n})\n"],"names":["isolateObjectProperty","createIsolatedDeferredCleanupContext","mergeBranch","branchesCollectionSlug","getScheduleMergeTask","authCollectionSlugs","slug","handler","input","req","user","Error","branch","relationTo","includes","value","payload","findByID","id","collection","depth","disableErrors","overrideAccess","branchDoc","find","limit","pagination","where","equals","docs","progressReq","context","transactionID","writeProgress","mergeProgress","update","data","result","changes","length","undefined","closeBranch","Boolean","problems","blocked","validationErrors","map","message","join","error","err","logger","msg","output","merged","warnings","inputSchema","name","type","required","hasMany"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { CollectionSlug } from '../index.js';
1
+ import type { CollectionSlug, GlobalSlug } from '../index.js';
2
2
  import type { PayloadRequest } from '../types/index.js';
3
3
  import type { Access } from './../config/types.js';
4
4
  import type { BranchMergeValidate } from './validation.js';
@@ -99,9 +99,10 @@ export type BranchingConfig = {
99
99
  updateBranch?: Access;
100
100
  };
101
101
  /**
102
- * Collections to exclude from branching, in addition to the defaults.
102
+ * Collection and global slugs to exclude from branching, in addition to the defaults.
103
+ * Exclusions take precedence over an entity's `branching: true` setting.
103
104
  */
104
- exclude?: CollectionSlug[];
105
+ exclude?: (CollectionSlug | GlobalSlug)[];
105
106
  /**
106
107
  * Branch lifecycle hooks. Document hooks are unaffected — every one of them
107
108
  * runs on merge, since merge is a genuine write to main.
@@ -121,15 +122,6 @@ export type BranchingConfig = {
121
122
  warnings: MergeWarning[];
122
123
  }) => Promise<void> | void;
123
124
  };
124
- /**
125
- * Ceiling on the number of shadowed document IDs injected into a single read
126
- * predicate by database adapters that use the legacy branch visibility fallback.
127
- * Official adapters use database-native branch visibility instead.
128
- *
129
- * @deprecated Retained for adapters that use the legacy branch visibility fallback.
130
- * @default 2000
131
- */
132
- maxShadowedIDs?: number;
133
125
  /**
134
126
  * Replaces the default best-effort pre-merge content validation policy.
135
127
  * Ordinary write validation, hooks, access control, and database constraints still apply.
@@ -142,7 +134,6 @@ export type SanitizedBranchingConfig = {
142
134
  /** Slugs of every global branching is active for. */
143
135
  branchableGlobals: Set<string>;
144
136
  enabled: boolean;
145
- maxShadowedIDs: number;
146
137
  validate: BranchMergeValidate;
147
138
  } & Omit<BranchingConfig, 'exclude' | 'validate'>;
148
139
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/branching/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/branching/types.ts"],"names":[],"mappings":"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"}