{"version":3,"file":"bidirectional-relations.mjs","sources":["../../../../src/services/document-service/utils/bidirectional-relations.ts"],"sourcesContent":["import { keyBy, omit } from 'lodash/fp';\nimport type { UID, Schema } from '@strapi/types';\nimport type { JoinTable } from '@strapi/database';\n\ninterface LoadContext {\n oldVersions: { id: string; locale: string }[];\n newVersions: { id: string; locale: string }[];\n}\n\ninterface RelationEntry {\n joinTable: JoinTable;\n relations: Record[];\n /** FK column for the entity being published */\n entityColumn: string;\n /** FK column for the related entity */\n relatedColumn: string;\n}\n\n/** Draft id → published id for rows that already have a published counterpart (same document_id + locale). */\nconst draftToPublishedMap = async (trx: any, tableName: string, rowIds: unknown[]) => {\n const uniqueIds = [...new Set(rowIds)];\n if (uniqueIds.length === 0) {\n return new Map();\n }\n\n const draftEntries = await strapi.db\n .getConnection()\n .select('id', 'document_id', 'locale')\n .from(tableName)\n .whereIn('id', uniqueIds as any)\n .transacting(trx);\n\n if (draftEntries.length === 0) {\n return new Map();\n }\n\n const pubEntries = await strapi.db\n .getConnection()\n .select('id', 'document_id', 'locale')\n .from(tableName)\n .whereNotNull('published_at')\n .whereIn(\n 'document_id',\n draftEntries.map((e: any) => e.document_id)\n )\n .transacting(trx);\n\n const pubByDocLocale = new Map(\n pubEntries.map((e: any) => [`${e.document_id}_${e.locale}`, e.id])\n );\n\n const map = new Map();\n for (const d of draftEntries) {\n const pubId = pubByDocLocale.get(`${d.document_id}_${d.locale}`);\n if (pubId) {\n map.set(String(d.id), String(pubId));\n }\n }\n return map;\n};\n\nconst remapRelatedIds = (rows: any[], relatedCol: string, idMap: Map) =>\n rows.map((row) => {\n const next = idMap.get(String(row[relatedCol]));\n return next ? { ...row, [relatedCol]: next } : row;\n });\n\n/**\n * Reads join rows tied to the entry being published (`publishedCol` IN draft/old ids) and returns\n * batches for `sync()`. When the FK in `relatedCol` points at a D&P type, maps known draft ids to\n * published ids; otherwise keeps draft ids so sync can still run after both sides exist.\n */\nconst captureJoinBatches = async (\n trx: any,\n opts: {\n joinTable: any;\n /** Column holding ids of the document being published (the `uid` passed to load). */\n publishedCol: string;\n /** The other FK; may be remapped via draftToPublishedMap. */\n relatedCol: string;\n /** Content type behind `relatedCol` (used for D&P + table name). */\n relatedUid: UID.ContentType;\n relatedHasDraftAndPublish: boolean;\n /** Model that owns this attribute; draft capture is skipped for components. */\n schemaUid: UID.ContentType;\n /**\n * True when the attribute being captured is the owning side of the relation and the entity\n * being published owns it (e.g. publishing an Article for `Article.categories`). In that case\n * the owning-side order is rebuilt from the draft by `entries.publish`, so capturing the old\n * published rows would only let `sync()` overwrite the freshly published order with a stale\n * one — silently reverting a reorder made in the draft. The inverse-side order still needs the\n * old-published capture to be restored, so this only suppresses the owning-side capture.\n */\n isOwningSide: boolean;\n oldVersions: LoadContext['oldVersions'];\n newVersions: LoadContext['newVersions'];\n }\n): Promise => {\n const {\n joinTable,\n publishedCol,\n relatedCol,\n relatedUid,\n relatedHasDraftAndPublish,\n schemaUid,\n isOwningSide,\n oldVersions,\n newVersions,\n } = opts;\n\n const batches: RelationEntry[] = [];\n const { name: table } = joinTable;\n\n // Skip the old-published capture for the owning side: those rows are recreated in draft order\n // by `entries.publish`, so restoring their order from the old published version is at best a\n // no-op and at worst reverts a draft reorder. The draftsOnly capture below is still needed\n // (e.g. when a related entry is published after this one) and is not affected by this guard.\n const oldIds = isOwningSide ? [] : oldVersions.map((e) => e.id);\n if (oldIds.length > 0) {\n const existing = await strapi.db\n .getConnection()\n .select('*')\n .from(table)\n .whereIn(publishedCol, oldIds)\n .transacting(trx);\n if (existing.length > 0) {\n batches.push({\n joinTable,\n relations: existing,\n entityColumn: publishedCol,\n relatedColumn: relatedCol,\n });\n }\n }\n\n if (!strapi.contentTypes[schemaUid]) {\n return batches;\n }\n\n const oldLocales = new Set(oldVersions.map((e) => e.locale));\n const draftsOnly = newVersions.filter((v) => !oldLocales.has(v.locale));\n if (draftsOnly.length === 0) {\n return batches;\n }\n\n const draftIds = draftsOnly.map((e) => e.id);\n const draftRows = await strapi.db\n .getConnection()\n .select('*')\n .from(table)\n .whereIn(publishedCol, draftIds)\n .transacting(trx);\n\n if (draftRows.length === 0) {\n return batches;\n }\n\n let relations = draftRows;\n if (relatedHasDraftAndPublish) {\n const meta = strapi.db.metadata.get(relatedUid);\n const relatedIds = draftRows.map((r: any) => r[relatedCol]);\n const map = await draftToPublishedMap(trx, meta.tableName, relatedIds);\n relations = remapRelatedIds(draftRows, relatedCol, map);\n }\n\n batches.push({ joinTable, relations, entityColumn: publishedCol, relatedColumn: relatedCol });\n return batches;\n};\n\n/**\n * Loads all bidirectional relations that need to be synchronized when content entries change state\n * (e.g., during publish/unpublish operations).\n *\n * In Strapi, bidirectional relations allow maintaining order from both sides of the relation.\n * When an entry is published, the following occurs:\n *\n * 1. The old published entry is deleted\n * 2. A new entry is created with all its relations\n *\n * This process affects relation ordering in the following way:\n *\n * Initial state (Entry A related to X, Y, Z):\n * ```\n * Entry A (draft) Entry A (published)\n * │ │\n * ├──(1)→ X ├──(1)→ X\n * ├──(2)→ Y ├──(2)→ Y\n * └──(3)→ Z └──(3)→ Z\n *\n * X's perspective: Y's perspective: Z's perspective:\n * └──(2)→ Entry A └──(1)→ Entry A └──(3)→ Entry A\n * ```\n *\n * After publishing Entry A (without relation order sync):\n * ```\n * Entry A (draft) Entry A (new published)\n * │ │\n * ├──(1)→ X ├──(1)→ X\n * ├──(2)→ Y ├──(2)→ Y\n * └──(3)→ Z └──(3)→ Z\n *\n * X's perspective: Y's perspective: Z's perspective:\n * └──(3)→ Entry A └──(3)→ Entry A └──(3)→ Entry A\n * (all relations appear last in order)\n * ```\n *\n * This module preserves the original ordering from both perspectives by:\n * 1. Capturing the relation order before the entry state changes\n * 2. Restoring this order after the new relations are created\n *\n * @param uid - The unique identifier of the content type being processed\n * @param context - Object containing arrays of old and new entry versions\n * @returns Array of objects containing join table metadata and relations to be updated\n */\nconst load = async (uid: UID.ContentType, { oldVersions, newVersions }: LoadContext) => {\n const relationsToUpdate: RelationEntry[] = [];\n\n await strapi.db.transaction(async ({ trx }) => {\n const models = [\n ...(Object.values(strapi.contentTypes) as Schema.ContentType[]),\n ...Object.values(strapi.components),\n ];\n\n for (const model of models) {\n const dbModel = strapi.db.metadata.get(model.uid);\n\n for (const attribute of Object.values(dbModel.attributes) as Record[]) {\n const joinTable = attribute.joinTable;\n\n if (attribute.type !== 'relation' || !joinTable) {\n continue;\n }\n\n if (!(attribute.inversedBy || attribute.mappedBy)) {\n continue;\n }\n\n // Owning side: e.g. Author.articles when publishing an Author.\n const isOwningSide =\n !!attribute.inversedBy &&\n model.uid === uid &&\n attribute.relation === 'manyToMany' &&\n model.uid !== attribute.target;\n\n // Inverse side: e.g. Article.authors when publishing an Article.\n const isInverseSide = attribute.target === uid && model.uid !== uid;\n\n if (!isOwningSide && !isInverseSide) {\n continue;\n }\n\n // Direction determines which join column belongs to the entity being published\n const publishedCol = isOwningSide\n ? joinTable.joinColumn.name\n : joinTable.inverseJoinColumn.name;\n const relatedCol = isOwningSide\n ? joinTable.inverseJoinColumn.name\n : joinTable.joinColumn.name;\n\n const relatedUid = (isOwningSide ? attribute.target : model.uid) as UID.ContentType;\n\n const batches = await captureJoinBatches(trx, {\n joinTable,\n publishedCol,\n relatedCol,\n relatedUid,\n relatedHasDraftAndPublish: isOwningSide\n ? !!strapi.contentTypes[relatedUid]?.options?.draftAndPublish\n : !!model.options?.draftAndPublish,\n schemaUid: model.uid as UID.ContentType,\n isOwningSide,\n oldVersions,\n newVersions,\n });\n relationsToUpdate.push(...batches);\n }\n }\n });\n\n return relationsToUpdate;\n};\n\n/**\n * Synchronizes the order of bidirectional relations after content entries have changed state.\n *\n * When entries change state (e.g., draft → published), their IDs change and all relations are recreated.\n * While the order of relations from the entry's perspective is maintained (as they're created in order),\n * the inverse relations (from related entries' perspective) would all appear last in order since they're new.\n *\n * Example:\n * ```\n * Before publish:\n * Article(id:1) →(order:1)→ Category(id:5)\n * Category(id:5) →(order:3)→ Article(id:1)\n *\n * After publish (without sync):\n * Article(id:2) →(order:1)→ Category(id:5) [order preserved]\n * Category(id:5) →(order:99)→ Article(id:2) [order lost - appears last]\n *\n * After sync:\n * Article(id:2) →(order:1)→ Category(id:5) [order preserved]\n * Category(id:5) →(order:3)→ Article(id:2) [order restored]\n * ```\n *\n * @param oldEntries - Array of previous entry versions with their IDs and locales\n * @param newEntries - Array of new entry versions with their IDs and locales\n * @param existingRelations - Array of join table data containing the relations to be updated\n */\nconst sync = async (\n oldEntries: { id: string; locale: string }[],\n newEntries: { id: string; locale: string }[],\n existingRelations: RelationEntry[]\n) => {\n const newEntriesByLocale = keyBy('locale', newEntries);\n\n const entryIdMapping = oldEntries.reduce(\n (acc, oldEntry) => {\n const newEntry = newEntriesByLocale[oldEntry.locale];\n if (!newEntry) {\n return acc;\n }\n acc[oldEntry.id] = newEntry.id;\n return acc;\n },\n {} as Record\n );\n\n const republishedEntryIds = new Set(newEntries.map((e) => String(e.id)));\n const isRepublishedEntry = (id: string | number) => republishedEntryIds.has(String(id));\n\n await strapi.db.transaction(async ({ trx }) => {\n for (const {\n joinTable,\n relations,\n entityColumn: sourceColumn,\n relatedColumn: targetColumn,\n } of existingRelations) {\n const orderColumn = joinTable.orderColumnName;\n\n // Failsafe in case those don't exist\n if (!sourceColumn || !targetColumn || !orderColumn) {\n continue;\n }\n\n const mappedRelations = relations\n .map((relation) => ({\n relation,\n oldSourceId: relation[sourceColumn] as string,\n targetId: relation[targetColumn] as string,\n originalOrder: relation[orderColumn],\n newSourceId: entryIdMapping[relation[sourceColumn] as string],\n }))\n .filter((r): r is typeof r & { newSourceId: string } => Boolean(r.newSourceId));\n\n if (!mappedRelations.length) continue;\n\n const newSourceIds = mappedRelations.map((r) => r.newSourceId);\n\n // Batch UPDATE: set each row's order in a single statement using CASE\n const caseFragments = mappedRelations.map(() => `WHEN ?? = ? AND ?? = ? THEN ?`);\n const caseBindings = mappedRelations.flatMap(({ newSourceId, targetId, originalOrder }) => [\n sourceColumn,\n newSourceId,\n targetColumn,\n targetId,\n originalOrder,\n ]);\n\n await trx(joinTable.name)\n .whereIn(sourceColumn, newSourceIds)\n .update({\n [orderColumn]: trx.raw(`CASE ${caseFragments.join(' ')} ELSE ?? END`, [\n ...caseBindings,\n orderColumn,\n ]),\n });\n\n // Batch SELECT: find which rows exist so we know what to insert\n const existingRows = await trx(joinTable.name)\n .whereIn(sourceColumn, newSourceIds)\n .select(sourceColumn, targetColumn);\n\n const existingSet = new Set(\n existingRows.map((r: Record) => `${r[sourceColumn]}:${r[targetColumn]}`)\n );\n\n // Batch INSERT: insert cascade-deleted rows that aren't from republished sources\n const toInsert = mappedRelations\n .filter(\n ({ newSourceId, targetId }) =>\n !existingSet.has(`${newSourceId}:${targetId}`) && !isRepublishedEntry(newSourceId)\n )\n .map(({ relation, newSourceId, originalOrder }) => ({\n ...omit(strapi.db.metadata.identifiers.ID_COLUMN, relation),\n [sourceColumn]: newSourceId,\n [orderColumn]: originalOrder,\n }));\n\n if (toInsert.length) {\n const batchSize = strapi.db.dialect.getBatchInsertSize();\n await trx.batchInsert(joinTable.name, toInsert, batchSize);\n }\n }\n });\n};\n\nexport { load, sync };\n"],"names":["draftToPublishedMap","trx","tableName","rowIds","uniqueIds","Set","length","Map","draftEntries","strapi","db","getConnection","select","from","whereIn","transacting","pubEntries","whereNotNull","map","e","document_id","pubByDocLocale","locale","id","d","pubId","get","set","String","remapRelatedIds","rows","relatedCol","idMap","row","next","captureJoinBatches","opts","joinTable","publishedCol","relatedUid","relatedHasDraftAndPublish","schemaUid","isOwningSide","oldVersions","newVersions","batches","name","table","oldIds","existing","push","relations","entityColumn","relatedColumn","contentTypes","oldLocales","draftsOnly","filter","v","has","draftIds","draftRows","meta","metadata","relatedIds","r","load","uid","relationsToUpdate","transaction","models","Object","values","components","model","dbModel","attribute","attributes","type","inversedBy","mappedBy","relation","target","isInverseSide","joinColumn","inverseJoinColumn","options","draftAndPublish","sync","oldEntries","newEntries","existingRelations","newEntriesByLocale","keyBy","entryIdMapping","reduce","acc","oldEntry","newEntry","republishedEntryIds","isRepublishedEntry","sourceColumn","targetColumn","orderColumn","orderColumnName","mappedRelations","oldSourceId","targetId","originalOrder","newSourceId","Boolean","newSourceIds","caseFragments","caseBindings","flatMap","update","raw","join","existingRows","existingSet","toInsert","omit","identifiers","ID_COLUMN","batchSize","dialect","getBatchInsertSize","batchInsert"],"mappings":"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"}