@strapi/data-transfer 5.51.1 → 5.52.0

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 (56) hide show
  1. package/dist/file/providers/source/index.js +3 -3
  2. package/dist/file/providers/source/index.js.map +1 -1
  3. package/dist/file/providers/source/index.mjs +3 -3
  4. package/dist/file/providers/source/index.mjs.map +1 -1
  5. package/dist/strapi/providers/local-destination/index.js +1 -1
  6. package/dist/strapi/providers/local-destination/index.js.map +1 -1
  7. package/dist/strapi/providers/local-destination/index.mjs +1 -1
  8. package/dist/strapi/providers/local-destination/index.mjs.map +1 -1
  9. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js +1 -1
  10. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js.map +1 -1
  11. package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs +1 -1
  12. package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs.map +1 -1
  13. package/dist/strapi/providers/local-destination/strategies/restore/index.js +1 -0
  14. package/dist/strapi/providers/local-destination/strategies/restore/index.js.map +1 -1
  15. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs +1 -0
  16. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs.map +1 -1
  17. package/dist/strapi/providers/local-destination/strategies/restore/links.d.ts +1 -0
  18. package/dist/strapi/providers/local-destination/strategies/restore/links.d.ts.map +1 -1
  19. package/dist/strapi/providers/local-destination/strategies/restore/links.js +57 -4
  20. package/dist/strapi/providers/local-destination/strategies/restore/links.js.map +1 -1
  21. package/dist/strapi/providers/local-destination/strategies/restore/links.mjs +57 -5
  22. package/dist/strapi/providers/local-destination/strategies/restore/links.mjs.map +1 -1
  23. package/dist/strapi/providers/local-source/index.d.ts.map +1 -1
  24. package/dist/strapi/providers/local-source/index.js +6 -1
  25. package/dist/strapi/providers/local-source/index.js.map +1 -1
  26. package/dist/strapi/providers/local-source/index.mjs +6 -1
  27. package/dist/strapi/providers/local-source/index.mjs.map +1 -1
  28. package/dist/strapi/providers/local-source/links.d.ts +4 -1
  29. package/dist/strapi/providers/local-source/links.d.ts.map +1 -1
  30. package/dist/strapi/providers/local-source/links.js +16 -2
  31. package/dist/strapi/providers/local-source/links.js.map +1 -1
  32. package/dist/strapi/providers/local-source/links.mjs +16 -3
  33. package/dist/strapi/providers/local-source/links.mjs.map +1 -1
  34. package/dist/strapi/queries/link.d.ts +4 -1
  35. package/dist/strapi/queries/link.d.ts.map +1 -1
  36. package/dist/strapi/queries/link.js +271 -64
  37. package/dist/strapi/queries/link.js.map +1 -1
  38. package/dist/strapi/queries/link.mjs +271 -64
  39. package/dist/strapi/queries/link.mjs.map +1 -1
  40. package/dist/strapi/remote/handlers/utils.js +1 -1
  41. package/dist/strapi/remote/handlers/utils.js.map +1 -1
  42. package/dist/strapi/remote/handlers/utils.mjs +1 -1
  43. package/dist/strapi/remote/handlers/utils.mjs.map +1 -1
  44. package/dist/utils/capped-warnings.d.ts +9 -0
  45. package/dist/utils/capped-warnings.d.ts.map +1 -0
  46. package/dist/utils/capped-warnings.js +28 -0
  47. package/dist/utils/capped-warnings.js.map +1 -0
  48. package/dist/utils/capped-warnings.mjs +25 -0
  49. package/dist/utils/capped-warnings.mjs.map +1 -0
  50. package/dist/utils/index.d.ts +1 -0
  51. package/dist/utils/index.d.ts.map +1 -1
  52. package/dist/utils/index.js +3 -0
  53. package/dist/utils/index.js.map +1 -1
  54. package/dist/utils/index.mjs +1 -0
  55. package/dist/utils/index.mjs.map +1 -1
  56. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","sources":["../../../src/strapi/queries/link.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport { clone, isNil } from 'lodash/fp';\nimport type { Core } from '@strapi/types';\n\nimport { ILink } from '../../types';\n\n// TODO: Remove any types when we'll have types for DB metadata\n\nexport const createLinkQuery = (strapi: Core.Strapi, trx?: Knex.Transaction) => {\n const query = () => {\n const { connection } = strapi.db;\n\n // TODO: Export utils from database and use the addSchema that is already written\n const addSchema = (tableName: string) => {\n const schemaName = connection.client.connectionSettings.schema;\n return schemaName ? `${schemaName}.${tableName}` : tableName;\n };\n\n async function* generateAllForAttribute(uid: string, fieldName: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n if (!(fieldName in attributes)) {\n throw new Error(`${fieldName} is not a valid relational attribute name`);\n }\n\n const attribute = attributes[fieldName];\n\n const kind = getLinkKind(attribute, uid);\n const { relation, target } = attribute;\n\n // The relation is stored in the same table\n // TODO: handle manyToOne joinColumn\n if (attribute.joinColumn) {\n const joinColumnName: string = attribute.joinColumn.name;\n\n const qb = connection\n .queryBuilder()\n .select('id', joinColumnName)\n .from(addSchema(metadata.tableName));\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[joinColumnName];\n\n if (ref !== null) {\n yield {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: target, ref },\n };\n }\n }\n }\n\n // The relation uses a join table\n if (attribute.joinTable) {\n const {\n name,\n joinColumn,\n inverseJoinColumn,\n orderColumnName,\n morphColumn,\n inverseOrderColumnName,\n } = attribute.joinTable;\n\n const qb = connection.queryBuilder().from(addSchema(name));\n\n type Columns = {\n left: { ref: string | null; order?: string };\n right: { ref: string | null; order?: string; type?: string; field?: string };\n };\n\n const columns: Columns = {\n left: { ref: null },\n right: { ref: null },\n };\n\n const left: Partial<ILink['left']> = { type: uid, field: fieldName };\n const right: Partial<ILink['right']> = {};\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n right.type = attribute.target;\n right.field = attribute.inversedBy;\n\n columns.left.ref = joinColumn.name;\n columns.right.ref = inverseJoinColumn.name;\n\n if (orderColumnName) {\n columns.left.order = orderColumnName as string;\n }\n\n if (inverseOrderColumnName) {\n columns.right.order = inverseOrderColumnName as string;\n }\n }\n\n if (kind === 'relation.morph') {\n columns.left.ref = joinColumn.name;\n\n columns.right.ref = morphColumn.idColumn.name;\n columns.right.type = morphColumn.typeColumn.name;\n columns.right.field = 'field';\n columns.right.order = 'order';\n }\n\n const validColumns = [\n // Left\n columns.left.ref,\n columns.left.order,\n // Right\n columns.right.ref,\n columns.right.type,\n columns.right.field,\n columns.right.order,\n ].filter((column: string | null | undefined) => !isNil(column));\n\n qb.select(validColumns);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n if (columns.left.ref) {\n left.ref = entry[columns.left.ref];\n }\n\n if (columns.right.ref) {\n right.ref = entry[columns.right.ref];\n }\n\n if (columns.left.order) {\n left.pos = entry[columns.left.order as string];\n }\n\n if (columns.right.order) {\n right.pos = entry[columns.right.order as string];\n }\n\n if (columns.right.type) {\n right.type = entry[columns.right.type as string];\n }\n\n if (columns.right.field) {\n right.field = entry[columns.right.field as string];\n }\n\n const link: ILink = {\n kind,\n relation,\n left: clone(left as ILink['left']),\n right: clone(right as ILink['right']),\n };\n\n yield link;\n }\n }\n\n if (attribute.morphColumn) {\n const { typeColumn, idColumn } = attribute.morphColumn;\n\n const qb = connection\n .queryBuilder()\n .select('id', typeColumn.name, idColumn.name)\n .from(addSchema(metadata.tableName))\n .whereNotNull(typeColumn.name)\n .whereNotNull(idColumn.name);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[idColumn.name];\n\n yield {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: entry[typeColumn.name], ref },\n };\n }\n }\n }\n\n async function* generateAll(uid: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n for (const fieldName of Object.keys(attributes)) {\n for await (const link of generateAllForAttribute(uid, fieldName)) {\n yield link;\n }\n }\n }\n\n const insert = async (link: ILink) => {\n const { kind, left, right } = link;\n\n const metadata = strapi.db.metadata.get(left.type);\n const attribute = metadata.attributes[left.field];\n\n const payload = {};\n\n /**\n * This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages\n * and a user is importing EE data into a CE project.\n */\n if (!attribute) {\n return;\n }\n\n if (attribute.type !== 'relation') {\n throw new Error(`Attribute ${left.field} is not a relation`);\n }\n\n if ('joinColumn' in attribute && attribute.joinColumn) {\n const joinColumnName = attribute.joinColumn.name;\n\n // Note: this addSchema may not be necessary, but is added for safety\n const qb = connection(addSchema(metadata.tableName))\n .where('id', left.ref)\n .update({ [joinColumnName]: right.ref });\n if (trx) {\n qb.transacting(trx);\n }\n await qb;\n }\n\n if ('joinTable' in attribute && attribute.joinTable) {\n const { joinTable } = attribute;\n\n if (joinTable.joinColumn) {\n Object.assign(payload, { [joinTable.joinColumn.name]: left.ref });\n }\n\n const assignInverseColumn = () => {\n if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {\n Object.assign(payload, {\n [joinTable.inverseJoinColumn.name]: right.ref,\n });\n }\n };\n\n const assignOrderColumns = () => {\n if ('orderColumnName' in joinTable && joinTable.orderColumnName) {\n Object.assign(payload, { [joinTable.orderColumnName]: left.pos ?? null });\n }\n\n if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {\n Object.assign(payload, { [joinTable.inverseOrderColumnName]: right.pos ?? null });\n }\n };\n\n const assignMorphColumns = () => {\n if ('morphColumn' in joinTable && joinTable.morphColumn) {\n const { idColumn, typeColumn } = joinTable.morphColumn ?? {};\n\n if (idColumn) {\n Object.assign(payload, { [idColumn.name]: right.ref });\n }\n\n if (typeColumn) {\n Object.assign(payload, { [typeColumn.name]: right.type });\n }\n\n Object.assign(payload, { order: right.pos ?? null, field: right.field ?? null });\n }\n };\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n assignInverseColumn();\n }\n\n if (kind === 'relation.morph') {\n assignMorphColumns();\n }\n\n assignOrderColumns();\n const qb = connection.insert(payload).into(addSchema(joinTable.name));\n if (trx) {\n await qb.transacting(trx);\n }\n }\n\n if ('morphColumn' in attribute && attribute.morphColumn) {\n const { morphColumn } = attribute;\n\n const qb = connection(addSchema(metadata.tableName))\n .where('id', left.ref)\n .update({\n [morphColumn.idColumn.name]: right.ref,\n [morphColumn.typeColumn.name]: right.type,\n });\n\n if (trx) {\n qb.transacting(trx);\n }\n\n await qb;\n }\n };\n\n return { generateAll, generateAllForAttribute, insert };\n };\n\n return query;\n};\n\nexport const filterValidRelationalAttributes = (attributes: Record<string, any>) => {\n const isOwner = (attribute: any) => {\n return attribute.owner || (!attribute.mappedBy && !attribute.morphBy);\n };\n\n const isComponentLike = (attribute: any) => attribute.joinTable?.name.endsWith('_cmps');\n\n return Object.entries(attributes)\n .filter(([, attribute]) => {\n return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);\n })\n .reduce<Record<string, any>>((acc, [key, attribute]) => ({ ...acc, [key]: attribute }), {});\n};\n\nconst getLinkKind = (attribute: any, uid: string): ILink['kind'] => {\n if (attribute.relation.startsWith('morph')) {\n return 'relation.morph';\n }\n\n if (attribute.target === uid) {\n return 'relation.circular';\n }\n\n return 'relation.basic';\n};\n"],"names":["createLinkQuery","strapi","trx","query","connection","db","addSchema","tableName","schemaName","client","connectionSettings","schema","generateAllForAttribute","uid","fieldName","metadata","get","Error","attributes","filterValidRelationalAttributes","attribute","kind","getLinkKind","relation","target","joinColumn","joinColumnName","name","qb","queryBuilder","select","from","transacting","entries","entry","ref","left","type","id","field","right","joinTable","inverseJoinColumn","orderColumnName","morphColumn","inverseOrderColumnName","columns","inversedBy","order","idColumn","typeColumn","validColumns","filter","column","isNil","pos","link","clone","whereNotNull","generateAll","Object","keys","insert","payload","where","update","assign","assignInverseColumn","assignOrderColumns","assignMorphColumns","into","isOwner","owner","mappedBy","morphBy","isComponentLike","endsWith","reduce","acc","key","startsWith"],"mappings":"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"}
