Repository: strapi/strapi
File: packages/core/core/src/services/document-service/utils/unidirectional-relations.ts (TypeScript)

Code before:
  relations: Record<string, any>[],
  componentSchema: Schema.Component,
  trx: any
): Promise<Record<string, any>[]> => {
  // Exit if no relations to filter
  if (relations.length === 0) {
    return relations;
  }

  const componentParents = getParentSchemasForComponent(componentSchema);

  // Exit if no draft & publish parent types exist
  if (componentParents.length === 0) {
    return relations;
  }

  const relationsToPropagate = [];
  for (const relation of relations) {
    if (
      await shouldPropagateRelationToNewVersion(relation, componentSchema, componentParents, trx)
    ) {
      relationsToPropagate.push(relation);
    }
  }

  return relationsToPropagate;
};

/**
 * Loads lingering relations that need to be updated when overriding a published or draft entry.
 * This is necessary because the relations are uni-directional and the target entry is not aware of the source entry.
 * This is not the case for bi-directional relations, where the target entry is also linked to the source entry.
 */
const load = async (
  uid: UID.ContentType,
  { oldVersions, newVersions }: LoadContext
): Promise<RelationUpdate[]> => {
  const updates: RelationUpdate[] = [];

  // Iterate all components and content types to find relations that need to be updated
  await strapi.db.transaction(async ({ trx }) => {
    const contentTypes = Object.values(strapi.contentTypes) as Schema.ContentType[];
    const components = Object.values(strapi.components) as Schema.Component[];

    for (const model of [...contentTypes, ...components]) {
      const dbModel = strapi.db.metadata.get(model.uid);

      for (const attribute of Object.values(dbModel.attributes) as any) {
        /**
         * Only consider unidirectional relations
         */

Review comment (suggestion):

```suggestion
          // This is the step where we query the join table based on the id of the document
```

Code after:
        const oldVersionsRelations = await strapi.db
          .getConnection()
          .select('*')
          .from(joinTable.name)
          .whereIn(targetColumnName, ids)
          .transacting(trx);

        if (oldVersionsRelations.length > 0) {
          updates.push({ joinTable, relations: oldVersionsRelations });
        }

        /**
         * if publishing
         *  if published version exists
         *    updated published versions links
         *  else
         *    create link to newly published version
         *
         * if discarding
         *    if published version link exists & not draft version link
         *       create link to new draft version
         */
        if (!model.options?.draftAndPublish) {
          const ids = newVersions.map((entry) => entry.id);

          // This is the step were we query the join table based on the id of the document
          const newVersionsRelations = await strapi.db
            .getConnection()
            .select('*')
            .from(joinTable.name)
            .whereIn(targetColumnName, ids)
            .transacting(trx);

          let versionRelations = newVersionsRelations;
          if (options.shouldPropagateRelation) {
            const relationsToPropagate = [];
            for (const relation of newVersionsRelations) {
              if (await options.shouldPropagateRelation(relation, model, trx)) {
                relationsToPropagate.push(relation);
              }
            }
            versionRelations = relationsToPropagate;
          }

          if (versionRelations.length > 0) {
            // when publishing a draft that doesn't have a published version yet,
            // copy the links to the draft over to the published version
            // when discarding a published version, if no drafts exists
            const discardToAdd = versionRelations
              .filter((relation) => {
                const matchingOldVersion = oldVersionsRelations.find((oldRelation) => {