@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
@@ -80,23 +80,39 @@ const DEFAULT_PRIMARY_KEY_COLUMN = 'id';
80
80
  return true;
81
81
  };
82
82
  /**
83
- * Copy all the published entries to draft entries, without it's components, dynamic zones or relations.
84
- * This ensures all necessary draft's exist before copying it's relations.
85
- */ async function copyPublishedEntriesToDraft({ db, trx, uid }) {
86
- // Extract all scalar attributes to use in the insert query
87
- const meta = db.metadata.get(uid);
88
- // Get scalar attributes that will be copied over the new draft
89
- const scalarAttributes = Object.values(meta.attributes).reduce((acc, attribute)=>{
90
- if ([
91
- 'id'
92
- ].includes(attribute.columnName)) {
93
- return acc;
83
+ * Join-column relations that are persisted on the row (e.g. createdBy), excluding virtual
84
+ * relations such as i18n `localizations` which reuse `document_id` and are not DB-owned.
85
+ */ const isPersistedJoinColumnRelation = (attribute)=>attribute?.type === 'relation' && !attribute.unstable_virtual && attribute.joinColumn && !attribute.joinTable;
86
+ /**
87
+ * Column names copied when cloning a published row into a draft (stage 1).
88
+ * Scalars plus persisted join-column FKs; deduped so virtual relations cannot repeat columns.
89
+ */ const getPublishedToDraftCloneColumns = (meta)=>{
90
+ const seen = new Set();
91
+ const columns = [];
92
+ const addColumn = (columnName)=>{
93
+ if (!columnName || columnName === 'id' || seen.has(columnName)) {
94
+ return;
94
95
  }
96
+ seen.add(columnName);
97
+ columns.push(columnName);
98
+ };
99
+ for (const attribute of Object.values(meta.attributes)){
95
100
  if (contentTypes.isScalarAttribute(attribute)) {
96
- acc.push(attribute.columnName);
101
+ addColumn(attribute.columnName);
102
+ continue;
103
+ }
104
+ if (isPersistedJoinColumnRelation(attribute)) {
105
+ addColumn(attribute.joinColumn.name);
97
106
  }
98
- return acc;
99
- }, []);
107
+ }
108
+ return columns;
109
+ };
110
+ /**
111
+ * Copy published entries to draft rows, cloning scalar fields and join-column foreign keys.
112
+ * Components, dynamic zones, and join-table relations are handled in later stages.
113
+ */ async function copyPublishedEntriesToDraft({ db, trx, uid }) {
114
+ const meta = db.metadata.get(uid);
115
+ const columnsToCopy = getPublishedToDraftCloneColumns(meta);
100
116
  /**
101
117
  * Query to copy the published entries into draft entries.
102
118
  *
@@ -104,12 +120,12 @@ const DEFAULT_PRIMARY_KEY_COLUMN = 'id';
104
120
  * SELECT columnName1, columnName2, columnName3, ...
105
121
  * FROM tableName
106
122
  */ await trx// INSERT INTO tableName (columnName1, columnName2, columnName3, ...)
107
- .into(trx.raw(`?? (${scalarAttributes.map(()=>`??`).join(', ')})`, [
123
+ .into(trx.raw(`?? (${columnsToCopy.map(()=>`??`).join(', ')})`, [
108
124
  meta.tableName,
109
- ...scalarAttributes
125
+ ...columnsToCopy
110
126
  ])).insert((subQb)=>{
111
127
  // SELECT columnName1, columnName2, columnName3, ...
112
- subQb.select(...scalarAttributes.map((att)=>{
128
+ subQb.select(...columnsToCopy.map((att)=>{
113
129
  // NOTE: these literals reference Strapi's built-in system columns. They never get shortened by
114
130
  // the identifier migration (5.0.0-01-convert-identifiers-long-than-max-length) so we can safely
115
131
  // compare/use them directly here.
@@ -969,7 +985,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
969
985
  /**
970
986
  * Builds a reverse map from draft IDs to published IDs for a target content type.
971
987
  * This is needed to check if a target ID is already a draft and find its published version.
972
- */ async function getDraftToPublishedMap(trx, targetUid, reverseMapCache) {
988
+ */ async function getDraftToPublishedMap(trx, targetUid, reverseMapCache, draftMapCache) {
973
989
  if (reverseMapCache.has(targetUid)) {
974
990
  return reverseMapCache.get(targetUid) ?? null;
975
991
  }
@@ -979,7 +995,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
979
995
  return null;
980
996
  }
981
997
  const draftToPublishedMap = new Map();
982
- const draftMap = await getDraftMapForTarget(trx, targetUid, new Map());
998
+ const draftMap = await getDraftMapForTarget(trx, targetUid, draftMapCache ?? new Map());
983
999
  if (draftMap) {
984
1000
  // Reverse the published->draft map to get draft->published
985
1001
  for (const [publishedId, draftId] of draftMap.entries()){
@@ -1021,7 +1037,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
1021
1037
  }
1022
1038
  // For published entity, if we got a draft ID, find the published version
1023
1039
  const effectiveReverseCache = reverseMapCache ?? new Map();
1024
- const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache);
1040
+ const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache, draftMapCache);
1025
1041
  if (reverseMap) {
1026
1042
  return reverseMap.get(Number(originalId)) ?? originalId;
1027
1043
  }
@@ -1048,7 +1064,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
1048
1064
  // For published entities: map draft targets to published targets
1049
1065
  if (targetState === 'draft') {
1050
1066
  const effectiveReverseCache = reverseMapCache ?? new Map();
1051
- const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache);
1067
+ const reverseMap = await getDraftToPublishedMap(trx, targetUid, effectiveReverseCache, draftMapCache);
1052
1068
  if (reverseMap) {
1053
1069
  return reverseMap.get(Number(originalId)) ?? originalId;
1054
1070
  }
@@ -1088,6 +1104,10 @@ const debug = createDebug('strapi::migration::discard-drafts');
1088
1104
  }
1089
1105
  const joinTable = attribute.joinTable;
1090
1106
  const sourceColumnName = joinTable.joinColumn.name;
1107
+ // Morph join tables use morphColumn instead of inverseJoinColumn — skip them
1108
+ if (!joinTable.inverseJoinColumn) {
1109
+ continue;
1110
+ }
1091
1111
  const targetColumnName = joinTable.inverseJoinColumn.name;
1092
1112
  if (!componentMeta.relationsLogPrinted) {
1093
1113
  debug(`[cloneComponentRelationJoinTables] Inspecting join table ${joinTable.name} for component ${componentUid}`);
@@ -1176,7 +1196,7 @@ const debug = createDebug('strapi::migration::discard-drafts');
1176
1196
  newComponentRow.created_at = resolveNowValue(trx);
1177
1197
  }
1178
1198
  for (const attribute of Object.values(componentMeta.attributes)){
1179
- if (attribute.type !== 'relation') {
1199
+ if (!isPersistedJoinColumnRelation(attribute)) {
1180
1200
  continue;
1181
1201
  }
1182
1202
  const joinColumn = attribute.joinColumn;
@@ -1379,6 +1399,10 @@ const debug = createDebug('strapi::migration::discard-drafts');
1379
1399
  continue;
1380
1400
  }
1381
1401
  const { name: sourceColumnName } = joinTable.joinColumn;
1402
+ // Morph join tables use morphColumn instead of inverseJoinColumn — skip them
1403
+ if (!joinTable.inverseJoinColumn) {
1404
+ continue;
1405
+ }
1382
1406
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1383
1407
  // Process in batches to avoid MySQL query size limits and SQLite expression tree limits
1384
1408
  const publishedIdsChunks = chunkArray(publishedIds, getBatchSize(trx, 1000));
@@ -1478,6 +1502,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1478
1502
  continue;
1479
1503
  }
1480
1504
  const { name: sourceColumnName } = joinTable.joinColumn;
1505
+ if (!joinTable.inverseJoinColumn) {
1506
+ continue;
1507
+ }
1481
1508
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1482
1509
  // Query existing relations by target IDs to avoid duplicates
1483
1510
  const existingKeys = await getExistingRelationKeys({
@@ -1551,6 +1578,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1551
1578
  continue;
1552
1579
  }
1553
1580
  const { name: sourceColumnName } = joinTable.joinColumn;
1581
+ if (!joinTable.inverseJoinColumn) {
1582
+ continue;
1583
+ }
1554
1584
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1555
1585
  // Get target content type's publishedToDraftMap if it has draft/publish (cached)
1556
1586
  const targetUid = attribute.target;
@@ -1671,14 +1701,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1671
1701
  const targetMapCache = new Map();
1672
1702
  // Find all JoinColumn relations (oneToOne, manyToOne without joinTable)
1673
1703
  for (const attribute of Object.values(meta.attributes)){
1674
- if (attribute.type !== 'relation') {
1704
+ if (!isPersistedJoinColumnRelation(attribute)) {
1675
1705
  continue;
1676
1706
  }
1677
- // Skip relations with joinTable (handled by copyRelationsToOtherContentTypes)
1678
- if (attribute.joinTable) {
1679
- continue;
1680
- }
1681
- // Only handle oneToOne and manyToOne relations that use joinColumn
1682
1707
  const joinColumn = attribute.joinColumn;
1683
1708
  if (!joinColumn) {
1684
1709
  continue;
@@ -1787,6 +1812,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1787
1812
  continue;
1788
1813
  }
1789
1814
  const { name: sourceColumnName } = joinTable.joinColumn;
1815
+ if (!joinTable.inverseJoinColumn) {
1816
+ continue;
1817
+ }
1790
1818
  const { name: targetColumnName } = joinTable.inverseJoinColumn;
1791
1819
  // Get draft map for target to convert published targets to draft targets
1792
1820
  const targetDraftMap = await getDraftMapForTarget(trx, targetUid, draftMapCache);
@@ -1933,6 +1961,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
1933
1961
  if (!targetHasDP) continue;
1934
1962
  const relationJoinTable = attr.joinTable.name;
1935
1963
  const sourceColumn = attr.joinTable.joinColumn.name;
1964
+ if (!attr.joinTable.inverseJoinColumn) {
1965
+ continue;
1966
+ }
1936
1967
  const targetColumn = attr.joinTable.inverseJoinColumn.name;
1937
1968
  const hasRelationTable = await trx.schema.hasTable(relationJoinTable);
1938
1969
  if (!hasRelationTable) continue;
@@ -2102,6 +2133,9 @@ const debug = createDebug('strapi::migration::discard-drafts');
2102
2133
  if (!targetContentType?.options?.draftAndPublish) continue;
2103
2134
  const relationJoinTable = attr.joinTable.name;
2104
2135
  const sourceColumn = attr.joinTable.joinColumn.name;
2136
+ if (!attr.joinTable.inverseJoinColumn) {
2137
+ continue;
2138
+ }
2105
2139
  const targetColumn = attr.joinTable.inverseJoinColumn.name;
2106
2140
  if (!await ensureTableExists(trx, relationJoinTable)) continue;
2107
2141
  const relations = await trx(relationJoinTable).whereIn(sourceColumn, ids).select('id', sourceColumn, targetColumn);
@@ -2198,6 +2232,8 @@ const debug = createDebug('strapi::migration::discard-drafts');
2198
2232
  const publishedIds = Array.from(publishedToDraftMap.keys());
2199
2233
  // Process in batches to avoid MySQL query size limits and SQLite expression tree limits
2200
2234
  const publishedIdsChunks = chunkArray(publishedIds, getBatchSize(trx, 1000));
2235
+ const componentTargetDraftMapCache = new Map();
2236
+ const componentTargetReverseMapCache = new Map();
2201
2237
  for (const publishedIdsChunk of publishedIdsChunks){
2202
2238
  // Get component relations for published entries
2203
2239
  const componentRelations = await trx(joinTableName).select('*').whereIn(entityIdColumn, publishedIdsChunk);
@@ -2206,8 +2242,6 @@ const debug = createDebug('strapi::migration::discard-drafts');
2206
2242
  }
2207
2243
  const componentCloneCache = new Map();
2208
2244
  const clonedComponentPairsCache = new Map();
2209
- const componentTargetDraftMapCache = new Map();
2210
- const componentTargetReverseMapCache = new Map();
2211
2245
  const componentHierarchyCaches = {
2212
2246
  parentInstanceCache: new Map(),
2213
2247
  ancestorDpCache: new Map(),