@strapi/core 5.46.0 → 5.47.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 (205) hide show
  1. package/dist/core-api/routes/index.js +2 -0
  2. package/dist/core-api/routes/index.js.map +1 -1
  3. package/dist/core-api/routes/index.mjs +2 -0
  4. package/dist/core-api/routes/index.mjs.map +1 -1
  5. package/dist/core-api/routes/validation/content-type.d.ts +13 -1
  6. package/dist/core-api/routes/validation/content-type.d.ts.map +1 -1
  7. package/dist/core-api/routes/validation/content-type.js +15 -2
  8. package/dist/core-api/routes/validation/content-type.js.map +1 -1
  9. package/dist/core-api/routes/validation/content-type.mjs +15 -2
  10. package/dist/core-api/routes/validation/content-type.mjs.map +1 -1
  11. package/dist/migrations/database/5.0.0-discard-drafts.d.ts +2 -1
  12. package/dist/migrations/database/5.0.0-discard-drafts.d.ts.map +1 -1
  13. package/dist/migrations/database/5.0.0-discard-drafts.js +64 -30
  14. package/dist/migrations/database/5.0.0-discard-drafts.js.map +1 -1
  15. package/dist/migrations/database/5.0.0-discard-drafts.mjs +64 -30
  16. package/dist/migrations/database/5.0.0-discard-drafts.mjs.map +1 -1
  17. package/dist/package.json.js +14 -12
  18. package/dist/package.json.js.map +1 -1
  19. package/dist/package.json.mjs +14 -12
  20. package/dist/package.json.mjs.map +1 -1
  21. package/dist/providers/index.d.ts.map +1 -1
  22. package/dist/providers/index.js +3 -1
  23. package/dist/providers/index.js.map +1 -1
  24. package/dist/providers/index.mjs +3 -1
  25. package/dist/providers/index.mjs.map +1 -1
  26. package/dist/providers/mcp.d.ts +3 -0
  27. package/dist/providers/mcp.d.ts.map +1 -0
  28. package/dist/providers/mcp.js +39 -0
  29. package/dist/providers/mcp.js.map +1 -0
  30. package/dist/providers/mcp.mjs +37 -0
  31. package/dist/providers/mcp.mjs.map +1 -0
  32. package/dist/providers/session-manager.d.ts.map +1 -1
  33. package/dist/providers/session-manager.js +1 -2
  34. package/dist/providers/session-manager.js.map +1 -1
  35. package/dist/providers/session-manager.mjs +1 -2
  36. package/dist/providers/session-manager.mjs.map +1 -1
  37. package/dist/services/ai.d.ts.map +1 -1
  38. package/dist/services/ai.js +3 -0
  39. package/dist/services/ai.js.map +1 -1
  40. package/dist/services/ai.mjs +3 -0
  41. package/dist/services/ai.mjs.map +1 -1
  42. package/dist/services/document-service/draft-and-publish.d.ts +2 -16
  43. package/dist/services/document-service/draft-and-publish.d.ts.map +1 -1
  44. package/dist/services/document-service/draft-and-publish.js +0 -53
  45. package/dist/services/document-service/draft-and-publish.js.map +1 -1
  46. package/dist/services/document-service/draft-and-publish.mjs +2 -53
  47. package/dist/services/document-service/draft-and-publish.mjs.map +1 -1
  48. package/dist/services/document-service/params.d.ts +2 -2
  49. package/dist/services/document-service/params.d.ts.map +1 -1
  50. package/dist/services/document-service/publication-filter.d.ts +6 -0
  51. package/dist/services/document-service/publication-filter.d.ts.map +1 -0
  52. package/dist/services/document-service/publication-filter.js +20 -0
  53. package/dist/services/document-service/publication-filter.js.map +1 -0
  54. package/dist/services/document-service/publication-filter.mjs +15 -0
  55. package/dist/services/document-service/publication-filter.mjs.map +1 -0
  56. package/dist/services/document-service/transform/query.d.ts +1 -1
  57. package/dist/services/document-service/transform/query.d.ts.map +1 -1
  58. package/dist/services/document-service/transform/query.js +32 -19
  59. package/dist/services/document-service/transform/query.js.map +1 -1
  60. package/dist/services/document-service/transform/query.mjs +33 -20
  61. package/dist/services/document-service/transform/query.mjs.map +1 -1
  62. package/dist/services/entity-validator/blocks-validator.js +1 -1
  63. package/dist/services/entity-validator/blocks-validator.js.map +1 -1
  64. package/dist/services/entity-validator/blocks-validator.mjs +1 -1
  65. package/dist/services/entity-validator/blocks-validator.mjs.map +1 -1
  66. package/dist/services/mcp/authentication.d.ts +23 -0
  67. package/dist/services/mcp/authentication.d.ts.map +1 -0
  68. package/dist/services/mcp/authentication.js +45 -0
  69. package/dist/services/mcp/authentication.js.map +1 -0
  70. package/dist/services/mcp/authentication.mjs +43 -0
  71. package/dist/services/mcp/authentication.mjs.map +1 -0
  72. package/dist/services/mcp/handlers/handlePost.d.ts +4 -0
  73. package/dist/services/mcp/handlers/handlePost.d.ts.map +1 -0
  74. package/dist/services/mcp/handlers/handlePost.js +59 -0
  75. package/dist/services/mcp/handlers/handlePost.js.map +1 -0
  76. package/dist/services/mcp/handlers/handlePost.mjs +57 -0
  77. package/dist/services/mcp/handlers/handlePost.mjs.map +1 -0
  78. package/dist/services/mcp/handlers/types.d.ts +12 -0
  79. package/dist/services/mcp/handlers/types.d.ts.map +1 -0
  80. package/dist/services/mcp/index.d.ts +6 -0
  81. package/dist/services/mcp/index.d.ts.map +1 -0
  82. package/dist/services/mcp/index.js +101 -0
  83. package/dist/services/mcp/index.js.map +1 -0
  84. package/dist/services/mcp/index.mjs +99 -0
  85. package/dist/services/mcp/index.mjs.map +1 -0
  86. package/dist/services/mcp/internal/McpCapabilityDefinitionRegistry.d.ts +13 -0
  87. package/dist/services/mcp/internal/McpCapabilityDefinitionRegistry.d.ts.map +1 -0
  88. package/dist/services/mcp/internal/McpCapabilityDefinitionRegistry.js +53 -0
  89. package/dist/services/mcp/internal/McpCapabilityDefinitionRegistry.js.map +1 -0
  90. package/dist/services/mcp/internal/McpCapabilityDefinitionRegistry.mjs +51 -0
  91. package/dist/services/mcp/internal/McpCapabilityDefinitionRegistry.mjs.map +1 -0
  92. package/dist/services/mcp/internal/McpCapabilityRegistry.d.ts +43 -0
  93. package/dist/services/mcp/internal/McpCapabilityRegistry.d.ts.map +1 -0
  94. package/dist/services/mcp/internal/McpCapabilityRegistry.js +108 -0
  95. package/dist/services/mcp/internal/McpCapabilityRegistry.js.map +1 -0
  96. package/dist/services/mcp/internal/McpCapabilityRegistry.mjs +106 -0
  97. package/dist/services/mcp/internal/McpCapabilityRegistry.mjs.map +1 -0
  98. package/dist/services/mcp/internal/McpConfiguration.d.ts +11 -0
  99. package/dist/services/mcp/internal/McpConfiguration.d.ts.map +1 -0
  100. package/dist/services/mcp/internal/McpConfiguration.js +34 -0
  101. package/dist/services/mcp/internal/McpConfiguration.js.map +1 -0
  102. package/dist/services/mcp/internal/McpConfiguration.mjs +32 -0
  103. package/dist/services/mcp/internal/McpConfiguration.mjs.map +1 -0
  104. package/dist/services/mcp/internal/McpServerFactory.d.ts +37 -0
  105. package/dist/services/mcp/internal/McpServerFactory.d.ts.map +1 -0
  106. package/dist/services/mcp/internal/McpServerFactory.js +71 -0
  107. package/dist/services/mcp/internal/McpServerFactory.js.map +1 -0
  108. package/dist/services/mcp/internal/McpServerFactory.mjs +69 -0
  109. package/dist/services/mcp/internal/McpServerFactory.mjs.map +1 -0
  110. package/dist/services/mcp/internal/syncMcpSessionCapabilities.d.ts +21 -0
  111. package/dist/services/mcp/internal/syncMcpSessionCapabilities.d.ts.map +1 -0
  112. package/dist/services/mcp/internal/syncMcpSessionCapabilities.js +76 -0
  113. package/dist/services/mcp/internal/syncMcpSessionCapabilities.js.map +1 -0
  114. package/dist/services/mcp/internal/syncMcpSessionCapabilities.mjs +73 -0
  115. package/dist/services/mcp/internal/syncMcpSessionCapabilities.mjs.map +1 -0
  116. package/dist/services/mcp/metrics/metrics.d.ts +29 -0
  117. package/dist/services/mcp/metrics/metrics.d.ts.map +1 -0
  118. package/dist/services/mcp/metrics/metrics.js +97 -0
  119. package/dist/services/mcp/metrics/metrics.js.map +1 -0
  120. package/dist/services/mcp/metrics/metrics.mjs +88 -0
  121. package/dist/services/mcp/metrics/metrics.mjs.map +1 -0
  122. package/dist/services/mcp/metrics/normalizeMcpCapability.d.ts +11 -0
  123. package/dist/services/mcp/metrics/normalizeMcpCapability.d.ts.map +1 -0
  124. package/dist/services/mcp/metrics/normalizeMcpCapability.js +10 -0
  125. package/dist/services/mcp/metrics/normalizeMcpCapability.js.map +1 -0
  126. package/dist/services/mcp/metrics/normalizeMcpCapability.mjs +8 -0
  127. package/dist/services/mcp/metrics/normalizeMcpCapability.mjs.map +1 -0
  128. package/dist/services/mcp/metrics/wrapCapabilityHandlerForMetrics.d.ts +4 -0
  129. package/dist/services/mcp/metrics/wrapCapabilityHandlerForMetrics.d.ts.map +1 -0
  130. package/dist/services/mcp/metrics/wrapCapabilityHandlerForMetrics.js +27 -0
  131. package/dist/services/mcp/metrics/wrapCapabilityHandlerForMetrics.js.map +1 -0
  132. package/dist/services/mcp/metrics/wrapCapabilityHandlerForMetrics.mjs +25 -0
  133. package/dist/services/mcp/metrics/wrapCapabilityHandlerForMetrics.mjs.map +1 -0
  134. package/dist/services/mcp/middleware/oauthDiscoveryFallback.d.ts +3 -0
  135. package/dist/services/mcp/middleware/oauthDiscoveryFallback.d.ts.map +1 -0
  136. package/dist/services/mcp/middleware/oauthDiscoveryFallback.js +47 -0
  137. package/dist/services/mcp/middleware/oauthDiscoveryFallback.js.map +1 -0
  138. package/dist/services/mcp/middleware/oauthDiscoveryFallback.mjs +45 -0
  139. package/dist/services/mcp/middleware/oauthDiscoveryFallback.mjs.map +1 -0
  140. package/dist/services/mcp/prompt-registry.d.ts +16 -0
  141. package/dist/services/mcp/prompt-registry.d.ts.map +1 -0
  142. package/dist/services/mcp/prompt-registry.js +77 -0
  143. package/dist/services/mcp/prompt-registry.js.map +1 -0
  144. package/dist/services/mcp/prompt-registry.mjs +75 -0
  145. package/dist/services/mcp/prompt-registry.mjs.map +1 -0
  146. package/dist/services/mcp/resource-registry.d.ts +14 -0
  147. package/dist/services/mcp/resource-registry.d.ts.map +1 -0
  148. package/dist/services/mcp/resource-registry.js +67 -0
  149. package/dist/services/mcp/resource-registry.js.map +1 -0
  150. package/dist/services/mcp/resource-registry.mjs +65 -0
  151. package/dist/services/mcp/resource-registry.mjs.map +1 -0
  152. package/dist/services/mcp/routes.d.ts +11 -0
  153. package/dist/services/mcp/routes.d.ts.map +1 -0
  154. package/dist/services/mcp/routes.js +58 -0
  155. package/dist/services/mcp/routes.js.map +1 -0
  156. package/dist/services/mcp/routes.mjs +56 -0
  157. package/dist/services/mcp/routes.mjs.map +1 -0
  158. package/dist/services/mcp/tool-registry.d.ts +25 -0
  159. package/dist/services/mcp/tool-registry.d.ts.map +1 -0
  160. package/dist/services/mcp/tool-registry.js +102 -0
  161. package/dist/services/mcp/tool-registry.js.map +1 -0
  162. package/dist/services/mcp/tool-registry.mjs +99 -0
  163. package/dist/services/mcp/tool-registry.mjs.map +1 -0
  164. package/dist/services/mcp/tools/log.d.ts +87 -0
  165. package/dist/services/mcp/tools/log.d.ts.map +1 -0
  166. package/dist/services/mcp/tools/log.js +88 -0
  167. package/dist/services/mcp/tools/log.js.map +1 -0
  168. package/dist/services/mcp/tools/log.mjs +86 -0
  169. package/dist/services/mcp/tools/log.mjs.map +1 -0
  170. package/dist/services/mcp/utils/createSafeCapabilityRegistration.d.ts +36 -0
  171. package/dist/services/mcp/utils/createSafeCapabilityRegistration.d.ts.map +1 -0
  172. package/dist/services/mcp/utils/createSafeCapabilityRegistration.js +59 -0
  173. package/dist/services/mcp/utils/createSafeCapabilityRegistration.js.map +1 -0
  174. package/dist/services/mcp/utils/createSafeCapabilityRegistration.mjs +56 -0
  175. package/dist/services/mcp/utils/createSafeCapabilityRegistration.mjs.map +1 -0
  176. package/dist/services/mcp/utils/jsonRpcErrors.d.ts +22 -0
  177. package/dist/services/mcp/utils/jsonRpcErrors.d.ts.map +1 -0
  178. package/dist/services/mcp/utils/jsonRpcErrors.js +25 -0
  179. package/dist/services/mcp/utils/jsonRpcErrors.js.map +1 -0
  180. package/dist/services/mcp/utils/jsonRpcErrors.mjs +23 -0
  181. package/dist/services/mcp/utils/jsonRpcErrors.mjs.map +1 -0
  182. package/dist/services/mcp/utils/safeHandlerWrapper.d.ts +18 -0
  183. package/dist/services/mcp/utils/safeHandlerWrapper.d.ts.map +1 -0
  184. package/dist/services/mcp/utils/safeHandlerWrapper.js +29 -0
  185. package/dist/services/mcp/utils/safeHandlerWrapper.js.map +1 -0
  186. package/dist/services/mcp/utils/safeHandlerWrapper.mjs +27 -0
  187. package/dist/services/mcp/utils/safeHandlerWrapper.mjs.map +1 -0
  188. package/dist/services/mcp/utils/sendJsonRpcError.d.ts +5 -0
  189. package/dist/services/mcp/utils/sendJsonRpcError.d.ts.map +1 -0
  190. package/dist/services/mcp/utils/sendJsonRpcError.js +23 -0
  191. package/dist/services/mcp/utils/sendJsonRpcError.js.map +1 -0
  192. package/dist/services/mcp/utils/sendJsonRpcError.mjs +21 -0
  193. package/dist/services/mcp/utils/sendJsonRpcError.mjs.map +1 -0
  194. package/dist/services/mcp/utils/withTimeout.d.ts +7 -0
  195. package/dist/services/mcp/utils/withTimeout.d.ts.map +1 -0
  196. package/dist/services/mcp/utils/withTimeout.js +23 -0
  197. package/dist/services/mcp/utils/withTimeout.js.map +1 -0
  198. package/dist/services/mcp/utils/withTimeout.mjs +21 -0
  199. package/dist/services/mcp/utils/withTimeout.mjs.map +1 -0
  200. package/dist/services/metrics/index.d.ts.map +1 -1
  201. package/dist/services/metrics/index.js +3 -1
  202. package/dist/services/metrics/index.js.map +1 -1
  203. package/dist/services/metrics/index.mjs +3 -1
  204. package/dist/services/metrics/index.mjs.map +1 -1
  205. package/package.json +14 -12