1
+ {"version":3,"file":"link.js","sources":["../../../src/strapi/queries/link.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport { clone, isNil } from 'lodash/fp';\nimport type { Core, UID } from '@strapi/types';\n\nimport { ILink } from '../../types';\n\n// TODO: Remove any types when we'll have types for DB metadata\n\nconst TARGET_EXISTS_ALIAS = '__target_exists';\nconst LEFT_EXISTS_ALIAS = '__left_exists';\nconst RIGHT_EXISTS_ALIAS = '__right_exists';\nconst EXISTENCE_CHECK_CHUNK_SIZE = 1000;\n\nconst getMetadataTableName = (strapi: Core.Strapi, uid: string) => {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n return metadata.tableName;\n};\n\nconst refKey = (ref: number | string) => `${typeof ref}:${ref}`;\n\n/**\n * Batch-load which refs exist for a content type. Handles numeric `id` refs and\n * string `documentId` refs separately, chunked to keep `IN (...)` lists bounded.\n */\nconst loadExistingRefs = async (\n strapi: Core.Strapi,\n uid: string,\n refs: Array<number | string>\n): Promise<Set<string>> => {\n const existing = new Set<string>();\n\n // Stale morph type UIDs (removed components/CTs) have no metadata — treat as orphaned.\n if (!strapi.db.metadata.has(uid)) {\n return existing;\n }\n\n const uniqueRefs = [...new Set(refs)];\n const numericIds = uniqueRefs.filter((ref): ref is number => typeof ref === 'number');\n const documentIds = uniqueRefs.filter((ref): ref is string => typeof ref === 'string');\n\n for (let i = 0; i < numericIds.length; i += EXISTENCE_CHECK_CHUNK_SIZE) {\n const chunk = numericIds.slice(i, i + EXISTENCE_CHECK_CHUNK_SIZE);\n const rows = await strapi.db.query(uid as UID.Schema).findMany({\n select: ['id'],\n where: { id: { $in: chunk } },\n });\n\n for (const row of rows) {\n existing.add(refKey(row.id as number));\n }\n }\n\n for (let i = 0; i < documentIds.length; i += EXISTENCE_CHECK_CHUNK_SIZE) {\n const chunk = documentIds.slice(i, i + EXISTENCE_CHECK_CHUNK_SIZE);\n const rows = await strapi.db.query(uid as UID.Schema).findMany({\n select: ['id', 'documentId'],\n where: { documentId: { $in: chunk } },\n });\n\n for (const row of rows) {\n if (row.documentId != null) {\n existing.add(refKey(row.documentId as string));\n }\n }\n }\n\n return existing;\n};\n\n/**\n * Filter morph links in batches. The morph owner (`left`) is not checked:\n * morphColumn rows come from the owner table itself, and morph join-table\n * owners are FK-backed. Only dynamic morph targets (`right`) need existence\n * checks, and those have no DB-level FK.\n */\nconst filterMorphLinksByTargetExistence = async function* filterMorphLinksByTargetExistence(\n strapi: Core.Strapi,\n links: ILink[],\n onOrphanedLink?: (link: ILink) => void\n): AsyncGenerator<ILink> {\n const refsByType = new Map<string, Array<number | string>>();\n\n for (const link of links) {\n const { type, ref } = link.right;\n\n if (ref == null || type == null) {\n onOrphanedLink?.(link);\n } else {\n const bucket = refsByType.get(type) ?? [];\n bucket.push(ref);\n refsByType.set(type, bucket);\n }\n }\n\n const existingByType = new Map<string, Set<string>>();\n\n for (const [type, refs] of refsByType) {\n existingByType.set(type, await loadExistingRefs(strapi, type, refs));\n }\n\n for (const link of links) {\n const { type, ref } = link.right;\n\n if (ref == null || type == null) {\n // already reported above\n } else if (existingByType.get(type)?.has(refKey(ref))) {\n yield link;\n } else {\n onOrphanedLink?.(link);\n }\n }\n};\n\nexport interface LinkQueryOptions {\n onOrphanedLink?: (link: ILink) => void;\n}\n\nconst aliasColumn = (tableAlias: string, column: string) => `${tableAlias}.${column}`;\n\nconst selectAliasedColumns = (tableAlias: string, columns: string[]) =>\n columns.map((column) => ({ [column]: aliasColumn(tableAlias, column) }));\n\nexport const createLinkQuery = (\n strapi: Core.Strapi,\n trx?: Knex.Transaction,\n options?: LinkQueryOptions\n) => {\n const { onOrphanedLink } = options ?? {};\n\n const query = () => {\n const { connection } = strapi.db;\n\n // TODO: Export utils from database and use the addSchema that is already written\n const addSchema = (tableName: string) => {\n const schemaName = connection.client.connectionSettings.schema;\n return schemaName ? `${schemaName}.${tableName}` : tableName;\n };\n\n async function* generateAllForAttribute(uid: string, fieldName: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n if (!(fieldName in attributes)) {\n throw new Error(`${fieldName} is not a valid relational attribute name`);\n }\n\n const attribute = attributes[fieldName];\n\n const kind = getLinkKind(attribute, uid);\n const { relation, target } = attribute;\n\n // The relation is stored in the same table\n // TODO: handle manyToOne joinColumn\n if (attribute.joinColumn) {\n const joinColumnName: string = attribute.joinColumn.name;\n const referencedColumn = attribute.joinColumn.referencedColumn ?? 'id';\n const ownerAlias = 'owner';\n const targetAlias = 'target';\n const ownerTable = addSchema(metadata.tableName);\n const targetTable = addSchema(getMetadataTableName(strapi, target));\n\n // Use EXISTS (not JOIN): joining on non-unique referencedColumn (e.g. i18n\n // document_id) multiplies owner rows by matching target locales.\n const targetExistsSubquery = () =>\n connection\n .queryBuilder()\n .select(connection.raw('1'))\n .from({ [targetAlias]: targetTable })\n .whereRaw('??.?? = ??.??', [targetAlias, referencedColumn, ownerAlias, joinColumnName]);\n\n const qb = connection\n .queryBuilder()\n .select(\n `${ownerAlias}.id`,\n `${ownerAlias}.${joinColumnName} as ${joinColumnName}`,\n ...(onOrphanedLink\n ? // Knex wraps QueryBuilder bindings in parentheses, so `exists (?)`\n // becomes `exists ((select ...))`, which SQLite rejects in a SELECT\n // list. Wrap the EXISTS expression so the compiled SQL is valid.\n [connection.raw('(exists ?) as ??', [targetExistsSubquery(), TARGET_EXISTS_ALIAS])]\n : [])\n )\n .from({ [ownerAlias]: ownerTable })\n .whereNotNull(aliasColumn(ownerAlias, joinColumnName));\n\n if (!onOrphanedLink) {\n qb.whereExists(targetExistsSubquery());\n }\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[joinColumnName];\n const link: ILink = {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: target, ref },\n };\n\n // EXISTS yields 0/1 (or boolean); treat falsy as orphaned.\n if (onOrphanedLink && !entry[TARGET_EXISTS_ALIAS]) {\n onOrphanedLink(link);\n } else {\n yield link;\n }\n }\n }\n\n // The relation uses a join table\n if (attribute.joinTable) {\n const {\n name,\n joinColumn,\n inverseJoinColumn,\n orderColumnName,\n morphColumn,\n inverseOrderColumnName,\n } = attribute.joinTable;\n\n type Columns = {\n left: { ref: string | null; order?: string };\n right: { ref: string | null; order?: string; type?: string; field?: string };\n };\n\n const columns: Columns = {\n left: { ref: null },\n right: { ref: null },\n };\n\n const left: Partial<ILink['left']> = { type: uid, field: fieldName };\n const right: Partial<ILink['right']> = {};\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n right.type = attribute.target;\n right.field = attribute.inversedBy;\n\n columns.left.ref = joinColumn.name;\n columns.right.ref = inverseJoinColumn.name;\n\n if (orderColumnName) {\n columns.left.order = orderColumnName as string;\n }\n\n if (inverseOrderColumnName) {\n columns.right.order = inverseOrderColumnName as string;\n }\n\n const joinAlias = 'join';\n const leftAlias = 'left';\n const rightAlias = 'right';\n const joinTable = addSchema(name);\n const leftTable = addSchema(metadata.tableName);\n const rightTable = addSchema(getMetadataTableName(strapi, attribute.target));\n const leftReferencedColumn = aliasColumn(leftAlias, joinColumn.referencedColumn ?? 'id');\n const rightReferencedColumn = aliasColumn(\n rightAlias,\n inverseJoinColumn.referencedColumn ?? 'id'\n );\n\n const validColumns = [\n columns.left.ref,\n columns.left.order,\n columns.right.ref,\n columns.right.order,\n ].filter((column: string | null | undefined) => !isNil(column)) as string[];\n\n const buildJoinTableLink = (entry: Record<string, unknown>): ILink => {\n const linkLeft: Partial<ILink['left']> = { type: uid, field: fieldName };\n const linkRight: Partial<ILink['right']> = {\n type: attribute.target,\n field: attribute.inversedBy,\n };\n\n if (columns.left.ref) {\n linkLeft.ref = entry[columns.left.ref] as number;\n }\n\n if (columns.right.ref) {\n linkRight.ref = entry[columns.right.ref] as number;\n }\n\n if (columns.left.order) {\n linkLeft.pos = entry[columns.left.order] as number;\n }\n\n if (columns.right.order) {\n linkRight.pos = entry[columns.right.order] as number;\n }\n\n return {\n kind,\n relation,\n left: clone(linkLeft as ILink['left']),\n right: clone(linkRight as ILink['right']),\n };\n };\n\n const selectColumns = [\n ...selectAliasedColumns(joinAlias, validColumns),\n ...(onOrphanedLink\n ? [\n { [LEFT_EXISTS_ALIAS]: leftReferencedColumn },\n { [RIGHT_EXISTS_ALIAS]: rightReferencedColumn },\n ]\n : []),\n ];\n\n const joinQb = connection\n .queryBuilder()\n .select(selectColumns)\n .from({ [joinAlias]: joinTable });\n\n if (onOrphanedLink) {\n joinQb\n .leftJoin(\n { [leftAlias]: leftTable },\n aliasColumn(joinAlias, joinColumn.name),\n leftReferencedColumn\n )\n .leftJoin(\n { [rightAlias]: rightTable },\n aliasColumn(joinAlias, inverseJoinColumn.name),\n rightReferencedColumn\n );\n } else {\n joinQb\n .innerJoin(\n { [leftAlias]: leftTable },\n aliasColumn(joinAlias, joinColumn.name),\n leftReferencedColumn\n )\n .innerJoin(\n { [rightAlias]: rightTable },\n aliasColumn(joinAlias, inverseJoinColumn.name),\n rightReferencedColumn\n );\n }\n\n if (trx) {\n joinQb.transacting(trx);\n }\n\n const entries = await joinQb;\n\n for (const entry of entries) {\n const link = buildJoinTableLink(entry);\n\n if (\n onOrphanedLink &&\n (entry[LEFT_EXISTS_ALIAS] == null || entry[RIGHT_EXISTS_ALIAS] == null)\n ) {\n onOrphanedLink(link);\n } else {\n yield link;\n }\n }\n }\n\n if (kind === 'relation.morph') {\n const qb = connection.queryBuilder().from(addSchema(name));\n\n columns.left.ref = joinColumn.name;\n\n columns.right.ref = morphColumn.idColumn.name;\n columns.right.type = morphColumn.typeColumn.name;\n columns.right.field = 'field';\n columns.right.order = 'order';\n\n const validColumns = [\n columns.left.ref,\n columns.left.order,\n columns.right.ref,\n columns.right.type,\n columns.right.field,\n columns.right.order,\n ].filter((column: string | null | undefined) => !isNil(column));\n\n qb.select(validColumns);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n const morphLinks: ILink[] = [];\n\n for (const entry of entries) {\n if (columns.left.ref) {\n left.ref = entry[columns.left.ref];\n }\n\n if (columns.right.ref) {\n right.ref = entry[columns.right.ref];\n }\n\n if (columns.left.order) {\n left.pos = entry[columns.left.order as string];\n }\n\n if (columns.right.order) {\n right.pos = entry[columns.right.order as string];\n }\n\n if (columns.right.type) {\n right.type = entry[columns.right.type as string];\n }\n\n if (columns.right.field) {\n right.field = entry[columns.right.field as string];\n }\n\n morphLinks.push({\n kind,\n relation,\n left: clone(left as ILink['left']),\n right: clone(right as ILink['right']),\n });\n }\n\n yield* filterMorphLinksByTargetExistence(strapi, morphLinks, onOrphanedLink);\n }\n }\n\n if (attribute.morphColumn) {\n const { typeColumn, idColumn } = attribute.morphColumn;\n\n const qb = connection\n .queryBuilder()\n .select('id', typeColumn.name, idColumn.name)\n .from(addSchema(metadata.tableName))\n .whereNotNull(typeColumn.name)\n .whereNotNull(idColumn.name);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n const entries = await qb;\n const morphLinks: ILink[] = entries.map((entry: Record<string, unknown>) => ({\n kind,\n relation,\n left: { type: uid, ref: entry.id as number, field: fieldName },\n right: { type: entry[typeColumn.name] as string, ref: entry[idColumn.name] as number },\n }));\n\n yield* filterMorphLinksByTargetExistence(strapi, morphLinks, onOrphanedLink);\n }\n }\n\n async function* generateAll(uid: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n for (const fieldName of Object.keys(attributes)) {\n for await (const link of generateAllForAttribute(uid, fieldName)) {\n yield link;\n }\n }\n }\n\n const insert = async (link: ILink) => {\n const { kind, left, right } = link;\n\n const metadata = strapi.db.metadata.get(left.type);\n const attribute = metadata.attributes[left.field];\n\n const payload = {};\n\n /**\n * This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages\n * and a user is importing EE data into a CE project.\n */\n if (!attribute) {\n return;\n }\n\n if (attribute.type !== 'relation') {\n throw new Error(`Attribute ${left.field} is not a relation`);\n }\n\n if ('joinColumn' in attribute && attribute.joinColumn) {\n const joinColumnName = attribute.joinColumn.name;\n\n // Note: this addSchema may not be necessary, but is added for safety\n const qb = connection(addSchema(metadata.tableName))\n .where('id', left.ref)\n .update({ [joinColumnName]: right.ref });\n if (trx) {\n qb.transacting(trx);\n }\n await qb;\n }\n\n if ('joinTable' in attribute && attribute.joinTable) {\n const { joinTable } = attribute;\n\n if (joinTable.joinColumn) {\n Object.assign(payload, { [joinTable.joinColumn.name]: left.ref });\n }\n\n const assignInverseColumn = () => {\n if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {\n Object.assign(payload, {\n [joinTable.inverseJoinColumn.name]: right.ref,\n });\n }\n };\n\n const assignOrderColumns = () => {\n if ('orderColumnName' in joinTable && joinTable.orderColumnName) {\n Object.assign(payload, { [joinTable.orderColumnName]: left.pos ?? null });\n }\n\n if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {\n Object.assign(payload, { [joinTable.inverseOrderColumnName]: right.pos ?? null });\n }\n };\n\n const assignMorphColumns = () => {\n if ('morphColumn' in joinTable && joinTable.morphColumn) {\n const { idColumn, typeColumn } = joinTable.morphColumn ?? {};\n\n if (idColumn) {\n Object.assign(payload, { [idColumn.name]: right.ref });\n }\n\n if (typeColumn) {\n Object.assign(payload, { [typeColumn.name]: right.type });\n }\n\n Object.assign(payload, { order: right.pos ?? null, field: right.field ?? null });\n }\n };\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n assignInverseColumn();\n }\n\n if (kind === 'relation.morph') {\n assignMorphColumns();\n }\n\n assignOrderColumns();\n const qb = connection.insert(payload).into(addSchema(joinTable.name));\n if (trx) {\n await qb.transacting(trx);\n }\n }\n\n if ('morphColumn' in attribute && attribute.morphColumn) {\n const { morphColumn } = attribute;\n\n const qb = connection(addSchema(metadata.tableName))\n .where('id', left.ref)\n .update({\n [morphColumn.idColumn.name]: right.ref,\n [morphColumn.typeColumn.name]: right.type,\n });\n\n if (trx) {\n qb.transacting(trx);\n }\n\n await qb;\n }\n };\n\n return { generateAll, generateAllForAttribute, insert };\n };\n\n return query;\n};\n\nexport const filterValidRelationalAttributes = (attributes: Record<string, any>) => {\n const isOwner = (attribute: any) => {\n return attribute.owner || (!attribute.mappedBy && !attribute.morphBy);\n };\n\n const isComponentLike = (attribute: any) => attribute.joinTable?.name.endsWith('_cmps');\n\n return Object.entries(attributes)\n .filter(([, attribute]) => {\n return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);\n })\n .reduce<Record<string, any>>((acc, [key, attribute]) => ({ ...acc, [key]: attribute }), {});\n};\n\nconst getLinkKind = (attribute: any, uid: string): ILink['kind'] => {\n if (attribute.relation.startsWith('morph')) {\n return 'relation.morph';\n }\n\n if (attribute.target === uid) {\n return 'relation.circular';\n }\n\n return 'relation.basic';\n};\n"],"names":["TARGET_EXISTS_ALIAS","LEFT_EXISTS_ALIAS","RIGHT_EXISTS_ALIAS","EXISTENCE_CHECK_CHUNK_SIZE","getMetadataTableName","strapi","uid","metadata","db","get","Error","tableName","refKey","ref","loadExistingRefs","refs","existing","Set","has","uniqueRefs","numericIds","filter","documentIds","i","length","chunk","slice","rows","query","findMany","select","where","id","$in","row","add","documentId","filterMorphLinksByTargetExistence","links","onOrphanedLink","refsByType","Map","link","type","right","bucket","push","set","existingByType","aliasColumn","tableAlias","column","selectAliasedColumns","columns","map","createLinkQuery","trx","options","connection","addSchema","schemaName","client","connectionSettings","schema","generateAllForAttribute","fieldName","attributes","filterValidRelationalAttributes","attribute","kind","getLinkKind","relation","target","joinColumn","joinColumnName","name","referencedColumn","ownerAlias","targetAlias","ownerTable","targetTable","targetExistsSubquery","queryBuilder","raw","from","whereRaw","qb","whereNotNull","whereExists","transacting","entries","entry","left","field","joinTable","inverseJoinColumn","orderColumnName","morphColumn","inverseOrderColumnName","inversedBy","order","joinAlias","leftAlias","rightAlias","leftTable","rightTable","leftReferencedColumn","rightReferencedColumn","validColumns","isNil","buildJoinTableLink","linkLeft","linkRight","pos","clone","selectColumns","joinQb","leftJoin","innerJoin","idColumn","typeColumn","morphLinks","generateAll","Object","keys","insert","payload","update","assign","assignInverseColumn","assignOrderColumns","assignMorphColumns","into","isOwner","owner","mappedBy","morphBy","isComponentLike","endsWith","reduce","acc","key","startsWith"],"mappings":"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"}
@@ -1,7 +1,105 @@
1
1
  import { isNil, clone } from 'lodash/fp';
