@strapi/database 5.12.0 → 5.12.2

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 (321) hide show
  1. package/dist/connection.js +43 -0
  2. package/dist/connection.js.map +1 -0
  3. package/dist/connection.mjs +41 -0
  4. package/dist/connection.mjs.map +1 -0
  5. package/dist/dialects/dialect.js +54 -0
  6. package/dist/dialects/dialect.js.map +1 -0
  7. package/dist/dialects/dialect.mjs +52 -0
  8. package/dist/dialects/dialect.mjs.map +1 -0
  9. package/dist/dialects/index.js +44 -0
  10. package/dist/dialects/index.js.map +1 -0
  11. package/dist/dialects/index.mjs +42 -0
  12. package/dist/dialects/index.mjs.map +1 -0
  13. package/dist/dialects/mysql/constants.js +8 -0
  14. package/dist/dialects/mysql/constants.js.map +1 -0
  15. package/dist/dialects/mysql/constants.mjs +5 -0
  16. package/dist/dialects/mysql/constants.mjs.map +1 -0
  17. package/dist/dialects/mysql/database-inspector.js +35 -0
  18. package/dist/dialects/mysql/database-inspector.js.map +1 -0
  19. package/dist/dialects/mysql/database-inspector.mjs +33 -0
  20. package/dist/dialects/mysql/database-inspector.mjs.map +1 -0
  21. package/dist/dialects/mysql/index.js +75 -0
  22. package/dist/dialects/mysql/index.js.map +1 -0
  23. package/dist/dialects/mysql/index.mjs +73 -0
  24. package/dist/dialects/mysql/index.mjs.map +1 -0
  25. package/dist/dialects/mysql/schema-inspector.js +297 -0
  26. package/dist/dialects/mysql/schema-inspector.js.map +1 -0
  27. package/dist/dialects/mysql/schema-inspector.mjs +295 -0
  28. package/dist/dialects/mysql/schema-inspector.mjs.map +1 -0
  29. package/dist/dialects/postgresql/index.js +62 -0
  30. package/dist/dialects/postgresql/index.js.map +1 -0
  31. package/dist/dialects/postgresql/index.mjs +60 -0
  32. package/dist/dialects/postgresql/index.mjs.map +1 -0
  33. package/dist/dialects/postgresql/schema-inspector.js +316 -0
  34. package/dist/dialects/postgresql/schema-inspector.js.map +1 -0
  35. package/dist/dialects/postgresql/schema-inspector.mjs +314 -0
  36. package/dist/dialects/postgresql/schema-inspector.mjs.map +1 -0
  37. package/dist/dialects/sqlite/index.js +82 -0
  38. package/dist/dialects/sqlite/index.js.map +1 -0
  39. package/dist/dialects/sqlite/index.mjs +80 -0
  40. package/dist/dialects/sqlite/index.mjs.map +1 -0
  41. package/dist/dialects/sqlite/schema-inspector.js +211 -0
  42. package/dist/dialects/sqlite/schema-inspector.js.map +1 -0
  43. package/dist/dialects/sqlite/schema-inspector.mjs +209 -0
  44. package/dist/dialects/sqlite/schema-inspector.mjs.map +1 -0
  45. package/dist/entity-manager/entity-repository.js +139 -0
  46. package/dist/entity-manager/entity-repository.js.map +1 -0
  47. package/dist/entity-manager/entity-repository.mjs +137 -0
  48. package/dist/entity-manager/entity-repository.mjs.map +1 -0
  49. package/dist/entity-manager/index.js +1186 -0
  50. package/dist/entity-manager/index.js.map +1 -0
  51. package/dist/entity-manager/index.mjs +1184 -0
  52. package/dist/entity-manager/index.mjs.map +1 -0
  53. package/dist/entity-manager/morph-relations.js +73 -0
  54. package/dist/entity-manager/morph-relations.js.map +1 -0
  55. package/dist/entity-manager/morph-relations.mjs +69 -0
  56. package/dist/entity-manager/morph-relations.mjs.map +1 -0
  57. package/dist/entity-manager/regular-relations.js +247 -0
  58. package/dist/entity-manager/regular-relations.js.map +1 -0
  59. package/dist/entity-manager/regular-relations.mjs +242 -0
  60. package/dist/entity-manager/regular-relations.mjs.map +1 -0
  61. package/dist/entity-manager/relations-orderer.js +221 -0
  62. package/dist/entity-manager/relations-orderer.js.map +1 -0
  63. package/dist/entity-manager/relations-orderer.mjs +218 -0
  64. package/dist/entity-manager/relations-orderer.mjs.map +1 -0
  65. package/dist/errors/database.js +13 -0
  66. package/dist/errors/database.js.map +1 -0
  67. package/dist/errors/database.mjs +11 -0
  68. package/dist/errors/database.mjs.map +1 -0
  69. package/dist/errors/index.js +18 -0
  70. package/dist/errors/index.js.map +1 -0
  71. package/dist/errors/index.mjs +7 -0
  72. package/dist/errors/index.mjs.map +1 -0
  73. package/dist/errors/invalid-date.js +13 -0
  74. package/dist/errors/invalid-date.js.map +1 -0
  75. package/dist/errors/invalid-date.mjs +11 -0
  76. package/dist/errors/invalid-date.mjs.map +1 -0
  77. package/dist/errors/invalid-datetime.js +13 -0
  78. package/dist/errors/invalid-datetime.js.map +1 -0
  79. package/dist/errors/invalid-datetime.mjs +11 -0
  80. package/dist/errors/invalid-datetime.mjs.map +1 -0
  81. package/dist/errors/invalid-relation.js +13 -0
  82. package/dist/errors/invalid-relation.js.map +1 -0
  83. package/dist/errors/invalid-relation.mjs +11 -0
  84. package/dist/errors/invalid-relation.mjs.map +1 -0
  85. package/dist/errors/invalid-time.js +13 -0
  86. package/dist/errors/invalid-time.js.map +1 -0
  87. package/dist/errors/invalid-time.mjs +11 -0
  88. package/dist/errors/invalid-time.mjs.map +1 -0
  89. package/dist/errors/not-null.js +17 -0
  90. package/dist/errors/not-null.js.map +1 -0
  91. package/dist/errors/not-null.mjs +15 -0
  92. package/dist/errors/not-null.mjs.map +1 -0
  93. package/dist/fields/biginteger.js +9 -0
  94. package/dist/fields/biginteger.js.map +1 -0
  95. package/dist/fields/biginteger.mjs +7 -0
  96. package/dist/fields/biginteger.mjs.map +1 -0
  97. package/dist/fields/boolean.js +48 -0
  98. package/dist/fields/boolean.js.map +1 -0
  99. package/dist/fields/boolean.mjs +46 -0
  100. package/dist/fields/boolean.mjs.map +1 -0
  101. package/dist/fields/date.js +16 -0
  102. package/dist/fields/date.js.map +1 -0
  103. package/dist/fields/date.mjs +14 -0
  104. package/dist/fields/date.mjs.map +1 -0
  105. package/dist/fields/datetime.js +37 -0
  106. package/dist/fields/datetime.js.map +1 -0
  107. package/dist/fields/datetime.mjs +16 -0
  108. package/dist/fields/datetime.mjs.map +1 -0
  109. package/dist/fields/field.js +16 -0
  110. package/dist/fields/field.js.map +1 -0
  111. package/dist/fields/field.mjs +14 -0
  112. package/dist/fields/field.mjs.map +1 -0
  113. package/dist/fields/index.js +45 -0
  114. package/dist/fields/index.js.map +1 -0
  115. package/dist/fields/index.mjs +43 -0
  116. package/dist/fields/index.mjs.map +1 -0
  117. package/dist/fields/json.js +36 -0
  118. package/dist/fields/json.js.map +1 -0
  119. package/dist/fields/json.mjs +34 -0
  120. package/dist/fields/json.mjs.map +1 -0
  121. package/dist/fields/number.js +20 -0
  122. package/dist/fields/number.js.map +1 -0
  123. package/dist/fields/number.mjs +18 -0
  124. package/dist/fields/number.mjs.map +1 -0
  125. package/dist/fields/shared/parsers.js +91 -0
  126. package/dist/fields/shared/parsers.js.map +1 -0
  127. package/dist/fields/shared/parsers.mjs +68 -0
  128. package/dist/fields/shared/parsers.mjs.map +1 -0
  129. package/dist/fields/string.js +16 -0
  130. package/dist/fields/string.js.map +1 -0
  131. package/dist/fields/string.mjs +14 -0
  132. package/dist/fields/string.mjs.map +1 -0
  133. package/dist/fields/time.js +17 -0
  134. package/dist/fields/time.js.map +1 -0
  135. package/dist/fields/time.mjs +15 -0
  136. package/dist/fields/time.mjs.map +1 -0
  137. package/dist/fields/timestamp.js +37 -0
  138. package/dist/fields/timestamp.js.map +1 -0
  139. package/dist/fields/timestamp.mjs +16 -0
  140. package/dist/fields/timestamp.mjs.map +1 -0
  141. package/dist/index.js +33 -8569
  142. package/dist/index.js.map +1 -1
  143. package/dist/index.mjs +16 -8532
  144. package/dist/index.mjs.map +1 -1
  145. package/dist/lifecycles/index.js +73 -0
  146. package/dist/lifecycles/index.js.map +1 -0
  147. package/dist/lifecycles/index.mjs +71 -0
  148. package/dist/lifecycles/index.mjs.map +1 -0
  149. package/dist/lifecycles/subscribers/index.js +10 -0
  150. package/dist/lifecycles/subscribers/index.js.map +1 -0
  151. package/dist/lifecycles/subscribers/index.mjs +8 -0
  152. package/dist/lifecycles/subscribers/index.mjs.map +1 -0
  153. package/dist/lifecycles/subscribers/models-lifecycles.js +13 -0
  154. package/dist/lifecycles/subscribers/models-lifecycles.js.map +1 -0
  155. package/dist/lifecycles/subscribers/models-lifecycles.mjs +11 -0
  156. package/dist/lifecycles/subscribers/models-lifecycles.mjs.map +1 -0
  157. package/dist/lifecycles/subscribers/timestamps.js +55 -0
  158. package/dist/lifecycles/subscribers/timestamps.js.map +1 -0
  159. package/dist/lifecycles/subscribers/timestamps.mjs +53 -0
  160. package/dist/lifecycles/subscribers/timestamps.mjs.map +1 -0
  161. package/dist/metadata/index.js +24 -0
  162. package/dist/metadata/index.js.map +1 -0
  163. package/dist/metadata/index.mjs +16 -0
  164. package/dist/metadata/index.mjs.map +1 -0
  165. package/dist/metadata/metadata.js +100 -0
  166. package/dist/metadata/metadata.js.map +1 -0
  167. package/dist/metadata/metadata.mjs +98 -0
  168. package/dist/metadata/metadata.mjs.map +1 -0
  169. package/dist/metadata/relations.js +545 -0
  170. package/dist/metadata/relations.js.map +1 -0
  171. package/dist/metadata/relations.mjs +536 -0
  172. package/dist/metadata/relations.mjs.map +1 -0
  173. package/dist/migrations/common.js +8 -0
  174. package/dist/migrations/common.js.map +1 -0
  175. package/dist/migrations/common.mjs +6 -0
  176. package/dist/migrations/common.mjs.map +1 -0
  177. package/dist/migrations/index.js +39 -0
  178. package/dist/migrations/index.js.map +1 -0
  179. package/dist/migrations/index.mjs +37 -0
  180. package/dist/migrations/index.mjs.map +1 -0
  181. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.js +179 -0
  182. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.js.map +1 -0
  183. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.mjs +177 -0
  184. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.mjs.map +1 -0
  185. package/dist/migrations/internal-migrations/5.0.0-02-document-id.js +125 -0
  186. package/dist/migrations/internal-migrations/5.0.0-02-document-id.js.map +1 -0
  187. package/dist/migrations/internal-migrations/5.0.0-02-document-id.mjs +123 -0
  188. package/dist/migrations/internal-migrations/5.0.0-02-document-id.mjs.map +1 -0
  189. package/dist/migrations/internal-migrations/5.0.0-03-locale.js +41 -0
  190. package/dist/migrations/internal-migrations/5.0.0-03-locale.js.map +1 -0
  191. package/dist/migrations/internal-migrations/5.0.0-03-locale.mjs +39 -0
  192. package/dist/migrations/internal-migrations/5.0.0-03-locale.mjs.map +1 -0
  193. package/dist/migrations/internal-migrations/5.0.0-04-published-at.js +45 -0
  194. package/dist/migrations/internal-migrations/5.0.0-04-published-at.js.map +1 -0
  195. package/dist/migrations/internal-migrations/5.0.0-04-published-at.mjs +43 -0
  196. package/dist/migrations/internal-migrations/5.0.0-04-published-at.mjs.map +1 -0
  197. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.js +43 -0
  198. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.js.map +1 -0
  199. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.mjs +41 -0
  200. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.mjs.map +1 -0
  201. package/dist/migrations/internal-migrations/index.js +26 -0
  202. package/dist/migrations/internal-migrations/index.js.map +1 -0
  203. package/dist/migrations/internal-migrations/index.mjs +24 -0
  204. package/dist/migrations/internal-migrations/index.mjs.map +1 -0
  205. package/dist/migrations/internal.js +63 -0
  206. package/dist/migrations/internal.js.map +1 -0
  207. package/dist/migrations/internal.mjs +61 -0
  208. package/dist/migrations/internal.mjs.map +1 -0
  209. package/dist/migrations/logger.js +24 -0
  210. package/dist/migrations/logger.js.map +1 -0
  211. package/dist/migrations/logger.mjs +22 -0
  212. package/dist/migrations/logger.mjs.map +1 -0
  213. package/dist/migrations/storage.js +39 -0
  214. package/dist/migrations/storage.js.map +1 -0
  215. package/dist/migrations/storage.mjs +37 -0
  216. package/dist/migrations/storage.mjs.map +1 -0
  217. package/dist/migrations/users.js +87 -0
  218. package/dist/migrations/users.js.map +1 -0
  219. package/dist/migrations/users.mjs +85 -0
  220. package/dist/migrations/users.mjs.map +1 -0
  221. package/dist/query/helpers/join.js +127 -0
  222. package/dist/query/helpers/join.js.map +1 -0
  223. package/dist/query/helpers/join.mjs +122 -0
  224. package/dist/query/helpers/join.mjs.map +1 -0
  225. package/dist/query/helpers/order-by.js +167 -0
  226. package/dist/query/helpers/order-by.js.map +1 -0
  227. package/dist/query/helpers/order-by.mjs +163 -0
  228. package/dist/query/helpers/order-by.mjs.map +1 -0
  229. package/dist/query/helpers/populate/apply.js +592 -0
  230. package/dist/query/helpers/populate/apply.js.map +1 -0
  231. package/dist/query/helpers/populate/apply.mjs +590 -0
  232. package/dist/query/helpers/populate/apply.mjs.map +1 -0
  233. package/dist/query/helpers/populate/process.js +92 -0
  234. package/dist/query/helpers/populate/process.js.map +1 -0
  235. package/dist/query/helpers/populate/process.mjs +90 -0
  236. package/dist/query/helpers/populate/process.mjs.map +1 -0
  237. package/dist/query/helpers/search.js +67 -0
  238. package/dist/query/helpers/search.js.map +1 -0
  239. package/dist/query/helpers/search.mjs +65 -0
  240. package/dist/query/helpers/search.mjs.map +1 -0
  241. package/dist/query/helpers/streams/readable.js +131 -0
  242. package/dist/query/helpers/streams/readable.js.map +1 -0
  243. package/dist/query/helpers/streams/readable.mjs +129 -0
  244. package/dist/query/helpers/streams/readable.mjs.map +1 -0
  245. package/dist/query/helpers/transform.js +77 -0
  246. package/dist/query/helpers/transform.js.map +1 -0
  247. package/dist/query/helpers/transform.mjs +73 -0
  248. package/dist/query/helpers/transform.mjs.map +1 -0
  249. package/dist/query/helpers/where.js +372 -0
  250. package/dist/query/helpers/where.js.map +1 -0
  251. package/dist/query/helpers/where.mjs +369 -0
  252. package/dist/query/helpers/where.mjs.map +1 -0
  253. package/dist/query/query-builder.js +507 -0
  254. package/dist/query/query-builder.js.map +1 -0
  255. package/dist/query/query-builder.mjs +505 -0
  256. package/dist/query/query-builder.mjs.map +1 -0
  257. package/dist/repairs/index.js +13 -0
  258. package/dist/repairs/index.js.map +1 -0
  259. package/dist/repairs/index.mjs +11 -0
  260. package/dist/repairs/index.mjs.map +1 -0
  261. package/dist/repairs/operations/remove-orphan-morph-types.js +54 -0
  262. package/dist/repairs/operations/remove-orphan-morph-types.js.map +1 -0
  263. package/dist/repairs/operations/remove-orphan-morph-types.mjs +52 -0
  264. package/dist/repairs/operations/remove-orphan-morph-types.mjs.map +1 -0
  265. package/dist/schema/builder.js +354 -0
  266. package/dist/schema/builder.js.map +1 -0
  267. package/dist/schema/builder.mjs +352 -0
  268. package/dist/schema/builder.mjs.map +1 -0
  269. package/dist/schema/diff.js +379 -0
  270. package/dist/schema/diff.js.map +1 -0
  271. package/dist/schema/diff.mjs +377 -0
  272. package/dist/schema/diff.mjs.map +1 -0
  273. package/dist/schema/index.js +93 -0
  274. package/dist/schema/index.js.map +1 -0
  275. package/dist/schema/index.mjs +91 -0
  276. package/dist/schema/index.mjs.map +1 -0
  277. package/dist/schema/schema.js +266 -0
  278. package/dist/schema/schema.js.map +1 -0
  279. package/dist/schema/schema.mjs +264 -0
  280. package/dist/schema/schema.mjs.map +1 -0
  281. package/dist/schema/storage.js +58 -0
  282. package/dist/schema/storage.js.map +1 -0
  283. package/dist/schema/storage.mjs +56 -0
  284. package/dist/schema/storage.mjs.map +1 -0
  285. package/dist/transaction-context.js +65 -0
  286. package/dist/transaction-context.js.map +1 -0
  287. package/dist/transaction-context.mjs +63 -0
  288. package/dist/transaction-context.mjs.map +1 -0
  289. package/dist/utils/async-curry.js +19 -0
  290. package/dist/utils/async-curry.js.map +1 -0
  291. package/dist/utils/async-curry.mjs +17 -0
  292. package/dist/utils/async-curry.mjs.map +1 -0
  293. package/dist/utils/identifiers/hash.js +30 -0
  294. package/dist/utils/identifiers/hash.js.map +1 -0
  295. package/dist/utils/identifiers/hash.mjs +28 -0
  296. package/dist/utils/identifiers/hash.mjs.map +1 -0
  297. package/dist/utils/identifiers/index.js +414 -0
  298. package/dist/utils/identifiers/index.js.map +1 -0
  299. package/dist/utils/identifiers/index.mjs +411 -0
  300. package/dist/utils/identifiers/index.mjs.map +1 -0
  301. package/dist/utils/knex.js +21 -0
  302. package/dist/utils/knex.js.map +1 -0
  303. package/dist/utils/knex.mjs +18 -0
  304. package/dist/utils/knex.mjs.map +1 -0
  305. package/dist/utils/types.js +51 -0
  306. package/dist/utils/types.js.map +1 -0
  307. package/dist/utils/types.mjs +44 -0
  308. package/dist/utils/types.mjs.map +1 -0
  309. package/dist/validations/index.js +12 -0
  310. package/dist/validations/index.js.map +1 -0
  311. package/dist/validations/index.mjs +10 -0
  312. package/dist/validations/index.mjs.map +1 -0
  313. package/dist/validations/relations/bidirectional.js +64 -0
  314. package/dist/validations/relations/bidirectional.js.map +1 -0
  315. package/dist/validations/relations/bidirectional.mjs +62 -0
  316. package/dist/validations/relations/bidirectional.mjs.map +1 -0
  317. package/dist/validations/relations/index.js +13 -0
  318. package/dist/validations/relations/index.js.map +1 -0
  319. package/dist/validations/relations/index.mjs +11 -0
  320. package/dist/validations/relations/index.mjs.map +1 -0
  321. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-orphan-morph-types.js","sources":["../../../src/repairs/operations/remove-orphan-morph-types.ts"],"sourcesContent":["import type { Database } from '../..';\nimport type { Attribute, MorphRelationalAttribute } from '../../types';\n\nexport interface RemoveOrphanMorphTypeOptions {\n pivot: string;\n}\n\nconst isMorphRelationWithPivot = (\n attribute: Attribute,\n pivot: string\n): attribute is MorphRelationalAttribute => {\n return (\n attribute.type === 'relation' &&\n 'relation' in attribute &&\n 'joinTable' in attribute &&\n 'name' in attribute.joinTable &&\n 'pivotColumns' in attribute.joinTable &&\n attribute.joinTable.pivotColumns.includes(pivot)\n );\n};\n\nconst filterMorphRelationalAttributes = (\n attributes: Record<string, Attribute>,\n pivot: string\n): MorphRelationalAttribute[] => {\n return Object.values(attributes).filter((attribute): attribute is MorphRelationalAttribute =>\n isMorphRelationWithPivot(attribute, pivot)\n );\n};\n\n/**\n * Removes morph relation data with invalid or non-existent morph type.\n *\n * This function iterates over the database metadata to identify morph relationships\n * (relations with a `joinTable` containing the specified pivot column) and removes\n * any entries in the relation's join table where the morph type is invalid.\n *\n * Note: This function does not check for orphaned IDs, only orphaned morph types.\n *\n * @param db - The database object containing metadata and a Knex connection.\n * @param options.pivot - The name of the column in the join table representing the morph type.\n */\nexport const removeOrphanMorphType = async (\n db: Database,\n { pivot }: RemoveOrphanMorphTypeOptions\n) => {\n db.logger.debug(`Removing orphaned morph type: ${JSON.stringify(pivot)}`);\n\n const mdValues = db.metadata.values();\n for (const model of mdValues) {\n const attributes = filterMorphRelationalAttributes(model.attributes || {}, pivot);\n\n for (const attribute of attributes) {\n const joinTableName = attribute.joinTable.name;\n\n // Query distinct morph types from the join table\n const morphTypes = await db.connection(joinTableName).distinct(pivot).pluck(pivot);\n\n for (const morphType of morphTypes) {\n // Check if metadata for the morph type exists\n const deleteComponentType = await (async () => {\n try {\n return !db.metadata.get(morphType); // If no metadata found, mark for deletion\n } catch {\n db.logger.debug(\n `Metadata for morph type \"${morphType}\" in table \"${joinTableName}\" not found`\n );\n return true; // Return true to delete if metadata is missing\n }\n })();\n\n if (deleteComponentType) {\n db.logger.debug(\n `Removing invalid morph type \"${morphType}\" from table \"${joinTableName}\".`\n );\n try {\n await db.connection(joinTableName).where(pivot, morphType).del();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n db.logger.error(\n `Failed to remove invalid morph type \"${morphType}\" from table \"${joinTableName}\": ${errorMessage}`\n );\n }\n }\n }\n }\n }\n};\n"],"names":["isMorphRelationWithPivot","attribute","pivot","type","joinTable","pivotColumns","includes","filterMorphRelationalAttributes","attributes","Object","values","filter","removeOrphanMorphType","db","logger","debug","JSON","stringify","mdValues","metadata","model","joinTableName","name","morphTypes","connection","distinct","pluck","morphType","deleteComponentType","get","where","del","error","errorMessage","Error","message","String"],"mappings":";;AAOA,MAAMA,wBAAAA,GAA2B,CAC/BC,SACAC,EAAAA,KAAAA,GAAAA;IAEA,OACED,SAAAA,CAAUE,IAAI,KAAK,UAAA,IACnB,cAAcF,SACd,IAAA,WAAA,IAAeA,SACf,IAAA,MAAA,IAAUA,SAAUG,CAAAA,SAAS,IAC7B,cAAkBH,IAAAA,SAAAA,CAAUG,SAAS,IACrCH,SAAAA,CAAUG,SAAS,CAACC,YAAY,CAACC,QAAQ,CAACJ,KAAAA,CAAAA;AAE9C,CAAA;AAEA,MAAMK,+BAAAA,GAAkC,CACtCC,UACAN,EAAAA,KAAAA,GAAAA;IAEA,OAAOO,MAAAA,CAAOC,MAAM,CAACF,UAAAA,CAAAA,CAAYG,MAAM,CAAC,CAACV,SACvCD,GAAAA,wBAAAA,CAAyBC,SAAWC,EAAAA,KAAAA,CAAAA,CAAAA;AAExC,CAAA;AAEA;;;;;;;;;;;AAWC,IACYU,MAAAA,qBAAAA,GAAwB,OACnCC,EACA,EAAA,EAAEX,KAAK,EAAgC,GAAA;IAEvCW,EAAGC,CAAAA,MAAM,CAACC,KAAK,CAAC,CAAC,8BAA8B,EAAEC,IAAKC,CAAAA,SAAS,CAACf,KAAAA,CAAAA,CAAO,CAAC,CAAA;AAExE,IAAA,MAAMgB,QAAWL,GAAAA,EAAAA,CAAGM,QAAQ,CAACT,MAAM,EAAA;IACnC,KAAK,MAAMU,SAASF,QAAU,CAAA;AAC5B,QAAA,MAAMV,aAAaD,+BAAgCa,CAAAA,KAAAA,CAAMZ,UAAU,IAAI,EAAIN,EAAAA,KAAAA,CAAAA;QAE3E,KAAK,MAAMD,aAAaO,UAAY,CAAA;AAClC,YAAA,MAAMa,aAAgBpB,GAAAA,SAAAA,CAAUG,SAAS,CAACkB,IAAI;;YAG9C,MAAMC,UAAAA,GAAa,MAAMV,EAAAA,CAAGW,UAAU,CAACH,eAAeI,QAAQ,CAACvB,KAAOwB,CAAAA,CAAAA,KAAK,CAACxB,KAAAA,CAAAA;YAE5E,KAAK,MAAMyB,aAAaJ,UAAY,CAAA;;gBAElC,MAAMK,mBAAAA,GAAsB,MAAO,CAAA,UAAA;oBACjC,IAAI;AACF,wBAAA,OAAO,CAACf,EAAGM,CAAAA,QAAQ,CAACU,GAAG,CAACF;AAC1B,qBAAA,CAAE,OAAM;AACNd,wBAAAA,EAAAA,CAAGC,MAAM,CAACC,KAAK,CACb,CAAC,yBAAyB,EAAEY,SAAAA,CAAU,YAAY,EAAEN,aAAc,CAAA,WAAW,CAAC,CAAA;AAEhF,wBAAA,OAAO;AACT;iBACF,GAAA;AAEA,gBAAA,IAAIO,mBAAqB,EAAA;AACvBf,oBAAAA,EAAAA,CAAGC,MAAM,CAACC,KAAK,CACb,CAAC,6BAA6B,EAAEY,SAAAA,CAAU,cAAc,EAAEN,aAAc,CAAA,EAAE,CAAC,CAAA;oBAE7E,IAAI;wBACF,MAAMR,EAAAA,CAAGW,UAAU,CAACH,aAAAA,CAAAA,CAAeS,KAAK,CAAC5B,KAAAA,EAAOyB,WAAWI,GAAG,EAAA;AAChE,qBAAA,CAAE,OAAOC,KAAO,EAAA;AACd,wBAAA,MAAMC,eAAeD,KAAiBE,YAAAA,KAAAA,GAAQF,KAAMG,CAAAA,OAAO,GAAGC,MAAOJ,CAAAA,KAAAA,CAAAA;AACrEnB,wBAAAA,EAAAA,CAAGC,MAAM,CAACkB,KAAK,CACb,CAAC,qCAAqC,EAAEL,SAAU,CAAA,cAAc,EAAEN,aAAAA,CAAc,GAAG,EAAEY,aAAa,CAAC,CAAA;AAEvG;AACF;AACF;AACF;AACF;AACF;;;;"}
@@ -0,0 +1,52 @@
1
+ const isMorphRelationWithPivot = (attribute, pivot)=>{
2
+ return attribute.type === 'relation' && 'relation' in attribute && 'joinTable' in attribute && 'name' in attribute.joinTable && 'pivotColumns' in attribute.joinTable && attribute.joinTable.pivotColumns.includes(pivot);
3
+ };
4
+ const filterMorphRelationalAttributes = (attributes, pivot)=>{
5
+ return Object.values(attributes).filter((attribute)=>isMorphRelationWithPivot(attribute, pivot));
6
+ };
7
+ /**
8
+ * Removes morph relation data with invalid or non-existent morph type.
9
+ *
10
+ * This function iterates over the database metadata to identify morph relationships
11
+ * (relations with a `joinTable` containing the specified pivot column) and removes
12
+ * any entries in the relation's join table where the morph type is invalid.
13
+ *
14
+ * Note: This function does not check for orphaned IDs, only orphaned morph types.
15
+ *
16
+ * @param db - The database object containing metadata and a Knex connection.
17
+ * @param options.pivot - The name of the column in the join table representing the morph type.
18
+ */ const removeOrphanMorphType = async (db, { pivot })=>{
19
+ db.logger.debug(`Removing orphaned morph type: ${JSON.stringify(pivot)}`);
20
+ const mdValues = db.metadata.values();
21
+ for (const model of mdValues){
22
+ const attributes = filterMorphRelationalAttributes(model.attributes || {}, pivot);
23
+ for (const attribute of attributes){
24
+ const joinTableName = attribute.joinTable.name;
25
+ // Query distinct morph types from the join table
26
+ const morphTypes = await db.connection(joinTableName).distinct(pivot).pluck(pivot);
27
+ for (const morphType of morphTypes){
28
+ // Check if metadata for the morph type exists
29
+ const deleteComponentType = await (async ()=>{
30
+ try {
31
+ return !db.metadata.get(morphType); // If no metadata found, mark for deletion
32
+ } catch {
33
+ db.logger.debug(`Metadata for morph type "${morphType}" in table "${joinTableName}" not found`);
34
+ return true; // Return true to delete if metadata is missing
35
+ }
36
+ })();
37
+ if (deleteComponentType) {
38
+ db.logger.debug(`Removing invalid morph type "${morphType}" from table "${joinTableName}".`);
39
+ try {
40
+ await db.connection(joinTableName).where(pivot, morphType).del();
41
+ } catch (error) {
42
+ const errorMessage = error instanceof Error ? error.message : String(error);
43
+ db.logger.error(`Failed to remove invalid morph type "${morphType}" from table "${joinTableName}": ${errorMessage}`);
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ };
50
+
51
+ export { removeOrphanMorphType };
52
+ //# sourceMappingURL=remove-orphan-morph-types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-orphan-morph-types.mjs","sources":["../../../src/repairs/operations/remove-orphan-morph-types.ts"],"sourcesContent":["import type { Database } from '../..';\nimport type { Attribute, MorphRelationalAttribute } from '../../types';\n\nexport interface RemoveOrphanMorphTypeOptions {\n pivot: string;\n}\n\nconst isMorphRelationWithPivot = (\n attribute: Attribute,\n pivot: string\n): attribute is MorphRelationalAttribute => {\n return (\n attribute.type === 'relation' &&\n 'relation' in attribute &&\n 'joinTable' in attribute &&\n 'name' in attribute.joinTable &&\n 'pivotColumns' in attribute.joinTable &&\n attribute.joinTable.pivotColumns.includes(pivot)\n );\n};\n\nconst filterMorphRelationalAttributes = (\n attributes: Record<string, Attribute>,\n pivot: string\n): MorphRelationalAttribute[] => {\n return Object.values(attributes).filter((attribute): attribute is MorphRelationalAttribute =>\n isMorphRelationWithPivot(attribute, pivot)\n );\n};\n\n/**\n * Removes morph relation data with invalid or non-existent morph type.\n *\n * This function iterates over the database metadata to identify morph relationships\n * (relations with a `joinTable` containing the specified pivot column) and removes\n * any entries in the relation's join table where the morph type is invalid.\n *\n * Note: This function does not check for orphaned IDs, only orphaned morph types.\n *\n * @param db - The database object containing metadata and a Knex connection.\n * @param options.pivot - The name of the column in the join table representing the morph type.\n */\nexport const removeOrphanMorphType = async (\n db: Database,\n { pivot }: RemoveOrphanMorphTypeOptions\n) => {\n db.logger.debug(`Removing orphaned morph type: ${JSON.stringify(pivot)}`);\n\n const mdValues = db.metadata.values();\n for (const model of mdValues) {\n const attributes = filterMorphRelationalAttributes(model.attributes || {}, pivot);\n\n for (const attribute of attributes) {\n const joinTableName = attribute.joinTable.name;\n\n // Query distinct morph types from the join table\n const morphTypes = await db.connection(joinTableName).distinct(pivot).pluck(pivot);\n\n for (const morphType of morphTypes) {\n // Check if metadata for the morph type exists\n const deleteComponentType = await (async () => {\n try {\n return !db.metadata.get(morphType); // If no metadata found, mark for deletion\n } catch {\n db.logger.debug(\n `Metadata for morph type \"${morphType}\" in table \"${joinTableName}\" not found`\n );\n return true; // Return true to delete if metadata is missing\n }\n })();\n\n if (deleteComponentType) {\n db.logger.debug(\n `Removing invalid morph type \"${morphType}\" from table \"${joinTableName}\".`\n );\n try {\n await db.connection(joinTableName).where(pivot, morphType).del();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n db.logger.error(\n `Failed to remove invalid morph type \"${morphType}\" from table \"${joinTableName}\": ${errorMessage}`\n );\n }\n }\n }\n }\n }\n};\n"],"names":["isMorphRelationWithPivot","attribute","pivot","type","joinTable","pivotColumns","includes","filterMorphRelationalAttributes","attributes","Object","values","filter","removeOrphanMorphType","db","logger","debug","JSON","stringify","mdValues","metadata","model","joinTableName","name","morphTypes","connection","distinct","pluck","morphType","deleteComponentType","get","where","del","error","errorMessage","Error","message","String"],"mappings":"AAOA,MAAMA,wBAAAA,GAA2B,CAC/BC,SACAC,EAAAA,KAAAA,GAAAA;IAEA,OACED,SAAAA,CAAUE,IAAI,KAAK,UAAA,IACnB,cAAcF,SACd,IAAA,WAAA,IAAeA,SACf,IAAA,MAAA,IAAUA,SAAUG,CAAAA,SAAS,IAC7B,cAAkBH,IAAAA,SAAAA,CAAUG,SAAS,IACrCH,SAAAA,CAAUG,SAAS,CAACC,YAAY,CAACC,QAAQ,CAACJ,KAAAA,CAAAA;AAE9C,CAAA;AAEA,MAAMK,+BAAAA,GAAkC,CACtCC,UACAN,EAAAA,KAAAA,GAAAA;IAEA,OAAOO,MAAAA,CAAOC,MAAM,CAACF,UAAAA,CAAAA,CAAYG,MAAM,CAAC,CAACV,SACvCD,GAAAA,wBAAAA,CAAyBC,SAAWC,EAAAA,KAAAA,CAAAA,CAAAA;AAExC,CAAA;AAEA;;;;;;;;;;;AAWC,IACYU,MAAAA,qBAAAA,GAAwB,OACnCC,EACA,EAAA,EAAEX,KAAK,EAAgC,GAAA;IAEvCW,EAAGC,CAAAA,MAAM,CAACC,KAAK,CAAC,CAAC,8BAA8B,EAAEC,IAAKC,CAAAA,SAAS,CAACf,KAAAA,CAAAA,CAAO,CAAC,CAAA;AAExE,IAAA,MAAMgB,QAAWL,GAAAA,EAAAA,CAAGM,QAAQ,CAACT,MAAM,EAAA;IACnC,KAAK,MAAMU,SAASF,QAAU,CAAA;AAC5B,QAAA,MAAMV,aAAaD,+BAAgCa,CAAAA,KAAAA,CAAMZ,UAAU,IAAI,EAAIN,EAAAA,KAAAA,CAAAA;QAE3E,KAAK,MAAMD,aAAaO,UAAY,CAAA;AAClC,YAAA,MAAMa,aAAgBpB,GAAAA,SAAAA,CAAUG,SAAS,CAACkB,IAAI;;YAG9C,MAAMC,UAAAA,GAAa,MAAMV,EAAAA,CAAGW,UAAU,CAACH,eAAeI,QAAQ,CAACvB,KAAOwB,CAAAA,CAAAA,KAAK,CAACxB,KAAAA,CAAAA;YAE5E,KAAK,MAAMyB,aAAaJ,UAAY,CAAA;;gBAElC,MAAMK,mBAAAA,GAAsB,MAAO,CAAA,UAAA;oBACjC,IAAI;AACF,wBAAA,OAAO,CAACf,EAAGM,CAAAA,QAAQ,CAACU,GAAG,CAACF;AAC1B,qBAAA,CAAE,OAAM;AACNd,wBAAAA,EAAAA,CAAGC,MAAM,CAACC,KAAK,CACb,CAAC,yBAAyB,EAAEY,SAAAA,CAAU,YAAY,EAAEN,aAAc,CAAA,WAAW,CAAC,CAAA;AAEhF,wBAAA,OAAO;AACT;iBACF,GAAA;AAEA,gBAAA,IAAIO,mBAAqB,EAAA;AACvBf,oBAAAA,EAAAA,CAAGC,MAAM,CAACC,KAAK,CACb,CAAC,6BAA6B,EAAEY,SAAAA,CAAU,cAAc,EAAEN,aAAc,CAAA,EAAE,CAAC,CAAA;oBAE7E,IAAI;wBACF,MAAMR,EAAAA,CAAGW,UAAU,CAACH,aAAAA,CAAAA,CAAeS,KAAK,CAAC5B,KAAAA,EAAOyB,WAAWI,GAAG,EAAA;AAChE,qBAAA,CAAE,OAAOC,KAAO,EAAA;AACd,wBAAA,MAAMC,eAAeD,KAAiBE,YAAAA,KAAAA,GAAQF,KAAMG,CAAAA,OAAO,GAAGC,MAAOJ,CAAAA,KAAAA,CAAAA;AACrEnB,wBAAAA,EAAAA,CAAGC,MAAM,CAACkB,KAAK,CACb,CAAC,qCAAqC,EAAEL,SAAU,CAAA,cAAc,EAAEN,aAAAA,CAAc,GAAG,EAAEY,aAAa,CAAC,CAAA;AAEvG;AACF;AACF;AACF;AACF;AACF;;;;"}
@@ -0,0 +1,354 @@
1
+ 'use strict';
2
+
3
+ var _ = require('lodash/fp');
4
+ var createDebug = require('debug');
5
+
6
+ const debug = createDebug('strapi::database');
7
+ var createSchemaBuilder = ((db)=>{
8
+ const helpers = createHelpers(db);
9
+ return {
10
+ /**
11
+ * Returns a knex schema builder instance
12
+ * @param {string} table - table name
13
+ */ getSchemaBuilder (trx) {
14
+ return db.getSchemaConnection(trx);
15
+ },
16
+ /**
17
+ * Creates schema in DB
18
+ */ async createSchema (schema) {
19
+ await db.connection.transaction(async (trx)=>{
20
+ await this.createTables(schema.tables, trx);
21
+ });
22
+ },
23
+ /**
24
+ * Creates a list of tables in a schema
25
+ * @param {KnexInstance} trx
26
+ * @param {Table[]} tables
27
+ */ async createTables (tables, trx) {
28
+ for (const table of tables){
29
+ debug(`Creating table: ${table.name}`);
30
+ const schemaBuilder = this.getSchemaBuilder(trx);
31
+ await helpers.createTable(schemaBuilder, table);
32
+ }
33
+ // create FKs once all the tables exist
34
+ for (const table of tables){
35
+ debug(`Creating table foreign keys: ${table.name}`);
36
+ const schemaBuilder = this.getSchemaBuilder(trx);
37
+ await helpers.createTableForeignKeys(schemaBuilder, table);
38
+ }
39
+ },
40
+ /**
41
+ * Drops schema from DB
42
+ */ async dropSchema (schema, { dropDatabase = false } = {}) {
43
+ if (dropDatabase) {
44
+ // TODO: drop database & return as it will drop everything
45
+ return;
46
+ }
47
+ await db.connection.transaction(async (trx)=>{
48
+ for (const table of schema.tables.reverse()){
49
+ const schemaBuilder = this.getSchemaBuilder(trx);
50
+ await helpers.dropTable(schemaBuilder, table);
51
+ }
52
+ });
53
+ },
54
+ /**
55
+ * Applies a schema diff update in the DB
56
+ * @param {*} schemaDiff
57
+ */ // TODO: implement force option to disable removal in DB
58
+ async updateSchema (schemaDiff) {
59
+ const forceMigration = db.config.settings?.forceMigration;
60
+ await db.dialect.startSchemaUpdate();
61
+ // Pre-fetch metadata for all updated tables
62
+ const existingMetadata = {};
63
+ for (const table of schemaDiff.tables.updated){
64
+ existingMetadata[table.name] = {
65
+ indexes: await db.dialect.schemaInspector.getIndexes(table.name),
66
+ foreignKeys: await db.dialect.schemaInspector.getForeignKeys(table.name)
67
+ };
68
+ }
69
+ await db.connection.transaction(async (trx)=>{
70
+ await this.createTables(schemaDiff.tables.added, trx);
71
+ if (forceMigration) {
72
+ // drop all delete table foreign keys then delete the tables
73
+ for (const table of schemaDiff.tables.removed){
74
+ debug(`Removing table foreign keys: ${table.name}`);
75
+ const schemaBuilder = this.getSchemaBuilder(trx);
76
+ await helpers.dropTableForeignKeys(schemaBuilder, table);
77
+ }
78
+ for (const table of schemaDiff.tables.removed){
79
+ debug(`Removing table: ${table.name}`);
80
+ const schemaBuilder = this.getSchemaBuilder(trx);
81
+ await helpers.dropTable(schemaBuilder, table);
82
+ }
83
+ }
84
+ for (const table of schemaDiff.tables.updated){
85
+ debug(`Updating table: ${table.name}`);
86
+ // alter table
87
+ const schemaBuilder = this.getSchemaBuilder(trx);
88
+ const { indexes, foreignKeys } = existingMetadata[table.name];
89
+ await helpers.alterTable(schemaBuilder, table, {
90
+ indexes,
91
+ foreignKeys
92
+ });
93
+ }
94
+ });
95
+ await db.dialect.endSchemaUpdate();
96
+ }
97
+ };
98
+ });
99
+ const createHelpers = (db)=>{
100
+ /**
101
+ * Creates a foreign key on a table
102
+ */ const createForeignKey = (tableBuilder, foreignKey)=>{
103
+ const { name, columns, referencedColumns, referencedTable, onDelete, onUpdate } = foreignKey;
104
+ const constraint = tableBuilder.foreign(columns, name).references(referencedColumns).inTable(db.getSchemaName() ? `${db.getSchemaName()}.${referencedTable}` : referencedTable);
105
+ if (onDelete) {
106
+ constraint.onDelete(onDelete);
107
+ }
108
+ if (onUpdate) {
109
+ constraint.onUpdate(onUpdate);
110
+ }
111
+ };
112
+ /**
113
+ * Drops a foreign key from a table
114
+ */ const dropForeignKey = (tableBuilder, foreignKey, existingForeignKeys)=>{
115
+ const { name, columns } = foreignKey;
116
+ // Check if the index exists in existingIndexes, and return early if it doesn't
117
+ if (existingForeignKeys && !existingForeignKeys.some((existingIndex)=>existingIndex?.name === name)) {
118
+ debug(`Foreign Key ${name} not found in existing foreign keys. Skipping drop.`);
119
+ return;
120
+ }
121
+ tableBuilder.dropForeign(columns, name);
122
+ };
123
+ /**
124
+ * Creates an index on a table
125
+ */ const createIndex = (tableBuilder, index)=>{
126
+ const { type, columns, name } = index;
127
+ switch(type){
128
+ case 'primary':
129
+ {
130
+ return tableBuilder.primary(columns, {
131
+ constraintName: name
132
+ });
133
+ }
134
+ case 'unique':
135
+ {
136
+ return tableBuilder.unique(columns, {
137
+ indexName: name
138
+ });
139
+ }
140
+ default:
141
+ {
142
+ return tableBuilder.index(columns, name, type);
143
+ }
144
+ }
145
+ };
146
+ /**
147
+ * Drops an index from table
148
+ * @param {Knex.TableBuilder} tableBuilder
149
+ * @param {Index} index
150
+ */ const dropIndex = (tableBuilder, index, existingIndexes)=>{
151
+ if (!db.config.settings?.forceMigration) {
152
+ return;
153
+ }
154
+ const { type, columns, name } = index;
155
+ // Check if the index exists in existingIndexes, and return early if it doesn't
156
+ if (existingIndexes && !existingIndexes.some((existingIndex)=>existingIndex?.name === name)) {
157
+ debug(`Index ${index.name} not found in existingIndexes. Skipping drop.`);
158
+ return;
159
+ }
160
+ switch(type){
161
+ case 'primary':
162
+ {
163
+ return tableBuilder.dropPrimary(name);
164
+ }
165
+ case 'unique':
166
+ {
167
+ return tableBuilder.dropUnique(columns, name);
168
+ }
169
+ default:
170
+ {
171
+ return tableBuilder.dropIndex(columns, name);
172
+ }
173
+ }
174
+ };
175
+ /**
176
+ * Creates a column in a table
177
+ */ const createColumn = (tableBuilder, column)=>{
178
+ const { type, name, args = [], defaultTo, unsigned, notNullable } = column;
179
+ const col = tableBuilder[type](name, ...args);
180
+ if (unsigned === true) {
181
+ col.unsigned();
182
+ }
183
+ if (!_.isNil(defaultTo)) {
184
+ const [value, opts] = _.castArray(defaultTo);
185
+ if (_.prop('isRaw', opts)) {
186
+ col.defaultTo(db.connection.raw(value), _.omit('isRaw', opts));
187
+ } else {
188
+ col.defaultTo(value, opts);
189
+ }
190
+ }
191
+ if (notNullable === true) {
192
+ col.notNullable();
193
+ } else {
194
+ col.nullable();
195
+ }
196
+ return col;
197
+ };
198
+ /**
199
+ * Drops a column from a table
200
+ */ const dropColumn = (tableBuilder, column)=>{
201
+ if (!db.config.settings?.forceMigration) {
202
+ return;
203
+ }
204
+ return tableBuilder.dropColumn(column.name);
205
+ };
206
+ /**
207
+ * Creates a table in a database
208
+ */ const createTable = async (schemaBuilder, table)=>{
209
+ await schemaBuilder.createTable(table.name, (tableBuilder)=>{
210
+ // columns
211
+ (table.columns || []).forEach((column)=>createColumn(tableBuilder, column));
212
+ // indexes
213
+ (table.indexes || []).forEach((index)=>createIndex(tableBuilder, index));
214
+ // foreign keys
215
+ if (!db.dialect.canAlterConstraints()) {
216
+ (table.foreignKeys || []).forEach((foreignKey)=>createForeignKey(tableBuilder, foreignKey));
217
+ }
218
+ });
219
+ };
220
+ /**
221
+ * Alters a database table by applying a set of schema changes including updates to columns, indexes, and foreign keys.
222
+ * This function ensures proper ordering of operations to avoid conflicts (e.g., foreign key errors) and handles
223
+ * MySQL-specific quirks where dropping a foreign key can implicitly drop an associated index.
224
+ *
225
+ * @param {Knex.SchemaBuilder} schemaBuilder - Knex SchemaBuilder instance to perform schema operations.
226
+ * @param {TableDiff['diff']} table - A diff object representing the schema changes to be applied to the table.
227
+ * @param {{ indexes: Index[]; foreignKeys: ForeignKey[] }} existingMetadata - Metadata about existing indexes and
228
+ * foreign keys in the table. Used to ensure safe operations and avoid unnecessary modifications.
229
+ * - indexes: Array of existing index definitions.
230
+ * - foreignKeys: Array of existing foreign key definitions.
231
+ */ const alterTable = async (schemaBuilder, table, existingMetadata = {
232
+ indexes: [],
233
+ foreignKeys: []
234
+ })=>{
235
+ let existingIndexes = [
236
+ ...existingMetadata.indexes
237
+ ];
238
+ const existingForeignKeys = [
239
+ ...existingMetadata.foreignKeys
240
+ ];
241
+ // Track dropped foreign keys
242
+ const droppedForeignKeyNames = [];
243
+ await schemaBuilder.alterTable(table.name, async (tableBuilder)=>{
244
+ // Drop foreign keys first to avoid foreign key errors in the following steps
245
+ for (const removedForeignKey of table.foreignKeys.removed){
246
+ debug(`Dropping foreign key ${removedForeignKey.name} on ${table.name}`);
247
+ dropForeignKey(tableBuilder, removedForeignKey, existingForeignKeys);
248
+ droppedForeignKeyNames.push(removedForeignKey.name);
249
+ }
250
+ for (const updatedForeignKey of table.foreignKeys.updated){
251
+ debug(`Dropping updated foreign key ${updatedForeignKey.name} on ${table.name}`);
252
+ dropForeignKey(tableBuilder, updatedForeignKey.object, existingForeignKeys);
253
+ droppedForeignKeyNames.push(updatedForeignKey.object.name);
254
+ }
255
+ // In MySQL, dropping a foreign key can also implicitly drop an index with the same name
256
+ // Remove dropped foreign keys from existingIndexes for MySQL
257
+ if (db.config.connection.client === 'mysql') {
258
+ existingIndexes = existingIndexes.filter((index)=>!droppedForeignKeyNames.includes(index.name));
259
+ }
260
+ for (const removedIndex of table.indexes.removed){
261
+ debug(`Dropping index ${removedIndex.name} on ${table.name}`);
262
+ dropIndex(tableBuilder, removedIndex, existingIndexes);
263
+ }
264
+ for (const updatedIndex of table.indexes.updated){
265
+ debug(`Dropping updated index ${updatedIndex.name} on ${table.name}`);
266
+ dropIndex(tableBuilder, updatedIndex.object, existingIndexes);
267
+ }
268
+ // Drop columns after FKs have been removed to avoid FK errors
269
+ for (const removedColumn of table.columns.removed){
270
+ debug(`Dropping column ${removedColumn.name} on ${table.name}`);
271
+ dropColumn(tableBuilder, removedColumn);
272
+ }
273
+ // Update existing columns
274
+ for (const updatedColumn of table.columns.updated){
275
+ debug(`Updating column ${updatedColumn.name} on ${table.name}`);
276
+ const { object } = updatedColumn;
277
+ if (object.type === 'increments') {
278
+ createColumn(tableBuilder, {
279
+ ...object,
280
+ type: 'integer'
281
+ }).alter();
282
+ } else {
283
+ createColumn(tableBuilder, object).alter();
284
+ }
285
+ }
286
+ // Add any new columns
287
+ for (const addedColumn of table.columns.added){
288
+ debug(`Creating column ${addedColumn.name} on ${table.name}`);
289
+ if (addedColumn.type === 'increments' && !db.dialect.canAddIncrements()) {
290
+ tableBuilder.integer(addedColumn.name).unsigned();
291
+ tableBuilder.primary([
292
+ addedColumn.name
293
+ ]);
294
+ } else {
295
+ createColumn(tableBuilder, addedColumn);
296
+ }
297
+ }
298
+ // once the columns have all been updated, we can create indexes again
299
+ for (const updatedForeignKey of table.foreignKeys.updated){
300
+ debug(`Recreating updated foreign key ${updatedForeignKey.name} on ${table.name}`);
301
+ createForeignKey(tableBuilder, updatedForeignKey.object);
302
+ }
303
+ for (const updatedIndex of table.indexes.updated){
304
+ debug(`Recreating updated index ${updatedIndex.name} on ${table.name}`);
305
+ createIndex(tableBuilder, updatedIndex.object);
306
+ }
307
+ for (const addedForeignKey of table.foreignKeys.added){
308
+ debug(`Creating foreign key ${addedForeignKey.name} on ${table.name}`);
309
+ createForeignKey(tableBuilder, addedForeignKey);
310
+ }
311
+ for (const addedIndex of table.indexes.added){
312
+ debug(`Creating index ${addedIndex.name} on ${table.name}`);
313
+ createIndex(tableBuilder, addedIndex);
314
+ }
315
+ });
316
+ };
317
+ /**
318
+ * Drops a table from a database
319
+ */ const dropTable = (schemaBuilder, table)=>{
320
+ if (!db.config.settings.forceMigration) {
321
+ return;
322
+ }
323
+ return schemaBuilder.dropTableIfExists(table.name);
324
+ };
325
+ /**
326
+ * Creates a table foreign keys constraints
327
+ */ const createTableForeignKeys = async (schemaBuilder, table)=>{
328
+ // foreign keys
329
+ await schemaBuilder.table(table.name, (tableBuilder)=>{
330
+ (table.foreignKeys || []).forEach((foreignKey)=>createForeignKey(tableBuilder, foreignKey));
331
+ });
332
+ };
333
+ /**
334
+ * Drops a table foreign keys constraints
335
+ */ const dropTableForeignKeys = async (schemaBuilder, table)=>{
336
+ if (!db.config.settings.forceMigration) {
337
+ return;
338
+ }
339
+ // foreign keys
340
+ await schemaBuilder.table(table.name, (tableBuilder)=>{
341
+ (table.foreignKeys || []).forEach((foreignKey)=>dropForeignKey(tableBuilder, foreignKey));
342
+ });
343
+ };
344
+ return {
345
+ createTable,
346
+ alterTable,
347
+ dropTable,
348
+ createTableForeignKeys,
349
+ dropTableForeignKeys
350
+ };
351
+ };
352
+
353
+ module.exports = createSchemaBuilder;
354
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sources":["../../src/schema/builder.ts"],"sourcesContent":["import { isNil, prop, omit, castArray } from 'lodash/fp';\nimport createDebug from 'debug';\n\nimport type { Knex } from 'knex';\nimport type { Database } from '..';\nimport type { Schema, Table, SchemaDiff, TableDiff, ForeignKey, Index, Column } from './types';\n\nconst debug = createDebug('strapi::database');\n\nexport default (db: Database) => {\n const helpers = createHelpers(db);\n\n return {\n /**\n * Returns a knex schema builder instance\n * @param {string} table - table name\n */\n getSchemaBuilder(trx: Knex.Transaction) {\n return db.getSchemaConnection(trx);\n },\n\n /**\n * Creates schema in DB\n */\n async createSchema(schema: Schema) {\n await db.connection.transaction(async (trx) => {\n await this.createTables(schema.tables, trx);\n });\n },\n\n /**\n * Creates a list of tables in a schema\n * @param {KnexInstance} trx\n * @param {Table[]} tables\n */\n async createTables(tables: Table[], trx: Knex.Transaction) {\n for (const table of tables) {\n debug(`Creating table: ${table.name}`);\n const schemaBuilder = this.getSchemaBuilder(trx);\n await helpers.createTable(schemaBuilder, table);\n }\n\n // create FKs once all the tables exist\n for (const table of tables) {\n debug(`Creating table foreign keys: ${table.name}`);\n const schemaBuilder = this.getSchemaBuilder(trx);\n await helpers.createTableForeignKeys(schemaBuilder, table);\n }\n },\n /**\n * Drops schema from DB\n */\n async dropSchema(schema: Schema, { dropDatabase = false } = {}) {\n if (dropDatabase) {\n // TODO: drop database & return as it will drop everything\n return;\n }\n\n await db.connection.transaction(async (trx) => {\n for (const table of schema.tables.reverse()) {\n const schemaBuilder = this.getSchemaBuilder(trx);\n await helpers.dropTable(schemaBuilder, table);\n }\n });\n },\n\n /**\n * Applies a schema diff update in the DB\n * @param {*} schemaDiff\n */\n // TODO: implement force option to disable removal in DB\n async updateSchema(schemaDiff: SchemaDiff['diff']) {\n const forceMigration = db.config.settings?.forceMigration;\n\n await db.dialect.startSchemaUpdate();\n\n // Pre-fetch metadata for all updated tables\n const existingMetadata: Record<string, { indexes: Index[]; foreignKeys: ForeignKey[] }> = {};\n for (const table of schemaDiff.tables.updated) {\n existingMetadata[table.name] = {\n indexes: await db.dialect.schemaInspector.getIndexes(table.name),\n foreignKeys: await db.dialect.schemaInspector.getForeignKeys(table.name),\n };\n }\n\n await db.connection.transaction(async (trx) => {\n await this.createTables(schemaDiff.tables.added, trx);\n\n if (forceMigration) {\n // drop all delete table foreign keys then delete the tables\n for (const table of schemaDiff.tables.removed) {\n debug(`Removing table foreign keys: ${table.name}`);\n\n const schemaBuilder = this.getSchemaBuilder(trx);\n await helpers.dropTableForeignKeys(schemaBuilder, table);\n }\n\n for (const table of schemaDiff.tables.removed) {\n debug(`Removing table: ${table.name}`);\n\n const schemaBuilder = this.getSchemaBuilder(trx);\n await helpers.dropTable(schemaBuilder, table);\n }\n }\n\n for (const table of schemaDiff.tables.updated) {\n debug(`Updating table: ${table.name}`);\n // alter table\n const schemaBuilder = this.getSchemaBuilder(trx);\n\n const { indexes, foreignKeys } = existingMetadata[table.name];\n await helpers.alterTable(schemaBuilder, table, { indexes, foreignKeys });\n }\n });\n\n await db.dialect.endSchemaUpdate();\n },\n };\n};\n\nconst createHelpers = (db: Database) => {\n /**\n * Creates a foreign key on a table\n */\n const createForeignKey = (tableBuilder: Knex.TableBuilder, foreignKey: ForeignKey) => {\n const { name, columns, referencedColumns, referencedTable, onDelete, onUpdate } = foreignKey;\n\n const constraint = tableBuilder\n .foreign(columns, name)\n .references(referencedColumns)\n .inTable(db.getSchemaName() ? `${db.getSchemaName()}.${referencedTable}` : referencedTable);\n\n if (onDelete) {\n constraint.onDelete(onDelete);\n }\n\n if (onUpdate) {\n constraint.onUpdate(onUpdate);\n }\n };\n\n /**\n * Drops a foreign key from a table\n */\n const dropForeignKey = (\n tableBuilder: Knex.TableBuilder,\n foreignKey: ForeignKey,\n existingForeignKeys?: ForeignKey[]\n ) => {\n const { name, columns } = foreignKey;\n\n // Check if the index exists in existingIndexes, and return early if it doesn't\n if (\n existingForeignKeys &&\n !existingForeignKeys.some((existingIndex) => existingIndex?.name === name)\n ) {\n debug(`Foreign Key ${name} not found in existing foreign keys. Skipping drop.`);\n return;\n }\n\n tableBuilder.dropForeign(columns, name);\n };\n\n /**\n * Creates an index on a table\n */\n const createIndex = (tableBuilder: Knex.TableBuilder, index: Index) => {\n const { type, columns, name } = index;\n\n switch (type) {\n case 'primary': {\n return tableBuilder.primary(columns, { constraintName: name });\n }\n case 'unique': {\n return tableBuilder.unique(columns, { indexName: name });\n }\n default: {\n return tableBuilder.index(columns, name, type);\n }\n }\n };\n\n /**\n * Drops an index from table\n * @param {Knex.TableBuilder} tableBuilder\n * @param {Index} index\n */\n const dropIndex = (tableBuilder: Knex.TableBuilder, index: Index, existingIndexes?: Index[]) => {\n if (!db.config.settings?.forceMigration) {\n return;\n }\n\n const { type, columns, name } = index;\n\n // Check if the index exists in existingIndexes, and return early if it doesn't\n if (existingIndexes && !existingIndexes.some((existingIndex) => existingIndex?.name === name)) {\n debug(`Index ${index.name} not found in existingIndexes. Skipping drop.`);\n return;\n }\n\n switch (type) {\n case 'primary': {\n return tableBuilder.dropPrimary(name);\n }\n case 'unique': {\n return tableBuilder.dropUnique(columns, name);\n }\n default: {\n return tableBuilder.dropIndex(columns, name);\n }\n }\n };\n\n /**\n * Creates a column in a table\n */\n const createColumn = (tableBuilder: Knex.TableBuilder, column: Column) => {\n const { type, name, args = [], defaultTo, unsigned, notNullable } = column;\n\n const col = (tableBuilder[type as keyof Knex.TableBuilder] as any)(name, ...args);\n\n if (unsigned === true) {\n col.unsigned();\n }\n\n if (!isNil(defaultTo)) {\n const [value, opts] = castArray(defaultTo);\n\n if (prop('isRaw', opts)) {\n col.defaultTo(db.connection.raw(value), omit('isRaw', opts));\n } else {\n col.defaultTo(value, opts);\n }\n }\n\n if (notNullable === true) {\n col.notNullable();\n } else {\n col.nullable();\n }\n\n return col;\n };\n\n /**\n * Drops a column from a table\n */\n const dropColumn = (tableBuilder: Knex.TableBuilder, column: Column) => {\n if (!db.config.settings?.forceMigration) {\n return;\n }\n\n return tableBuilder.dropColumn(column.name);\n };\n\n /**\n * Creates a table in a database\n */\n const createTable = async (schemaBuilder: Knex.SchemaBuilder, table: Table) => {\n await schemaBuilder.createTable(table.name, (tableBuilder) => {\n // columns\n (table.columns || []).forEach((column) => createColumn(tableBuilder, column));\n\n // indexes\n (table.indexes || []).forEach((index) => createIndex(tableBuilder, index));\n\n // foreign keys\n\n if (!db.dialect.canAlterConstraints()) {\n (table.foreignKeys || []).forEach((foreignKey) =>\n createForeignKey(tableBuilder, foreignKey)\n );\n }\n });\n };\n\n /**\n * Alters a database table by applying a set of schema changes including updates to columns, indexes, and foreign keys.\n * This function ensures proper ordering of operations to avoid conflicts (e.g., foreign key errors) and handles\n * MySQL-specific quirks where dropping a foreign key can implicitly drop an associated index.\n *\n * @param {Knex.SchemaBuilder} schemaBuilder - Knex SchemaBuilder instance to perform schema operations.\n * @param {TableDiff['diff']} table - A diff object representing the schema changes to be applied to the table.\n * @param {{ indexes: Index[]; foreignKeys: ForeignKey[] }} existingMetadata - Metadata about existing indexes and\n * foreign keys in the table. Used to ensure safe operations and avoid unnecessary modifications.\n * - indexes: Array of existing index definitions.\n * - foreignKeys: Array of existing foreign key definitions.\n */\n const alterTable = async (\n schemaBuilder: Knex.SchemaBuilder,\n table: TableDiff['diff'],\n existingMetadata: { indexes: Index[]; foreignKeys: ForeignKey[] } = {\n indexes: [],\n foreignKeys: [],\n }\n ) => {\n let existingIndexes = [...existingMetadata.indexes];\n const existingForeignKeys = [...existingMetadata.foreignKeys];\n\n // Track dropped foreign keys\n const droppedForeignKeyNames: string[] = [];\n\n await schemaBuilder.alterTable(table.name, async (tableBuilder) => {\n // Drop foreign keys first to avoid foreign key errors in the following steps\n for (const removedForeignKey of table.foreignKeys.removed) {\n debug(`Dropping foreign key ${removedForeignKey.name} on ${table.name}`);\n dropForeignKey(tableBuilder, removedForeignKey, existingForeignKeys);\n\n droppedForeignKeyNames.push(removedForeignKey.name);\n }\n\n for (const updatedForeignKey of table.foreignKeys.updated) {\n debug(`Dropping updated foreign key ${updatedForeignKey.name} on ${table.name}`);\n dropForeignKey(tableBuilder, updatedForeignKey.object, existingForeignKeys);\n\n droppedForeignKeyNames.push(updatedForeignKey.object.name);\n }\n\n // In MySQL, dropping a foreign key can also implicitly drop an index with the same name\n // Remove dropped foreign keys from existingIndexes for MySQL\n if (db.config.connection.client === 'mysql') {\n existingIndexes = existingIndexes.filter(\n (index) => !droppedForeignKeyNames.includes(index.name)\n );\n }\n\n for (const removedIndex of table.indexes.removed) {\n debug(`Dropping index ${removedIndex.name} on ${table.name}`);\n dropIndex(tableBuilder, removedIndex, existingIndexes);\n }\n\n for (const updatedIndex of table.indexes.updated) {\n debug(`Dropping updated index ${updatedIndex.name} on ${table.name}`);\n dropIndex(tableBuilder, updatedIndex.object, existingIndexes);\n }\n\n // Drop columns after FKs have been removed to avoid FK errors\n for (const removedColumn of table.columns.removed) {\n debug(`Dropping column ${removedColumn.name} on ${table.name}`);\n dropColumn(tableBuilder, removedColumn);\n }\n\n // Update existing columns\n for (const updatedColumn of table.columns.updated) {\n debug(`Updating column ${updatedColumn.name} on ${table.name}`);\n\n const { object } = updatedColumn;\n\n if (object.type === 'increments') {\n createColumn(tableBuilder, { ...object, type: 'integer' }).alter();\n } else {\n createColumn(tableBuilder, object).alter();\n }\n }\n\n // Add any new columns\n for (const addedColumn of table.columns.added) {\n debug(`Creating column ${addedColumn.name} on ${table.name}`);\n\n if (addedColumn.type === 'increments' && !db.dialect.canAddIncrements()) {\n tableBuilder.integer(addedColumn.name).unsigned();\n tableBuilder.primary([addedColumn.name]);\n } else {\n createColumn(tableBuilder, addedColumn);\n }\n }\n\n // once the columns have all been updated, we can create indexes again\n for (const updatedForeignKey of table.foreignKeys.updated) {\n debug(`Recreating updated foreign key ${updatedForeignKey.name} on ${table.name}`);\n createForeignKey(tableBuilder, updatedForeignKey.object);\n }\n\n for (const updatedIndex of table.indexes.updated) {\n debug(`Recreating updated index ${updatedIndex.name} on ${table.name}`);\n createIndex(tableBuilder, updatedIndex.object);\n }\n\n for (const addedForeignKey of table.foreignKeys.added) {\n debug(`Creating foreign key ${addedForeignKey.name} on ${table.name}`);\n createForeignKey(tableBuilder, addedForeignKey);\n }\n\n for (const addedIndex of table.indexes.added) {\n debug(`Creating index ${addedIndex.name} on ${table.name}`);\n createIndex(tableBuilder, addedIndex);\n }\n });\n };\n\n /**\n * Drops a table from a database\n */\n const dropTable = (schemaBuilder: Knex.SchemaBuilder, table: Table) => {\n if (!db.config.settings.forceMigration) {\n return;\n }\n\n return schemaBuilder.dropTableIfExists(table.name);\n };\n\n /**\n * Creates a table foreign keys constraints\n */\n const createTableForeignKeys = async (schemaBuilder: Knex.SchemaBuilder, table: Table) => {\n // foreign keys\n await schemaBuilder.table(table.name, (tableBuilder) => {\n (table.foreignKeys || []).forEach((foreignKey) => createForeignKey(tableBuilder, foreignKey));\n });\n };\n\n /**\n * Drops a table foreign keys constraints\n */\n const dropTableForeignKeys = async (schemaBuilder: Knex.SchemaBuilder, table: Table) => {\n if (!db.config.settings.forceMigration) {\n return;\n }\n\n // foreign keys\n await schemaBuilder.table(table.name, (tableBuilder) => {\n (table.foreignKeys || []).forEach((foreignKey) => dropForeignKey(tableBuilder, foreignKey));\n });\n };\n\n return {\n createTable,\n alterTable,\n dropTable,\n createTableForeignKeys,\n dropTableForeignKeys,\n };\n};\n"],"names":["debug","createDebug","db","helpers","createHelpers","getSchemaBuilder","trx","getSchemaConnection","createSchema","schema","connection","transaction","createTables","tables","table","name","schemaBuilder","createTable","createTableForeignKeys","dropSchema","dropDatabase","reverse","dropTable","updateSchema","schemaDiff","forceMigration","config","settings","dialect","startSchemaUpdate","existingMetadata","updated","indexes","schemaInspector","getIndexes","foreignKeys","getForeignKeys","added","removed","dropTableForeignKeys","alterTable","endSchemaUpdate","createForeignKey","tableBuilder","foreignKey","columns","referencedColumns","referencedTable","onDelete","onUpdate","constraint","foreign","references","inTable","getSchemaName","dropForeignKey","existingForeignKeys","some","existingIndex","dropForeign","createIndex","index","type","primary","constraintName","unique","indexName","dropIndex","existingIndexes","dropPrimary","dropUnique","createColumn","column","args","defaultTo","unsigned","notNullable","col","isNil","value","opts","castArray","prop","raw","omit","nullable","dropColumn","forEach","canAlterConstraints","droppedForeignKeyNames","removedForeignKey","push","updatedForeignKey","object","client","filter","includes","removedIndex","updatedIndex","removedColumn","updatedColumn","alter","addedColumn","canAddIncrements","integer","addedForeignKey","addedIndex","dropTableIfExists"],"mappings":"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"}