@@ -82,23 +82,39 @@ const DEFAULT_PRIMARY_KEY_COLUMN = 'id';
82
82
  return true;
83
83
  };
84
84
  /**
85
- * Copy all the published entries to draft entries, without it's components, dynamic zones or relations.
86
- * This ensures all necessary draft's exist before copying it's relations.
87
- */ async function copyPublishedEntriesToDraft({ db, trx, uid }) {
88
- // Extract all scalar attributes to use in the insert query
89
- const meta = db.metadata.get(uid);
90
- // Get scalar attributes that will be copied over the new draft
91
- const scalarAttributes = Object.values(meta.attributes).reduce((acc, attribute)=>{
92
- if ([
93
- 'id'
94
- ].includes(attribute.columnName)) {
95
- return acc;
85
+ * Join-column relations that are persisted on the row (e.g. createdBy), excluding virtual
86
+ * relations such as i18n `localizations` which reuse `document_id` and are not DB-owned.
87
+ */ const isPersistedJoinColumnRelation = (attribute)=>attribute?.type === 'relation' && !attribute.unstable_virtual && attribute.joinColumn && !attribute.joinTable;
88
+ /**
89
+ * Column names copied when cloning a published row into a draft (stage 1).
90
+ * Scalars plus persisted join-column FKs; deduped so virtual relations cannot repeat columns.
91
+ */ const getPublishedToDraftCloneColumns = (meta)=>{
92
+ const seen = new Set();
93
+ const columns = [];
94
+ const addColumn = (columnName)=>{
95
+ if (!columnName || columnName === 'id' || seen.has(columnName)) {
96
+ return;
96
97
  }
98
+ seen.add(columnName);
99
+ columns.push(columnName);
100
+ };
101
+ for (const attribute of Object.values(meta.attributes)){
97
102
  if (strapiUtils.contentTypes.isScalarAttribute(attribute)) {
98
- acc.push(attribute.columnName);
103
+ addColumn(attribute.columnName);
104
+ continue;
105
+ }
106
+ if (isPersistedJoinColumnRelation(attribute)) {
107
+ addColumn(attribute.joinColumn.name);
99
108
  }
100
- return acc;
101
- }, []);
109
+ }
110
+ return columns;
111
+ };
112
+ /**
113
+ * Copy published entries to draft rows, cloning scalar fields and join-column foreign keys.
114
+ * Components, dynamic zones, and join-table relations are handled in later stages.
115
+ */ async function copyPublishedEntriesToDraft({ db, trx, uid }) {
116
+ const meta = db.metadata.get(uid);
117
+ const columnsToCopy = getPublishedToDraftCloneColumns(meta);
102
118
  /**
103
119
  * Query to copy the published entries into draft entries.
104
120
  *
@@ -106,12 +122,12 @@ const DEFAULT_PRIMARY_KEY_COLUMN = 'id';
106
122
  * SELECT columnName1, columnName2, columnName3, ...
107
123
  * FROM tableName
108
124
  */ await trx// INSERT INTO tableName (columnName1, columnName2, columnName3, ...)
109
- .into(trx.raw(`?? (${scalarAttributes.map(()=>`??`).join(', ')})`, [
125
+ .into(trx.raw(`?? (${columnsToCopy.map(()=>`??`).join(', ')})`, [
110
126
  meta.tableName,
111
- ...scalarAttributes
127
+ ...columnsToCopy
112
128
  ])).insert((subQb)=>{
113
129
  // SELECT columnName1, columnName2, columnName3, ...
114
- subQb.select(...scalarAttributes.map((att)=>{
130
+ subQb.select(...columnsToCopy.map((att)=>{
115
131
  // NOTE: these literals reference Strapi's built-in system columns. They never get shortened by
116
132
  // the identifier migration (5.0.0-01-convert-identifiers-long-than-max-length) so we can safely
117
133
  // compare/use them directly here.
@@ -971,7 +987,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
971
987
  /**
972
988
  * Builds a reverse map from draft IDs to published IDs for a target content type.
973
989
  * This is needed to check if a target ID is already a draft and find its published version.
974
- */ async function getDraftToPublishedMap(trx, targetUid, reverseMapCache) {
990
+ */ async function getDraftToPublishedMap(trx, targetUid, reverseMapCache, draftMapCache) {
975
991
  if (reverseMapCache.has(targetUid)) {
976
992
  return reverseMapCache.get(targetUid) ?? null;
977
993
  }
@@ -981,7 +997,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
981
997
  return null;
982
998
  }
983
999
  const draftToPublishedMap = new Map();
984
- const draftMap = await getDraftMapForTarget(trx, targetUid, new Map());
1000
+ const draftMap = await getDraftMapForTarget(trx, targetUid, draftMapCache ?? new Map());
985
1001
  if (draftMap) {
986
1002
  // Reverse the published->draft map to get draft->published
987
1003
  for (const [publishedId, draftId] of draftMap.entries()){
@@ -1023,7 +1039,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
1023
1039
  }
1024
1040
  // For published entity, if we got a draft ID, find the published version
1025
1041
  const effectiveReverseCache = reverseMapCache ?? new Map();
1026
- const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache);
1042
+ const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache, draftMapCache);
1027
1043
  if (reverseMap) {
1028
1044
  return reverseMap.get(Number(originalId)) ?? originalId;
1029
1045
  }
@@ -1050,7 +1066,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
1050
1066
  // For published entities: map draft targets to published targets
1051
1067
  if (targetState === 'draft') {
1052
1068
  const effectiveReverseCache = reverseMapCache ?? new Map();
1053
- const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache);
1069
+ const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache, draftMapCache);
1054
1070
  if (reverseMap) {
1055
1071
  return reverseMap.get(Number(originalId)) ?? originalId;
1056
1072
  }
@@ -1090,6 +1106,10 @@ const debug = createDebug('strapi::migration::discard-drafts');
1090
1106
  }
1091
1107
  const joinTable = attribute.joinTable;
1092
1108
  const sourceColumnName = joinTable.joinColumn.name;
1109
+ // Morph join tables use morphColumn instead of inverseJoinColumn — skip them
1110
+ if (!joinTable.inverseJoinColumn) {
1111
+ continue;
1112
+ }
1093
1113
  const targetColumnName = joinTable.inverseJoinColumn.name;
1094
1114
  if (!componentMeta.relationsLogPrinted) {
1095
1115
  debug(`[cloneComponentRelationJoinTables] Inspecting join table ${joinTable.name} for component ${componentUid}`);
@@ -1178,7 +1198,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
1178
1198
  newComponentRow.created_at = resolveNowValue(trx);
1179
1199
  }
1180
1200
  for (const attribute of Object.values(componentMeta.attributes)){
1181
- if (attribute.type !== 'relation') {
1201
+ if (!isPersistedJoinColumnRelation(attribute)) {
1182
1202
  continue;
1183
1203
  }
1184
1204
  const joinColumn = attribute.joinColumn;
@@ -1381,6 +1401,10 @@ const debug = createDebug('strapi::migration::discard-drafts');
1381
1401
  continue;
1382
1402
  }
1383
1403
  const { name: sourceColumnName } = joinTable.joinColumn;
1404
+ // Morph join tables use morphColumn instead of inverseJoinColumn — skip them
1405
+ if (!joinTable.inverseJoinColumn) {
1406
+ continue;
1407
+ }
1384
1408
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1385
1409
  // Process in batches to avoid MySQL query size limits and SQLite expression tree limits
1386
1410
  const publishedIdsChunks = chunkArray(publishedIds, getBatchSize(trx, 1000));
@@ -1480,6 +1504,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1480
1504
  continue;
1481
1505
  }
1482
1506
  const { name: sourceColumnName } = joinTable.joinColumn;
1507
+ if (!joinTable.inverseJoinColumn) {
1508
+ continue;
1509
+ }
1483
1510
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1484
1511
  // Query existing relations by target IDs to avoid duplicates
1485
1512
  const existingKeys = await getExistingRelationKeys({
@@ -1553,6 +1580,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1553
1580
  continue;
1554
1581
  }
1555
1582
  const { name: sourceColumnName } = joinTable.joinColumn;
1583
+ if (!joinTable.inverseJoinColumn) {
1584
+ continue;
1585
+ }
1556
1586
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1557
1587
  // Get target content type's publishedToDraftMap if it has draft/publish (cached)
1558
1588
  const targetUid = attribute.target;
@@ -1673,14 +1703,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1673
1703
  const targetMapCache = new Map();
1674
1704
  // Find all JoinColumn relations (oneToOne, manyToOne without joinTable)
1675
1705
  for (const attribute of Object.values(meta.attributes)){
1676
- if (attribute.type !== 'relation') {
1706
+ if (!isPersistedJoinColumnRelation(attribute)) {
1677
1707
  continue;
1678
1708
  }
1679
- // Skip relations with joinTable (handled by copyRelationsToOtherContentTypes)
1680
- if (attribute.joinTable) {
1681
- continue;
1682
- }
1683
- // Only handle oneToOne and manyToOne relations that use joinColumn
1684
1709
  const joinColumn = attribute.joinColumn;
1685
1710
  if (!joinColumn) {
1686
1711
  continue;
@@ -1789,6 +1814,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1789
1814
  continue;
1790
1815
  }
1791
1816
  const { name: sourceColumnName } = joinTable.joinColumn;
1817
+ if (!joinTable.inverseJoinColumn) {
1818
+ continue;
1819
+ }
1792
1820
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1793
1821
  // Get draft map for target to convert published targets to draft targets
1794
1822
  const targetDraftMap = await getDraftMapForTarget(trx, targetUid, draftMapCache);
@@ -1935,6 +1963,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1935
1963
  if (!targetHasDP) continue;
1936
1964
  const relationJoinTable = attr.joinTable.name;
1937
1965
  const sourceColumn = attr.joinTable.joinColumn.name;
1966
+ if (!attr.joinTable.inverseJoinColumn) {
1967
+ continue;
1968
+ }
1938
1969
  const targetColumn = attr.joinTable.inverseJoinColumn.name;
1939
1970
  const hasRelationTable = await trx.schema.hasTable(relationJoinTable);
1940
1971
  if (!hasRelationTable) continue;
@@ -2104,6 +2135,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
2104
2135
  if (!targetContentType?.options?.draftAndPublish) continue;
2105
2136
  const relationJoinTable = attr.joinTable.name;
2106
2137
  const sourceColumn = attr.joinTable.joinColumn.name;
2138
+ if (!attr.joinTable.inverseJoinColumn) {
2139
+ continue;
2140
+ }
2107
2141
  const targetColumn = attr.joinTable.inverseJoinColumn.name;
2108
2142
  if (!await ensureTableExists(trx, relationJoinTable)) continue;
2109
2143
  const relations = await trx(relationJoinTable).whereIn(sourceColumn, ids).select('id', sourceColumn, targetColumn);
@@ -2200,6 +2234,8 @@ const debug = createDebug('strapi::migration::discard-drafts');
2200
2234
  const publishedIds = Array.from(publishedToDraftMap.keys());
2201
2235
  // Process in batches to avoid MySQL query size limits and SQLite expression tree limits
2202
2236
  const publishedIdsChunks = chunkArray(publishedIds, getBatchSize(trx, 1000));
2237
+ const componentTargetDraftMapCache = new Map();
2238
+ const componentTargetReverseMapCache = new Map();
2203
2239
  for (const publishedIdsChunk of publishedIdsChunks){
2204
2240
  // Get component relations for published entries
2205
2241
  const componentRelations = await trx(joinTableName).select('*').whereIn(entityIdColumn, publishedIdsChunk);
@@ -2208,8 +2244,6 @@ const debug = createDebug('strapi::migration::discard-drafts');
2208
2244
  }
2209
2245
  const componentCloneCache = new Map();
2210
2246
  const clonedComponentPairsCache = new Map();
2211
- const componentTargetDraftMapCache = new Map();
2212
- const componentTargetReverseMapCache = new Map();
2213
2247
  const componentHierarchyCaches = {
2214
2248
  parentInstanceCache: new Map(),
2215
2249
  ancestorDpCache: new Map(),