2
2
 
3
3
  // TODO: Remove any types when we'll have types for DB metadata
4
- const createLinkQuery = (strapi, trx)=>{
4
+ const TARGET_EXISTS_ALIAS = '__target_exists';
5
+ const LEFT_EXISTS_ALIAS = '__left_exists';
6
+ const RIGHT_EXISTS_ALIAS = '__right_exists';
7
+ const EXISTENCE_CHECK_CHUNK_SIZE = 1000;
8
+ const getMetadataTableName = (strapi, uid)=>{
9
+ const metadata = strapi.db.metadata.get(uid);
10
+ if (!metadata) {
11
+ throw new Error(`No metadata found for ${uid}`);
12
+ }
13
+ return metadata.tableName;
14
+ };
15
+ const refKey = (ref)=>`${typeof ref}:${ref}`;
16
+ /**
17
+ * Batch-load which refs exist for a content type. Handles numeric `id` refs and
18
+ * string `documentId` refs separately, chunked to keep `IN (...)` lists bounded.
19
+ */ const loadExistingRefs = async (strapi, uid, refs)=>{
20
+ const existing = new Set();
21
+ // Stale morph type UIDs (removed components/CTs) have no metadata — treat as orphaned.
22
+ if (!strapi.db.metadata.has(uid)) {
23
+ return existing;
24
+ }
25
+ const uniqueRefs = [
26
+ ...new Set(refs)
27
+ ];
28
+ const numericIds = uniqueRefs.filter((ref)=>typeof ref === 'number');
29
+ const documentIds = uniqueRefs.filter((ref)=>typeof ref === 'string');
30
+ for(let i = 0; i < numericIds.length; i += EXISTENCE_CHECK_CHUNK_SIZE){
31
+ const chunk = numericIds.slice(i, i + EXISTENCE_CHECK_CHUNK_SIZE);
32
+ const rows = await strapi.db.query(uid).findMany({
33
+ select: [
34
+ 'id'
35
+ ],
36
+ where: {
37
+ id: {
38
+ $in: chunk
39
+ }
40
+ }
41
+ });
42
+ for (const row of rows){
43
+ existing.add(refKey(row.id));
44
+ }
45
+ }
46
+ for(let i = 0; i < documentIds.length; i += EXISTENCE_CHECK_CHUNK_SIZE){
47
+ const chunk = documentIds.slice(i, i + EXISTENCE_CHECK_CHUNK_SIZE);
48
+ const rows = await strapi.db.query(uid).findMany({
49
+ select: [
50
+ 'id',
51
+ 'documentId'
52
+ ],
53
+ where: {
54
+ documentId: {
55
+ $in: chunk
56
+ }
57
+ }
58
+ });
59
+ for (const row of rows){
60
+ if (row.documentId != null) {
61
+ existing.add(refKey(row.documentId));
62
+ }
63
+ }
64
+ }
65
+ return existing;
66
+ };
67
+ /**
68
+ * Filter morph links in batches. The morph owner (`left`) is not checked:
69
+ * morphColumn rows come from the owner table itself, and morph join-table
70
+ * owners are FK-backed. Only dynamic morph targets (`right`) need existence
71
+ * checks, and those have no DB-level FK.
72
+ */ const filterMorphLinksByTargetExistence = async function* filterMorphLinksByTargetExistence(strapi, links, onOrphanedLink) {
73
+ const refsByType = new Map();
74
+ for (const link of links){
75
+ const { type, ref } = link.right;
76
+ if (ref == null || type == null) {
77
+ onOrphanedLink?.(link);
78
+ } else {
79
+ const bucket = refsByType.get(type) ?? [];
80
+ bucket.push(ref);
81
+ refsByType.set(type, bucket);
82
+ }
83
+ }
84
+ const existingByType = new Map();
85
+ for (const [type, refs] of refsByType){
86
+ existingByType.set(type, await loadExistingRefs(strapi, type, refs));
87
+ }
88
+ for (const link of links){
89
+ const { type, ref } = link.right;
90
+ if (ref == null || type == null) ; else if (existingByType.get(type)?.has(refKey(ref))) {
91
+ yield link;
92
+ } else {
93
+ onOrphanedLink?.(link);
94
+ }
95
+ }
96
+ };
97
+ const aliasColumn = (tableAlias, column)=>`${tableAlias}.${column}`;
98
+ const selectAliasedColumns = (tableAlias, columns)=>columns.map((column)=>({
99
+ [column]: aliasColumn(tableAlias, column)
100
+ }));
101
+ const createLinkQuery = (strapi, trx, options)=>{
102
+ const { onOrphanedLink } = options ?? {};
5
103
  const query = ()=>{
6
104
  const { connection } = strapi.db;
7
105
  // TODO: Export utils from database and use the addSchema that is already written
@@ -25,7 +123,34 @@ const createLinkQuery = (strapi, trx)=>{
25
123
  // TODO: handle manyToOne joinColumn
26
124
  if (attribute.joinColumn) {
27
125
  const joinColumnName = attribute.joinColumn.name;
28
- const qb = connection.queryBuilder().select('id', joinColumnName).from(addSchema(metadata.tableName));
126
+ const referencedColumn = attribute.joinColumn.referencedColumn ?? 'id';
127
+ const ownerAlias = 'owner';
128
+ const targetAlias = 'target';
129
+ const ownerTable = addSchema(metadata.tableName);
130
+ const targetTable = addSchema(getMetadataTableName(strapi, target));
131
+ // Use EXISTS (not JOIN): joining on non-unique referencedColumn (e.g. i18n
132
+ // document_id) multiplies owner rows by matching target locales.
133
+ const targetExistsSubquery = ()=>connection.queryBuilder().select(connection.raw('1')).from({
134
+ [targetAlias]: targetTable
135
+ }).whereRaw('??.?? = ??.??', [
136
+ targetAlias,
137
+ referencedColumn,
138
+ ownerAlias,
139
+ joinColumnName
140
+ ]);
141
+ const qb = connection.queryBuilder().select(`${ownerAlias}.id`, `${ownerAlias}.${joinColumnName} as ${joinColumnName}`, ...onOrphanedLink ? // becomes `exists ((select ...))`, which SQLite rejects in a SELECT
142
+ // list. Wrap the EXISTS expression so the compiled SQL is valid.
143
+ [
144
+ connection.raw('(exists ?) as ??', [
145
+ targetExistsSubquery(),
146
+ TARGET_EXISTS_ALIAS
147
+ ])
148
+ ] : []).from({
149
+ [ownerAlias]: ownerTable
150
+ }).whereNotNull(aliasColumn(ownerAlias, joinColumnName));
151
+ if (!onOrphanedLink) {
152
+ qb.whereExists(targetExistsSubquery());
153
+ }
29
154
  if (trx) {
30
155
  qb.transacting(trx);
31
156
  }
@@ -33,27 +158,30 @@ const createLinkQuery = (strapi, trx)=>{
33
158
  const entries = await qb;
34
159
  for (const entry of entries){
35
160
  const ref = entry[joinColumnName];
36
- if (ref !== null) {
37
- yield {
38
- kind,
39
- relation,
40
- left: {
41
- type: uid,
42
- ref: entry.id,
43
- field: fieldName
44
- },
45
- right: {
46
- type: target,
47
- ref
48
- }
49
- };
161
+ const link = {
162
+ kind,
163
+ relation,
164
+ left: {
165
+ type: uid,
166
+ ref: entry.id,
167
+ field: fieldName
168
+ },
169
+ right: {
170
+ type: target,
171
+ ref
172
+ }
173
+ };
174
+ // EXISTS yields 0/1 (or boolean); treat falsy as orphaned.
175
+ if (onOrphanedLink && !entry[TARGET_EXISTS_ALIAS]) {
176
+ onOrphanedLink(link);
177
+ } else {
178
+ yield link;
50
179
  }
51
180
  }
52
181
  }
53
182
  // The relation uses a join table
54
183
  if (attribute.joinTable) {
55
184
  const { name, joinColumn, inverseJoinColumn, orderColumnName, morphColumn, inverseOrderColumnName } = attribute.joinTable;
56
- const qb = connection.queryBuilder().from(addSchema(name));
57
185
  const columns = {
58
186
  left: {
59
187
  ref: null
@@ -78,56 +206,137 @@ const createLinkQuery = (strapi, trx)=>{
78
206
  if (inverseOrderColumnName) {
79
207
  columns.right.order = inverseOrderColumnName;
80
208
  }
209
+ const joinAlias = 'join';
210
+ const leftAlias = 'left';
211
+ const rightAlias = 'right';
212
+ const joinTable = addSchema(name);
213
+ const leftTable = addSchema(metadata.tableName);
214
+ const rightTable = addSchema(getMetadataTableName(strapi, attribute.target));
215
+ const leftReferencedColumn = aliasColumn(leftAlias, joinColumn.referencedColumn ?? 'id');
216
+ const rightReferencedColumn = aliasColumn(rightAlias, inverseJoinColumn.referencedColumn ?? 'id');
217
+ const validColumns = [
218
+ columns.left.ref,
219
+ columns.left.order,
220
+ columns.right.ref,
221
+ columns.right.order
222
+ ].filter((column)=>!isNil(column));
223
+ const buildJoinTableLink = (entry)=>{
224
+ const linkLeft = {
225
+ type: uid,
226
+ field: fieldName
227
+ };
228
+ const linkRight = {
229
+ type: attribute.target,
230
+ field: attribute.inversedBy
231
+ };
232
+ if (columns.left.ref) {
233
+ linkLeft.ref = entry[columns.left.ref];
234
+ }
235
+ if (columns.right.ref) {
236
+ linkRight.ref = entry[columns.right.ref];
237
+ }
238
+ if (columns.left.order) {
239
+ linkLeft.pos = entry[columns.left.order];
240
+ }
241
+ if (columns.right.order) {
242
+ linkRight.pos = entry[columns.right.order];
243
+ }
244
+ return {
245
+ kind,
246
+ relation,
247
+ left: clone(linkLeft),
248
+ right: clone(linkRight)
249
+ };
250
+ };
251
+ const selectColumns = [
252
+ ...selectAliasedColumns(joinAlias, validColumns),
253
+ ...onOrphanedLink ? [
254
+ {
255
+ [LEFT_EXISTS_ALIAS]: leftReferencedColumn
256
+ },
257
+ {
258
+ [RIGHT_EXISTS_ALIAS]: rightReferencedColumn
259
+ }
260
+ ] : []
261
+ ];
262
+ const joinQb = connection.queryBuilder().select(selectColumns).from({
263
+ [joinAlias]: joinTable
264
+ });
265
+ if (onOrphanedLink) {
266
+ joinQb.leftJoin({
267
+ [leftAlias]: leftTable
268
+ }, aliasColumn(joinAlias, joinColumn.name), leftReferencedColumn).leftJoin({
269
+ [rightAlias]: rightTable
270
+ }, aliasColumn(joinAlias, inverseJoinColumn.name), rightReferencedColumn);
271
+ } else {
272
+ joinQb.innerJoin({
273
+ [leftAlias]: leftTable
274
+ }, aliasColumn(joinAlias, joinColumn.name), leftReferencedColumn).innerJoin({
275
+ [rightAlias]: rightTable
276
+ }, aliasColumn(joinAlias, inverseJoinColumn.name), rightReferencedColumn);
277
+ }
278
+ if (trx) {
279
+ joinQb.transacting(trx);
280
+ }
281
+ const entries = await joinQb;
282
+ for (const entry of entries){
283
+ const link = buildJoinTableLink(entry);
284
+ if (onOrphanedLink && (entry[LEFT_EXISTS_ALIAS] == null || entry[RIGHT_EXISTS_ALIAS] == null)) {
285
+ onOrphanedLink(link);
286
+ } else {
287
+ yield link;
288
+ }
289
+ }
81
290
  }
82
291
  if (kind === 'relation.morph') {
292
+ const qb = connection.queryBuilder().from(addSchema(name));
83
293
  columns.left.ref = joinColumn.name;
84
294
  columns.right.ref = morphColumn.idColumn.name;
85
295
  columns.right.type = morphColumn.typeColumn.name;
86
296
  columns.right.field = 'field';
87
297
  columns.right.order = 'order';
88
- }
89
- const validColumns = [
90
- // Left
91
- columns.left.ref,
92
- columns.left.order,
93
- // Right
94
- columns.right.ref,
95
- columns.right.type,
96
- columns.right.field,
97
- columns.right.order
98
- ].filter((column)=>!isNil(column));
99
- qb.select(validColumns);
100
- if (trx) {
101
- qb.transacting(trx);
102
- }
103
- // TODO: stream the query to improve performances
104
- const entries = await qb;
105
- for (const entry of entries){
106
- if (columns.left.ref) {
107
- left.ref = entry[columns.left.ref];
108
- }
109
- if (columns.right.ref) {
110
- right.ref = entry[columns.right.ref];
298
+ const validColumns = [
299
+ columns.left.ref,
300
+ columns.left.order,
301
+ columns.right.ref,
302
+ columns.right.type,
303
+ columns.right.field,
304
+ columns.right.order
305
+ ].filter((column)=>!isNil(column));
306
+ qb.select(validColumns);
307
+ if (trx) {
308
+ qb.transacting(trx);
111
309
  }
112
- if (columns.left.order) {
113
- left.pos = entry[columns.left.order];
114
- }
115
- if (columns.right.order) {
116
- right.pos = entry[columns.right.order];
117
- }
118
- if (columns.right.type) {
119
- right.type = entry[columns.right.type];
120
- }
121
- if (columns.right.field) {
122
- right.field = entry[columns.right.field];
310
+ // TODO: stream the query to improve performances
311
+ const entries = await qb;
312
+ const morphLinks = [];
313
+ for (const entry of entries){
314
+ if (columns.left.ref) {
315
+ left.ref = entry[columns.left.ref];
316
+ }
317
+ if (columns.right.ref) {
318
+ right.ref = entry[columns.right.ref];
319
+ }
320
+ if (columns.left.order) {
321
+ left.pos = entry[columns.left.order];
322
+ }
323
+ if (columns.right.order) {
324
+ right.pos = entry[columns.right.order];
325
+ }
326
+ if (columns.right.type) {
327
+ right.type = entry[columns.right.type];
328
+ }
329
+ if (columns.right.field) {
330
+ right.field = entry[columns.right.field];
331
+ }
332
+ morphLinks.push({
333
+ kind,
334
+ relation,
335
+ left: clone(left),
336
+ right: clone(right)
337
+ });
123
338
  }
124
- const link = {
125
- kind,
126
- relation,
127
- left: clone(left),
128
- right: clone(right)
129
- };
130
- yield link;
339
+ yield* filterMorphLinksByTargetExistence(strapi, morphLinks, onOrphanedLink);
131
340
  }
132
341
  }
133
342
  if (attribute.morphColumn) {
@@ -137,9 +346,7 @@ const createLinkQuery = (strapi, trx)=>{
137
346
  qb.transacting(trx);
138
347
  }
139
348
  const entries = await qb;
140
- for (const entry of entries){
141
- const ref = entry[idColumn.name];
142
- yield {
349
+ const morphLinks = entries.map((entry)=>({
143
350
  kind,
144
351
  relation,
145
352
  left: {
@@ -149,10 +356,10 @@ const createLinkQuery = (strapi, trx)=>{
149
356
  },
150
357
  right: {
151
358
  type: entry[typeColumn.name],
152
- ref
359
+ ref: entry[idColumn.name]
153
360
  }
154
- };
155
- }
361
+ }));
362
+ yield* filterMorphLinksByTargetExistence(strapi, morphLinks, onOrphanedLink);
156
363
  }
157
364
  }
158
365
  async function* generateAll(uid) {