@supabase/pg-delta 1.0.0-alpha.3 → 1.0.0-alpha.5

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 (633) hide show
  1. package/README.md +41 -2
  2. package/dist/cli/app.js +26 -3
  3. package/dist/cli/bin/cli.js +5 -0
  4. package/dist/cli/commands/catalog-export.d.ts +5 -0
  5. package/dist/cli/commands/catalog-export.js +64 -0
  6. package/dist/cli/commands/declarative-apply.d.ts +6 -0
  7. package/dist/cli/commands/declarative-apply.js +288 -0
  8. package/dist/cli/commands/declarative-export.d.ts +5 -0
  9. package/dist/cli/commands/declarative-export.js +245 -0
  10. package/dist/cli/commands/plan.js +40 -6
  11. package/dist/cli/exit-code.d.ts +2 -0
  12. package/dist/cli/exit-code.js +7 -0
  13. package/dist/cli/formatters/tree/tree.js +3 -2
  14. package/dist/cli/utils/apply-display.d.ts +52 -0
  15. package/dist/cli/utils/apply-display.js +183 -0
  16. package/dist/cli/utils/export-display.d.ts +43 -0
  17. package/dist/cli/utils/export-display.js +202 -0
  18. package/dist/cli/utils/resolve-input.d.ts +7 -0
  19. package/dist/cli/utils/resolve-input.js +13 -0
  20. package/dist/cli/utils.d.ts +2 -0
  21. package/dist/cli/utils.js +1 -1
  22. package/dist/core/catalog-export/index.d.ts +11 -0
  23. package/dist/core/catalog-export/index.js +10 -0
  24. package/dist/core/catalog.diff.d.ts +1 -0
  25. package/dist/core/catalog.diff.js +64 -48
  26. package/dist/core/catalog.model.d.ts +14 -1
  27. package/dist/core/catalog.model.js +103 -1
  28. package/dist/core/catalog.snapshot.d.ts +66 -0
  29. package/dist/core/catalog.snapshot.js +206 -0
  30. package/dist/core/declarative-apply/discover-sql.d.ts +18 -0
  31. package/dist/core/declarative-apply/discover-sql.js +86 -0
  32. package/dist/core/declarative-apply/extract-catalog-providers.d.ts +23 -0
  33. package/dist/core/declarative-apply/extract-catalog-providers.js +159 -0
  34. package/dist/core/declarative-apply/index.d.ts +49 -0
  35. package/dist/core/declarative-apply/index.js +134 -0
  36. package/dist/core/declarative-apply/round-apply.d.ts +100 -0
  37. package/dist/core/declarative-apply/round-apply.js +378 -0
  38. package/dist/core/export/file-mapper.d.ts +71 -0
  39. package/dist/core/export/file-mapper.js +474 -0
  40. package/dist/core/export/grouper.d.ts +13 -0
  41. package/dist/core/export/grouper.js +76 -0
  42. package/dist/core/export/index.d.ts +45 -0
  43. package/dist/core/export/index.js +63 -0
  44. package/dist/core/export/types.d.ts +84 -0
  45. package/dist/core/export/types.js +25 -0
  46. package/dist/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  47. package/dist/core/integrations/filter/dsl.d.ts +38 -1
  48. package/dist/core/integrations/filter/dsl.js +20 -2
  49. package/dist/core/integrations/filter/extractors.js +42 -0
  50. package/dist/core/integrations/integration-dsl.d.ts +10 -0
  51. package/dist/core/integrations/supabase.d.ts +8 -0
  52. package/dist/core/integrations/supabase.js +9 -0
  53. package/dist/core/objects/aggregate/aggregate.diff.d.ts +2 -8
  54. package/dist/core/objects/aggregate/aggregate.diff.js +16 -70
  55. package/dist/core/objects/aggregate/aggregate.model.d.ts +8 -8
  56. package/dist/core/objects/aggregate/aggregate.model.js +1 -1
  57. package/dist/core/objects/aggregate/changes/aggregate.create.js +1 -1
  58. package/dist/core/objects/aggregate/changes/aggregate.drop.js +1 -1
  59. package/dist/core/objects/base.privilege-diff.d.ts +38 -13
  60. package/dist/core/objects/base.privilege-diff.js +104 -22
  61. package/dist/core/objects/base.privilege.d.ts +1 -0
  62. package/dist/core/objects/base.privilege.js +9 -2
  63. package/dist/core/objects/collation/collation.diff.d.ts +2 -3
  64. package/dist/core/objects/diff-context.d.ts +15 -0
  65. package/dist/core/objects/diff-context.js +1 -0
  66. package/dist/core/objects/domain/changes/domain.create.js +4 -2
  67. package/dist/core/objects/domain/domain.diff.d.ts +2 -8
  68. package/dist/core/objects/domain/domain.diff.js +16 -77
  69. package/dist/core/objects/domain/domain.model.js +1 -1
  70. package/dist/core/objects/event-trigger/event-trigger.diff.d.ts +2 -3
  71. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.d.ts +2 -8
  72. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.js +13 -77
  73. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +2 -2
  74. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.d.ts +2 -8
  75. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -77
  76. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +1 -1
  77. package/dist/core/objects/foreign-data-wrapper/server/server.diff.d.ts +2 -8
  78. package/dist/core/objects/foreign-data-wrapper/server/server.diff.js +13 -77
  79. package/dist/core/objects/language/language.diff.d.ts +2 -5
  80. package/dist/core/objects/language/language.diff.js +7 -39
  81. package/dist/core/objects/materialized-view/materialized-view.diff.d.ts +2 -8
  82. package/dist/core/objects/materialized-view/materialized-view.diff.js +16 -158
  83. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +3 -3
  84. package/dist/core/objects/materialized-view/materialized-view.model.js +1 -1
  85. package/dist/core/objects/procedure/changes/procedure.alter.js +12 -12
  86. package/dist/core/objects/procedure/procedure.diff.d.ts +2 -8
  87. package/dist/core/objects/procedure/procedure.diff.js +16 -77
  88. package/dist/core/objects/procedure/procedure.model.d.ts +9 -9
  89. package/dist/core/objects/procedure/procedure.model.js +1 -1
  90. package/dist/core/objects/publication/changes/publication.alter.d.ts +0 -9
  91. package/dist/core/objects/publication/changes/publication.alter.js +0 -14
  92. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -2
  93. package/dist/core/objects/publication/publication.diff.d.ts +2 -3
  94. package/dist/core/objects/publication/publication.diff.js +8 -13
  95. package/dist/core/objects/rls-policy/changes/rls-policy.alter.js +3 -3
  96. package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
  97. package/dist/core/objects/role/role.diff.js +22 -1
  98. package/dist/core/objects/role/role.model.d.ts +4 -3
  99. package/dist/core/objects/role/role.model.js +118 -12
  100. package/dist/core/objects/rule/rule.model.d.ts +1 -1
  101. package/dist/core/objects/schema/schema.diff.d.ts +2 -8
  102. package/dist/core/objects/schema/schema.diff.js +16 -77
  103. package/dist/core/objects/schema/schema.model.js +1 -1
  104. package/dist/core/objects/sequence/sequence.diff.d.ts +2 -8
  105. package/dist/core/objects/sequence/sequence.diff.js +16 -79
  106. package/dist/core/objects/sequence/sequence.model.js +1 -1
  107. package/dist/core/objects/subscription/subscription.diff.d.ts +2 -3
  108. package/dist/core/objects/table/changes/table.create.js +3 -0
  109. package/dist/core/objects/table/table.diff.d.ts +2 -8
  110. package/dist/core/objects/table/table.diff.js +26 -157
  111. package/dist/core/objects/table/table.model.d.ts +25 -22
  112. package/dist/core/objects/table/table.model.js +4 -1
  113. package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
  114. package/dist/core/objects/trigger/changes/trigger.create.js +4 -5
  115. package/dist/core/objects/trigger/trigger.model.d.ts +9 -0
  116. package/dist/core/objects/trigger/trigger.model.js +14 -0
  117. package/dist/core/objects/type/composite-type/composite-type.diff.d.ts +2 -8
  118. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -77
  119. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +3 -3
  120. package/dist/core/objects/type/composite-type/composite-type.model.js +2 -1
  121. package/dist/core/objects/type/enum/enum.diff.d.ts +2 -8
  122. package/dist/core/objects/type/enum/enum.diff.js +25 -112
  123. package/dist/core/objects/type/enum/enum.model.js +1 -1
  124. package/dist/core/objects/type/range/changes/range.create.js +6 -3
  125. package/dist/core/objects/type/range/range.diff.d.ts +2 -8
  126. package/dist/core/objects/type/range/range.diff.js +16 -77
  127. package/dist/core/objects/type/range/range.model.js +1 -1
  128. package/dist/core/objects/view/view.diff.d.ts +2 -8
  129. package/dist/core/objects/view/view.diff.js +16 -158
  130. package/dist/core/objects/view/view.model.d.ts +18 -4
  131. package/dist/core/objects/view/view.model.js +3 -13
  132. package/dist/core/plan/apply.js +11 -28
  133. package/dist/core/plan/create.d.ts +19 -6
  134. package/dist/core/plan/create.js +134 -155
  135. package/dist/core/plan/serialize.js +16 -4
  136. package/dist/core/plan/sql-format/constants.d.ts +2 -0
  137. package/dist/core/plan/sql-format/constants.js +11 -0
  138. package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
  139. package/dist/core/plan/sql-format/fixtures.js +2447 -0
  140. package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
  141. package/dist/core/plan/sql-format/format-utils.js +274 -0
  142. package/dist/core/plan/sql-format/formatters.d.ts +20 -0
  143. package/dist/core/plan/sql-format/formatters.js +737 -0
  144. package/dist/core/plan/sql-format/index.d.ts +2 -0
  145. package/dist/core/plan/sql-format/index.js +98 -0
  146. package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
  147. package/dist/core/plan/sql-format/keyword-case.js +893 -0
  148. package/dist/core/plan/sql-format/protect.d.ts +3 -0
  149. package/dist/core/plan/sql-format/protect.js +269 -0
  150. package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
  151. package/dist/core/plan/sql-format/sql-scanner.js +202 -0
  152. package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
  153. package/dist/core/plan/sql-format/tokenizer.js +118 -0
  154. package/dist/core/plan/sql-format/types.d.ts +28 -0
  155. package/dist/core/plan/sql-format/types.js +1 -0
  156. package/dist/core/plan/sql-format/wrap.d.ts +2 -0
  157. package/dist/core/plan/sql-format/wrap.js +165 -0
  158. package/dist/core/plan/sql-format.d.ts +2 -0
  159. package/dist/core/plan/sql-format.js +1 -0
  160. package/dist/core/plan/ssl-config.d.ts +32 -0
  161. package/dist/core/plan/ssl-config.js +115 -0
  162. package/dist/core/plan/statements.d.ts +2 -1
  163. package/dist/core/plan/statements.js +6 -2
  164. package/dist/core/plan/types.d.ts +6 -0
  165. package/dist/core/postgres-config.d.ts +29 -0
  166. package/dist/core/postgres-config.js +83 -2
  167. package/dist/core/sort/graph-builder.js +10 -0
  168. package/dist/core/sort/logical-sort.js +31 -23
  169. package/dist/core/test-utils/assert-valid-sql.d.ts +10 -0
  170. package/dist/core/test-utils/assert-valid-sql.js +19 -0
  171. package/dist/index.d.ts +8 -0
  172. package/dist/index.js +7 -1
  173. package/package.json +54 -22
  174. package/src/cli/app.ts +52 -0
  175. package/src/cli/bin/cli.ts +15 -0
  176. package/src/cli/commands/apply.ts +101 -0
  177. package/src/cli/commands/catalog-export.ts +78 -0
  178. package/src/cli/commands/declarative-apply.diagnostics.test.ts +77 -0
  179. package/src/cli/commands/declarative-apply.ts +380 -0
  180. package/src/cli/commands/declarative-export.ts +330 -0
  181. package/src/cli/commands/plan.ts +216 -0
  182. package/src/cli/commands/sync.ts +185 -0
  183. package/src/cli/exit-code.test.ts +19 -0
  184. package/src/cli/exit-code.ts +7 -0
  185. package/src/cli/formatters/index.ts +5 -0
  186. package/src/cli/formatters/tree/tree-builder.ts +380 -0
  187. package/src/cli/formatters/tree/tree-renderer.ts +372 -0
  188. package/src/cli/formatters/tree/tree.ts +238 -0
  189. package/src/cli/utils/apply-display.test.ts +348 -0
  190. package/src/cli/utils/apply-display.ts +238 -0
  191. package/src/cli/utils/export-display.test.ts +103 -0
  192. package/src/cli/utils/export-display.ts +275 -0
  193. package/src/cli/utils/integrations.test.ts +44 -0
  194. package/src/cli/utils/integrations.ts +42 -0
  195. package/src/cli/utils/resolve-input.test.ts +38 -0
  196. package/src/cli/utils/resolve-input.ts +17 -0
  197. package/src/cli/utils.ts +231 -0
  198. package/src/core/catalog-export/index.ts +20 -0
  199. package/src/core/catalog.diff.ts +247 -0
  200. package/src/core/catalog.model.test.ts +122 -0
  201. package/src/core/catalog.model.ts +510 -0
  202. package/src/core/catalog.snapshot.test.ts +464 -0
  203. package/src/core/catalog.snapshot.ts +289 -0
  204. package/src/core/change.types.ts +44 -0
  205. package/src/core/context.ts +26 -0
  206. package/src/core/declarative-apply/discover-sql.test.ts +103 -0
  207. package/src/core/declarative-apply/discover-sql.ts +107 -0
  208. package/src/core/declarative-apply/extract-catalog-providers.ts +220 -0
  209. package/src/core/declarative-apply/index.test.ts +67 -0
  210. package/src/core/declarative-apply/index.ts +205 -0
  211. package/src/core/declarative-apply/round-apply.test.ts +504 -0
  212. package/src/core/declarative-apply/round-apply.ts +562 -0
  213. package/src/core/depend.ts +1870 -0
  214. package/src/core/expand-replace-dependencies.test.ts +70 -0
  215. package/src/core/expand-replace-dependencies.ts +380 -0
  216. package/src/core/export/file-mapper.test.ts +816 -0
  217. package/src/core/export/file-mapper.ts +574 -0
  218. package/src/core/export/grouper.ts +108 -0
  219. package/src/core/export/index.ts +129 -0
  220. package/src/core/export/types.ts +104 -0
  221. package/src/core/fingerprint.ts +204 -0
  222. package/src/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  223. package/src/core/integrations/filter/dsl.test.ts +211 -0
  224. package/src/core/integrations/filter/dsl.ts +266 -0
  225. package/src/core/integrations/filter/extractors.test.ts +244 -0
  226. package/src/core/integrations/filter/extractors.ts +187 -0
  227. package/src/core/integrations/filter/filter.types.ts +3 -0
  228. package/src/core/integrations/integration-dsl.ts +34 -0
  229. package/src/core/integrations/integration.types.ts +7 -0
  230. package/src/core/integrations/serialize/dsl.test.ts +91 -0
  231. package/src/core/integrations/serialize/dsl.ts +77 -0
  232. package/src/core/integrations/serialize/serialize.types.ts +3 -0
  233. package/src/core/integrations/supabase.ts +130 -0
  234. package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
  235. package/src/core/objects/aggregate/aggregate.diff.ts +222 -0
  236. package/src/core/objects/aggregate/aggregate.model.ts +317 -0
  237. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +66 -0
  238. package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
  239. package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
  240. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +89 -0
  241. package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
  242. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +104 -0
  243. package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
  244. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +82 -0
  245. package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
  246. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +136 -0
  247. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
  248. package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
  249. package/src/core/objects/base.change.ts +62 -0
  250. package/src/core/objects/base.default-privileges.ts +204 -0
  251. package/src/core/objects/base.diff.ts +20 -0
  252. package/src/core/objects/base.model.ts +82 -0
  253. package/src/core/objects/base.privilege-diff.ts +447 -0
  254. package/src/core/objects/base.privilege.ts +191 -0
  255. package/src/core/objects/collation/changes/collation.alter.test.ts +68 -0
  256. package/src/core/objects/collation/changes/collation.alter.ts +79 -0
  257. package/src/core/objects/collation/changes/collation.base.ts +20 -0
  258. package/src/core/objects/collation/changes/collation.comment.ts +68 -0
  259. package/src/core/objects/collation/changes/collation.create.test.ts +56 -0
  260. package/src/core/objects/collation/changes/collation.create.ts +106 -0
  261. package/src/core/objects/collation/changes/collation.drop.test.ts +31 -0
  262. package/src/core/objects/collation/changes/collation.drop.ts +37 -0
  263. package/src/core/objects/collation/changes/collation.types.ts +10 -0
  264. package/src/core/objects/collation/collation.diff.test.ts +97 -0
  265. package/src/core/objects/collation/collation.diff.ts +127 -0
  266. package/src/core/objects/collation/collation.model.ts +224 -0
  267. package/src/core/objects/diff-context.ts +16 -0
  268. package/src/core/objects/domain/changes/domain.alter.test.ts +335 -0
  269. package/src/core/objects/domain/changes/domain.alter.ts +286 -0
  270. package/src/core/objects/domain/changes/domain.base.ts +20 -0
  271. package/src/core/objects/domain/changes/domain.comment.ts +59 -0
  272. package/src/core/objects/domain/changes/domain.create.test.ts +95 -0
  273. package/src/core/objects/domain/changes/domain.create.ts +124 -0
  274. package/src/core/objects/domain/changes/domain.drop.test.ts +33 -0
  275. package/src/core/objects/domain/changes/domain.drop.ts +34 -0
  276. package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
  277. package/src/core/objects/domain/changes/domain.types.ts +12 -0
  278. package/src/core/objects/domain/domain.diff.test.ts +284 -0
  279. package/src/core/objects/domain/domain.diff.ts +295 -0
  280. package/src/core/objects/domain/domain.model.ts +190 -0
  281. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +57 -0
  282. package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
  283. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
  284. package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
  285. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +27 -0
  286. package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
  287. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +25 -0
  288. package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
  289. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
  290. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +131 -0
  291. package/src/core/objects/event-trigger/event-trigger.diff.ts +127 -0
  292. package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
  293. package/src/core/objects/extension/changes/extension.alter.test.ts +63 -0
  294. package/src/core/objects/extension/changes/extension.alter.ts +78 -0
  295. package/src/core/objects/extension/changes/extension.base.ts +20 -0
  296. package/src/core/objects/extension/changes/extension.comment.ts +64 -0
  297. package/src/core/objects/extension/changes/extension.create.test.ts +28 -0
  298. package/src/core/objects/extension/changes/extension.create.ts +63 -0
  299. package/src/core/objects/extension/changes/extension.drop.test.ts +26 -0
  300. package/src/core/objects/extension/changes/extension.drop.ts +34 -0
  301. package/src/core/objects/extension/changes/extension.types.ts +10 -0
  302. package/src/core/objects/extension/extension.diff.test.ts +42 -0
  303. package/src/core/objects/extension/extension.diff.ts +90 -0
  304. package/src/core/objects/extension/extension.model.test.ts +98 -0
  305. package/src/core/objects/extension/extension.model.ts +280 -0
  306. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +136 -0
  307. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
  308. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
  309. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
  310. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +160 -0
  311. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
  312. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +26 -0
  313. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
  314. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
  315. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
  316. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +286 -0
  317. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +271 -0
  318. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
  319. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
  320. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +340 -0
  321. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
  322. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
  323. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
  324. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +210 -0
  325. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
  326. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +46 -0
  327. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
  328. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
  329. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
  330. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
  331. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +343 -0
  332. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
  333. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +183 -0
  334. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
  335. package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
  336. package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
  337. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +144 -0
  338. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
  339. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +27 -0
  340. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
  341. package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
  342. package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
  343. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +262 -0
  344. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +247 -0
  345. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
  346. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +91 -0
  347. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
  348. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
  349. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +96 -0
  350. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
  351. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +60 -0
  352. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
  353. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
  354. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
  355. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
  356. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
  357. package/src/core/objects/index/changes/index.alter.test.ts +209 -0
  358. package/src/core/objects/index/changes/index.alter.ts +144 -0
  359. package/src/core/objects/index/changes/index.base.ts +20 -0
  360. package/src/core/objects/index/changes/index.comment.ts +63 -0
  361. package/src/core/objects/index/changes/index.create.test.ts +69 -0
  362. package/src/core/objects/index/changes/index.create.ts +68 -0
  363. package/src/core/objects/index/changes/index.drop.test.ts +47 -0
  364. package/src/core/objects/index/changes/index.drop.ts +34 -0
  365. package/src/core/objects/index/changes/index.types.ts +6 -0
  366. package/src/core/objects/index/changes/utils.ts +16 -0
  367. package/src/core/objects/index/index.diff.test.ts +153 -0
  368. package/src/core/objects/index/index.diff.ts +243 -0
  369. package/src/core/objects/index/index.model.ts +370 -0
  370. package/src/core/objects/language/changes/language.alter.test.ts +36 -0
  371. package/src/core/objects/language/changes/language.alter.ts +53 -0
  372. package/src/core/objects/language/changes/language.base.ts +20 -0
  373. package/src/core/objects/language/changes/language.comment.ts +58 -0
  374. package/src/core/objects/language/changes/language.create.test.ts +30 -0
  375. package/src/core/objects/language/changes/language.create.ts +104 -0
  376. package/src/core/objects/language/changes/language.drop.test.ts +28 -0
  377. package/src/core/objects/language/changes/language.drop.ts +39 -0
  378. package/src/core/objects/language/changes/language.privilege.ts +172 -0
  379. package/src/core/objects/language/changes/language.types.ts +12 -0
  380. package/src/core/objects/language/language.diff.test.ts +135 -0
  381. package/src/core/objects/language/language.diff.ts +144 -0
  382. package/src/core/objects/language/language.model.ts +150 -0
  383. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +130 -0
  384. package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
  385. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
  386. package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
  387. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +69 -0
  388. package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
  389. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +37 -0
  390. package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
  391. package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
  392. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
  393. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +264 -0
  394. package/src/core/objects/materialized-view/materialized-view.diff.ts +301 -0
  395. package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
  396. package/src/core/objects/procedure/changes/procedure.alter.test.ts +1077 -0
  397. package/src/core/objects/procedure/changes/procedure.alter.ts +290 -0
  398. package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
  399. package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
  400. package/src/core/objects/procedure/changes/procedure.create.test.ts +51 -0
  401. package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
  402. package/src/core/objects/procedure/changes/procedure.drop.test.ts +90 -0
  403. package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
  404. package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
  405. package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
  406. package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
  407. package/src/core/objects/procedure/procedure.diff.ts +341 -0
  408. package/src/core/objects/procedure/procedure.model.ts +264 -0
  409. package/src/core/objects/procedure/utils.ts +58 -0
  410. package/src/core/objects/publication/changes/publication.alter.test.ts +217 -0
  411. package/src/core/objects/publication/changes/publication.alter.ts +225 -0
  412. package/src/core/objects/publication/changes/publication.base.ts +20 -0
  413. package/src/core/objects/publication/changes/publication.comment.test.ts +73 -0
  414. package/src/core/objects/publication/changes/publication.comment.ts +64 -0
  415. package/src/core/objects/publication/changes/publication.create.test.ts +90 -0
  416. package/src/core/objects/publication/changes/publication.create.ts +82 -0
  417. package/src/core/objects/publication/changes/publication.drop.test.ts +48 -0
  418. package/src/core/objects/publication/changes/publication.drop.ts +29 -0
  419. package/src/core/objects/publication/changes/publication.types.ts +24 -0
  420. package/src/core/objects/publication/publication.diff.test.ts +297 -0
  421. package/src/core/objects/publication/publication.diff.ts +247 -0
  422. package/src/core/objects/publication/publication.model.ts +206 -0
  423. package/src/core/objects/publication/utils.ts +55 -0
  424. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +267 -0
  425. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
  426. package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
  427. package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
  428. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +81 -0
  429. package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
  430. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +31 -0
  431. package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
  432. package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
  433. package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
  434. package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
  435. package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
  436. package/src/core/objects/role/changes/role.alter.test.ts +362 -0
  437. package/src/core/objects/role/changes/role.alter.ts +110 -0
  438. package/src/core/objects/role/changes/role.base.ts +24 -0
  439. package/src/core/objects/role/changes/role.comment.ts +55 -0
  440. package/src/core/objects/role/changes/role.create.test.ts +56 -0
  441. package/src/core/objects/role/changes/role.create.ts +102 -0
  442. package/src/core/objects/role/changes/role.drop.test.ts +32 -0
  443. package/src/core/objects/role/changes/role.drop.ts +34 -0
  444. package/src/core/objects/role/changes/role.privilege.ts +376 -0
  445. package/src/core/objects/role/changes/role.types.ts +12 -0
  446. package/src/core/objects/role/role.diff.test.ts +279 -0
  447. package/src/core/objects/role/role.diff.ts +499 -0
  448. package/src/core/objects/role/role.model.ts +452 -0
  449. package/src/core/objects/rule/changes/rule.alter.test.ts +82 -0
  450. package/src/core/objects/rule/changes/rule.alter.ts +72 -0
  451. package/src/core/objects/rule/changes/rule.base.ts +20 -0
  452. package/src/core/objects/rule/changes/rule.comment.test.ts +58 -0
  453. package/src/core/objects/rule/changes/rule.comment.ts +62 -0
  454. package/src/core/objects/rule/changes/rule.create.test.ts +63 -0
  455. package/src/core/objects/rule/changes/rule.create.ts +42 -0
  456. package/src/core/objects/rule/changes/rule.drop.test.ts +40 -0
  457. package/src/core/objects/rule/changes/rule.drop.ts +29 -0
  458. package/src/core/objects/rule/changes/rule.types.ts +12 -0
  459. package/src/core/objects/rule/rule.diff.test.ts +132 -0
  460. package/src/core/objects/rule/rule.diff.ts +79 -0
  461. package/src/core/objects/rule/rule.model.ts +173 -0
  462. package/src/core/objects/schema/changes/schema.alter.test.ts +31 -0
  463. package/src/core/objects/schema/changes/schema.alter.ts +45 -0
  464. package/src/core/objects/schema/changes/schema.base.ts +20 -0
  465. package/src/core/objects/schema/changes/schema.comment.ts +56 -0
  466. package/src/core/objects/schema/changes/schema.create.test.ts +25 -0
  467. package/src/core/objects/schema/changes/schema.create.ts +47 -0
  468. package/src/core/objects/schema/changes/schema.drop.test.ts +23 -0
  469. package/src/core/objects/schema/changes/schema.drop.ts +34 -0
  470. package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
  471. package/src/core/objects/schema/changes/schema.types.ts +12 -0
  472. package/src/core/objects/schema/schema.diff.test.ts +42 -0
  473. package/src/core/objects/schema/schema.diff.ts +146 -0
  474. package/src/core/objects/schema/schema.model.ts +107 -0
  475. package/src/core/objects/sequence/changes/sequence.alter.test.ts +157 -0
  476. package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
  477. package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
  478. package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
  479. package/src/core/objects/sequence/changes/sequence.create.test.ts +89 -0
  480. package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
  481. package/src/core/objects/sequence/changes/sequence.drop.test.ts +35 -0
  482. package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
  483. package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
  484. package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
  485. package/src/core/objects/sequence/sequence.diff.test.ts +255 -0
  486. package/src/core/objects/sequence/sequence.diff.ts +294 -0
  487. package/src/core/objects/sequence/sequence.model.ts +185 -0
  488. package/src/core/objects/subscription/changes/subscription.alter.test.ts +134 -0
  489. package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
  490. package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
  491. package/src/core/objects/subscription/changes/subscription.comment.test.ts +70 -0
  492. package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
  493. package/src/core/objects/subscription/changes/subscription.create.test.ts +80 -0
  494. package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
  495. package/src/core/objects/subscription/changes/subscription.drop.test.ts +48 -0
  496. package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
  497. package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
  498. package/src/core/objects/subscription/subscription.diff.test.ts +237 -0
  499. package/src/core/objects/subscription/subscription.diff.ts +242 -0
  500. package/src/core/objects/subscription/subscription.model.ts +190 -0
  501. package/src/core/objects/subscription/utils.ts +156 -0
  502. package/src/core/objects/table/changes/table.alter.test.ts +846 -0
  503. package/src/core/objects/table/changes/table.alter.ts +806 -0
  504. package/src/core/objects/table/changes/table.base.ts +20 -0
  505. package/src/core/objects/table/changes/table.comment.ts +266 -0
  506. package/src/core/objects/table/changes/table.create.test.ts +188 -0
  507. package/src/core/objects/table/changes/table.create.ts +192 -0
  508. package/src/core/objects/table/changes/table.drop.test.ts +36 -0
  509. package/src/core/objects/table/changes/table.drop.ts +45 -0
  510. package/src/core/objects/table/changes/table.privilege.ts +200 -0
  511. package/src/core/objects/table/changes/table.types.ts +12 -0
  512. package/src/core/objects/table/table.diff.test.ts +868 -0
  513. package/src/core/objects/table/table.diff.ts +817 -0
  514. package/src/core/objects/table/table.model.ts +460 -0
  515. package/src/core/objects/trigger/changes/trigger.alter.test.ts +50 -0
  516. package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
  517. package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
  518. package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
  519. package/src/core/objects/trigger/changes/trigger.create.test.ts +47 -0
  520. package/src/core/objects/trigger/changes/trigger.create.ts +88 -0
  521. package/src/core/objects/trigger/changes/trigger.drop.test.ts +47 -0
  522. package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
  523. package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
  524. package/src/core/objects/trigger/trigger.diff.test.ts +84 -0
  525. package/src/core/objects/trigger/trigger.diff.ts +116 -0
  526. package/src/core/objects/trigger/trigger.model.ts +264 -0
  527. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +208 -0
  528. package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
  529. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
  530. package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
  531. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +106 -0
  532. package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
  533. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +36 -0
  534. package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
  535. package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
  536. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
  537. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +269 -0
  538. package/src/core/objects/type/composite-type/composite-type.diff.ts +310 -0
  539. package/src/core/objects/type/composite-type/composite-type.model.ts +253 -0
  540. package/src/core/objects/type/enum/changes/enum.alter.test.ts +113 -0
  541. package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
  542. package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
  543. package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
  544. package/src/core/objects/type/enum/changes/enum.create.test.ts +31 -0
  545. package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
  546. package/src/core/objects/type/enum/changes/enum.drop.test.ts +28 -0
  547. package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
  548. package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
  549. package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
  550. package/src/core/objects/type/enum/enum.diff.test.ts +372 -0
  551. package/src/core/objects/type/enum/enum.diff.ts +308 -0
  552. package/src/core/objects/type/enum/enum.model.ts +194 -0
  553. package/src/core/objects/type/range/changes/range.alter.test.ts +29 -0
  554. package/src/core/objects/type/range/changes/range.alter.ts +51 -0
  555. package/src/core/objects/type/range/changes/range.base.ts +20 -0
  556. package/src/core/objects/type/range/changes/range.comment.ts +64 -0
  557. package/src/core/objects/type/range/changes/range.create.test.ts +54 -0
  558. package/src/core/objects/type/range/changes/range.create.ts +155 -0
  559. package/src/core/objects/type/range/changes/range.drop.test.ts +28 -0
  560. package/src/core/objects/type/range/changes/range.drop.ts +34 -0
  561. package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
  562. package/src/core/objects/type/range/changes/range.types.ts +12 -0
  563. package/src/core/objects/type/range/range.diff.test.ts +147 -0
  564. package/src/core/objects/type/range/range.diff.ts +197 -0
  565. package/src/core/objects/type/range/range.model.ts +187 -0
  566. package/src/core/objects/type/type.types.ts +5 -0
  567. package/src/core/objects/utils.ts +171 -0
  568. package/src/core/objects/view/changes/view.alter.test.ts +115 -0
  569. package/src/core/objects/view/changes/view.alter.ts +112 -0
  570. package/src/core/objects/view/changes/view.base.ts +20 -0
  571. package/src/core/objects/view/changes/view.comment.ts +59 -0
  572. package/src/core/objects/view/changes/view.create.test.ts +70 -0
  573. package/src/core/objects/view/changes/view.create.ts +73 -0
  574. package/src/core/objects/view/changes/view.drop.test.ts +37 -0
  575. package/src/core/objects/view/changes/view.drop.ts +40 -0
  576. package/src/core/objects/view/changes/view.privilege.ts +200 -0
  577. package/src/core/objects/view/changes/view.types.ts +12 -0
  578. package/src/core/objects/view/view.diff.test.ts +173 -0
  579. package/src/core/objects/view/view.diff.ts +215 -0
  580. package/src/core/objects/view/view.model.ts +262 -0
  581. package/src/core/plan/apply.ts +172 -0
  582. package/src/core/plan/create.ts +368 -0
  583. package/src/core/plan/hierarchy.ts +574 -0
  584. package/src/core/plan/index.ts +29 -0
  585. package/src/core/plan/io.ts +20 -0
  586. package/src/core/plan/risk.ts +48 -0
  587. package/src/core/plan/serialize.test.ts +317 -0
  588. package/src/core/plan/serialize.ts +209 -0
  589. package/src/core/plan/sql-format/constants.ts +13 -0
  590. package/src/core/plan/sql-format/fixtures.ts +2803 -0
  591. package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
  592. package/src/core/plan/sql-format/format-functions.test.ts +127 -0
  593. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +119 -0
  594. package/src/core/plan/sql-format/format-off.test.ts +806 -0
  595. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1061 -0
  596. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1279 -0
  597. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1057 -0
  598. package/src/core/plan/sql-format/format-pretty-upper.test.ts +1048 -0
  599. package/src/core/plan/sql-format/format-stress.test.ts +616 -0
  600. package/src/core/plan/sql-format/format-utils.test.ts +91 -0
  601. package/src/core/plan/sql-format/format-utils.ts +391 -0
  602. package/src/core/plan/sql-format/formatters.ts +921 -0
  603. package/src/core/plan/sql-format/index.ts +149 -0
  604. package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
  605. package/src/core/plan/sql-format/keyword-case.ts +1120 -0
  606. package/src/core/plan/sql-format/protect.test.ts +127 -0
  607. package/src/core/plan/sql-format/protect.ts +337 -0
  608. package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
  609. package/src/core/plan/sql-format/sql-scanner.ts +252 -0
  610. package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
  611. package/src/core/plan/sql-format/tokenizer.ts +152 -0
  612. package/src/core/plan/sql-format/types.ts +31 -0
  613. package/src/core/plan/sql-format/wrap.test.ts +119 -0
  614. package/src/core/plan/sql-format/wrap.ts +196 -0
  615. package/src/core/plan/sql-format.ts +2 -0
  616. package/src/core/plan/ssl-config.ts +172 -0
  617. package/src/core/plan/statements.ts +22 -0
  618. package/src/core/plan/types.ts +171 -0
  619. package/src/core/postgres-config.ts +238 -0
  620. package/src/core/sort/custom-constraints.ts +161 -0
  621. package/src/core/sort/debug-visualization.ts +239 -0
  622. package/src/core/sort/dependency-filter.ts +224 -0
  623. package/src/core/sort/graph-builder.ts +235 -0
  624. package/src/core/sort/graph-utils.ts +51 -0
  625. package/src/core/sort/logical-sort.test.ts +371 -0
  626. package/src/core/sort/logical-sort.ts +597 -0
  627. package/src/core/sort/sort-changes.ts +234 -0
  628. package/src/core/sort/topological-sort.test.ts +275 -0
  629. package/src/core/sort/topological-sort.ts +184 -0
  630. package/src/core/sort/types.ts +112 -0
  631. package/src/core/sort/utils.ts +69 -0
  632. package/src/core/test-utils/assert-valid-sql.ts +20 -0
  633. package/src/index.ts +38 -0
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Phased dependency-graph sort for ordered schema changes.
3
+ *
4
+ * Changes are split into two execution phases:
5
+ * - `drop`: Destructive operations (executed first, in reverse dependency order)
6
+ * - `create_alter_object`: All remaining changes (executed second, in forward dependency order)
7
+ *
8
+ * Within each phase, changes are sorted using Constraints derived from:
9
+ * - Catalog dependencies (from pg_depend)
10
+ * - Explicit requirements (from Change.requires)
11
+ * - Custom constraints (change-to-change ordering rules)
12
+ */
13
+
14
+ import debug from "debug";
15
+ import type { Catalog } from "../catalog.model.ts";
16
+ import type { Change } from "../change.types.ts";
17
+ import { generateCustomConstraints } from "./custom-constraints.ts";
18
+ import { printDebugGraph } from "./debug-visualization.ts";
19
+
20
+ const debugGraph = debug("pg-delta:graph");
21
+
22
+ import {
23
+ filterEdgesForCycleBreaking,
24
+ getEdgesInCycle,
25
+ } from "./dependency-filter.ts";
26
+ import {
27
+ buildGraphData,
28
+ convertCatalogDependenciesToConstraints,
29
+ convertConstraintsToEdges,
30
+ convertExplicitRequirementsToConstraints,
31
+ edgesToPairs,
32
+ } from "./graph-builder.ts";
33
+ import { dedupeEdges } from "./graph-utils.ts";
34
+ import { logicalSort } from "./logical-sort.ts";
35
+ import {
36
+ findCycle,
37
+ formatCycleError,
38
+ performStableTopologicalSort,
39
+ } from "./topological-sort.ts";
40
+ import type { PgDependRow, PhaseSortOptions } from "./types.ts";
41
+ import { getExecutionPhase, type Phase } from "./utils.ts";
42
+
43
+ /**
44
+ * Sort changes using dependency information from catalogs and custom constraints.
45
+ *
46
+ * First applies logical pre-sorting to group related changes together,
47
+ * then applies dependency-based topological sorting to ensure correct execution order.
48
+ *
49
+ * @param catalogs - Main and branch catalogs containing dependency information
50
+ * @param changes - List of Change objects to order
51
+ * @returns Ordered list of Change objects
52
+ */
53
+ export function sortChanges(
54
+ catalogs: { mainCatalog: Catalog; branchCatalog: Catalog },
55
+ changes: Change[],
56
+ ): Change[] {
57
+ // Step 1: Apply logical pre-sorting to group changes by object type, stable ID, and scope
58
+ const logicallySorted = logicalSort(changes);
59
+
60
+ // Step 2: Apply dependency-based topological sorting
61
+ return sortChangesByPhasedGraph(
62
+ {
63
+ mainCatalog: { depends: catalogs.mainCatalog.depends },
64
+ branchCatalog: { depends: catalogs.branchCatalog.depends },
65
+ },
66
+ logicallySorted,
67
+ );
68
+ }
69
+
70
+ /**
71
+ * Sort changes by phases, using dependency information in each phase.
72
+ *
73
+ * @param catalogContext - pg_depend rows from the main and branch catalogs
74
+ * @param changeList - list of Change objects to order
75
+ * @returns ordered list of Change objects
76
+ */
77
+ function sortChangesByPhasedGraph(
78
+ catalogContext: {
79
+ mainCatalog: { depends: PgDependRow[] };
80
+ branchCatalog: { depends: PgDependRow[] };
81
+ },
82
+ changeList: Change[],
83
+ ): Change[] {
84
+ const changesByPhase: Record<Phase, Change[]> = {
85
+ drop: [],
86
+ create_alter_object: [],
87
+ };
88
+
89
+ // Partition changes into execution phases
90
+ for (const changeItem of changeList) {
91
+ const phase = getExecutionPhase(changeItem);
92
+ changesByPhase[phase].push(changeItem);
93
+ }
94
+
95
+ // Sort DROP phase: reverse dependency order using main catalog dependencies
96
+ const sortedDropPhase = sortPhaseChanges(
97
+ changesByPhase.drop,
98
+ catalogContext.mainCatalog.depends,
99
+ { invert: true },
100
+ );
101
+
102
+ // Sort CREATE/ALTER phase: forward dependency order using branch catalog dependencies
103
+ const sortedCreateAlterPhase = sortPhaseChanges(
104
+ changesByPhase.create_alter_object,
105
+ catalogContext.branchCatalog.depends,
106
+ {},
107
+ );
108
+
109
+ return [...sortedDropPhase, ...sortedCreateAlterPhase];
110
+ }
111
+
112
+ /**
113
+ * Sort changes within a phase using Constraints derived from all dependency sources.
114
+ *
115
+ * Algorithm:
116
+ * 1. Build graph data (change sets and reverse indexes)
117
+ * 2. Convert all sources to Constraints (catalog, explicit, custom constraints)
118
+ * 3. Convert Constraints to edges
119
+ * 4. Iteratively detect and break cycles (deduplicate edges, detect cycles, filter problematic edges)
120
+ * 5. Perform stable topological sort on the acyclic graph
121
+ *
122
+ * In DROP phase, edges are inverted so drops run in reverse dependency order.
123
+ */
124
+ function sortPhaseChanges(
125
+ phaseChanges: Change[],
126
+ dependencyRows: PgDependRow[],
127
+ options: PhaseSortOptions = {},
128
+ ): Change[] {
129
+ if (phaseChanges.length <= 1) return phaseChanges;
130
+
131
+ // Step 1: Build graph data structures
132
+ const graphData = buildGraphData(phaseChanges, options);
133
+
134
+ // Step 2: Convert all sources to Constraints
135
+ const catalogConstraints = convertCatalogDependenciesToConstraints(
136
+ dependencyRows,
137
+ graphData,
138
+ );
139
+ const explicitConstraints = convertExplicitRequirementsToConstraints(
140
+ phaseChanges,
141
+ graphData,
142
+ );
143
+ const customConstraintObjects = generateCustomConstraints(phaseChanges);
144
+ const allConstraints = [
145
+ ...catalogConstraints,
146
+ ...explicitConstraints,
147
+ ...customConstraintObjects,
148
+ ];
149
+
150
+ // Step 3: Convert constraints to edges and deduplicate immediately
151
+ let edges = dedupeEdges(convertConstraintsToEdges(allConstraints, options));
152
+
153
+ // Step 4: Iteratively detect and break cycles
154
+ // Track cycles we've seen to detect when filtering fails to break a cycle.
155
+ // The only way we loop indefinitely is if we encounter a cycle we've already seen,
156
+ // which means filtering didn't break it. Otherwise, we continue until all cycles are broken.
157
+ const seenCycles = new Set<string>();
158
+
159
+ /**
160
+ * Normalize a cycle by rotating it to start with the smallest node index.
161
+ * This allows us to compare cycles regardless of where they start.
162
+ */
163
+ function normalizeCycle(cycleNodeIndexes: number[]): string {
164
+ if (cycleNodeIndexes.length === 0) return "";
165
+ const minIndex = Math.min(...cycleNodeIndexes);
166
+ const minIndexPos = cycleNodeIndexes.indexOf(minIndex);
167
+ const rotated = [
168
+ ...cycleNodeIndexes.slice(minIndexPos),
169
+ ...cycleNodeIndexes.slice(0, minIndexPos),
170
+ ];
171
+ return rotated.join(",");
172
+ }
173
+
174
+ while (true) {
175
+ // Edge deduplication moved outside loop
176
+ const edgePairs = edgesToPairs(edges);
177
+
178
+ // Detect cycles
179
+ const cycleNodeIndexes = findCycle(phaseChanges.length, edgePairs);
180
+
181
+ if (!cycleNodeIndexes) {
182
+ // No cycles found, we're done
183
+ break;
184
+ }
185
+
186
+ // Normalize cycle to check if we've seen it before
187
+ const cycleSignature = normalizeCycle(cycleNodeIndexes);
188
+ if (seenCycles.has(cycleSignature)) {
189
+ // We've seen this cycle before - filtering didn't break it
190
+ // Get edges involved in the cycle for detailed error message
191
+ const cycleEdges = getEdgesInCycle(cycleNodeIndexes, edges);
192
+ throw new Error(
193
+ formatCycleError(cycleNodeIndexes, phaseChanges, cycleEdges),
194
+ );
195
+ }
196
+
197
+ // Track this cycle
198
+ seenCycles.add(cycleSignature);
199
+
200
+ // Filter only edges involved in the cycle to break it
201
+ edges = filterEdgesForCycleBreaking(
202
+ edges,
203
+ cycleNodeIndexes,
204
+ phaseChanges,
205
+ graphData,
206
+ );
207
+ }
208
+
209
+ const finalEdgePairs = edgesToPairs(edges);
210
+
211
+ // Debug visualization
212
+ if (debugGraph.enabled) {
213
+ printDebugGraph(
214
+ phaseChanges,
215
+ graphData,
216
+ finalEdgePairs,
217
+ dependencyRows,
218
+ allConstraints,
219
+ );
220
+ }
221
+
222
+ // Step 5: Perform stable topological sort (no cycles, so this will succeed)
223
+ const topologicalOrder = performStableTopologicalSort(
224
+ phaseChanges.length,
225
+ finalEdgePairs,
226
+ );
227
+
228
+ if (!topologicalOrder || topologicalOrder.length !== phaseChanges.length) {
229
+ // This should never happen if findCycle returned null, but guard anyway
230
+ throw new Error("CycleError: dependency graph contains a cycle");
231
+ }
232
+
233
+ return topologicalOrder.map((changeIndex) => phaseChanges[changeIndex]);
234
+ }
@@ -0,0 +1,275 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import type { Change } from "../change.types.ts";
3
+ import {
4
+ findCycle,
5
+ formatCycleError,
6
+ performStableTopologicalSort,
7
+ } from "./topological-sort.ts";
8
+ import type { Constraint } from "./types.ts";
9
+
10
+ function mockChange(name: string, creates: string[] = []): Change {
11
+ const change = {
12
+ objectType: "table",
13
+ operation: "create" as const,
14
+ scope: "object",
15
+ creates,
16
+ drops: [],
17
+ requires: [],
18
+ serialize: () => "",
19
+ };
20
+ Object.defineProperty(change, "constructor", { value: { name } });
21
+ return change as unknown as Change;
22
+ }
23
+
24
+ describe("performStableTopologicalSort", () => {
25
+ test("no edges returns identity order", () => {
26
+ const result = performStableTopologicalSort(3, []);
27
+ expect(result).toEqual([0, 1, 2]);
28
+ });
29
+
30
+ test("linear chain produces correct order", () => {
31
+ const result = performStableTopologicalSort(3, [
32
+ [0, 1],
33
+ [1, 2],
34
+ ]);
35
+ expect(result).toEqual([0, 1, 2]);
36
+ });
37
+
38
+ test("reversed linear chain reorders correctly", () => {
39
+ const result = performStableTopologicalSort(3, [
40
+ [2, 1],
41
+ [1, 0],
42
+ ]);
43
+ expect(result).toEqual([2, 1, 0]);
44
+ });
45
+
46
+ test("diamond dependency resolves correctly", () => {
47
+ const result = performStableTopologicalSort(4, [
48
+ [0, 1],
49
+ [0, 2],
50
+ [1, 3],
51
+ [2, 3],
52
+ ]);
53
+ expect(result).toEqual([0, 1, 2, 3]);
54
+ });
55
+
56
+ test("cycle returns null", () => {
57
+ const result = performStableTopologicalSort(2, [
58
+ [0, 1],
59
+ [1, 0],
60
+ ]);
61
+ expect(result).toBeNull();
62
+ });
63
+
64
+ test("stable ordering among unconstrained nodes", () => {
65
+ const result = performStableTopologicalSort(5, [[3, 4]]);
66
+ expect(result).toEqual([0, 1, 2, 3, 4]);
67
+ });
68
+
69
+ test("duplicate edges are handled", () => {
70
+ const result = performStableTopologicalSort(2, [
71
+ [0, 1],
72
+ [0, 1],
73
+ ]);
74
+ expect(result).toEqual([0, 1]);
75
+ });
76
+
77
+ test("single node returns identity", () => {
78
+ const result = performStableTopologicalSort(1, []);
79
+ expect(result).toEqual([0]);
80
+ });
81
+ });
82
+
83
+ describe("findCycle", () => {
84
+ test("no edges means no cycle", () => {
85
+ expect(findCycle(3, [])).toBeNull();
86
+ });
87
+
88
+ test("linear chain has no cycle", () => {
89
+ expect(
90
+ findCycle(3, [
91
+ [0, 1],
92
+ [1, 2],
93
+ ]),
94
+ ).toBeNull();
95
+ });
96
+
97
+ test("simple cycle is detected", () => {
98
+ const cycle = findCycle(2, [
99
+ [0, 1],
100
+ [1, 0],
101
+ ]);
102
+ expect(cycle).not.toBeNull();
103
+ expect(cycle?.length).toBeGreaterThanOrEqual(2);
104
+ });
105
+
106
+ test("three-node cycle is detected", () => {
107
+ const cycle = findCycle(3, [
108
+ [0, 1],
109
+ [1, 2],
110
+ [2, 0],
111
+ ]);
112
+ expect(cycle).not.toBeNull();
113
+ expect(cycle?.length).toBe(3);
114
+ });
115
+
116
+ test("self-loop is detected", () => {
117
+ const cycle = findCycle(1, [[0, 0]]);
118
+ expect(cycle).not.toBeNull();
119
+ });
120
+
121
+ test("cycle in subgraph is found", () => {
122
+ const cycle = findCycle(4, [
123
+ [0, 1],
124
+ [2, 3],
125
+ [3, 2],
126
+ ]);
127
+ expect(cycle).not.toBeNull();
128
+ expect(cycle).toContain(2);
129
+ expect(cycle).toContain(3);
130
+ });
131
+ });
132
+
133
+ describe("formatCycleError", () => {
134
+ test("basic format without cycleEdges", () => {
135
+ const changes = [
136
+ mockChange("CreateTable", ["table:public.a"]),
137
+ mockChange("CreateTable", ["table:public.b"]),
138
+ ];
139
+
140
+ const message = formatCycleError([0, 1], changes);
141
+ expect(message).toContain("CycleError");
142
+ expect(message).toContain("2 changes");
143
+ expect(message).toContain("CreateTable");
144
+ expect(message).toContain("table:public.a");
145
+ expect(message).toContain("table:public.b");
146
+ expect(message).toContain("circular dependency");
147
+ expect(message).not.toContain("Cycle path");
148
+ });
149
+
150
+ test("catalog source with dependentStableId", () => {
151
+ const changes = [
152
+ mockChange("CreateTable", ["table:public.a"]),
153
+ mockChange("CreateView", ["view:public.v"]),
154
+ ];
155
+
156
+ const constraint: Constraint = {
157
+ sourceChangeIndex: 0,
158
+ targetChangeIndex: 1,
159
+ source: "catalog",
160
+ reason: {
161
+ dependentStableId: "view:public.v",
162
+ referencedStableId: "table:public.a",
163
+ },
164
+ };
165
+
166
+ const message = formatCycleError([0, 1], changes, [
167
+ { sourceIndex: 0, targetIndex: 1, constraint },
168
+ ]);
169
+ expect(message).toContain("Cycle path");
170
+ expect(message).toContain("source: catalog");
171
+ expect(message).toContain("Dependency: view:public.v → table:public.a");
172
+ expect(message).toContain("Cycle-breaking filter did not match");
173
+ expect(message).toContain("cycle-breaking filters were unable");
174
+ });
175
+
176
+ test("explicit source without dependentStableId", () => {
177
+ const changes = [
178
+ mockChange("CreateTable"),
179
+ mockChange("CreateView", ["view:public.v"]),
180
+ ];
181
+
182
+ const constraint: Constraint = {
183
+ sourceChangeIndex: 0,
184
+ targetChangeIndex: 1,
185
+ source: "explicit",
186
+ reason: {
187
+ referencedStableId: "table:public.a",
188
+ },
189
+ };
190
+
191
+ const message = formatCycleError([0, 1], changes, [
192
+ { sourceIndex: 0, targetIndex: 1, constraint },
193
+ ]);
194
+ expect(message).toContain("source: explicit");
195
+ expect(message).toContain("Requires: table:public.a");
196
+ expect(message).toContain(
197
+ "Explicit requirement without created IDs (not filtered)",
198
+ );
199
+ });
200
+
201
+ test("custom source constraint", () => {
202
+ const changes = [
203
+ mockChange("CreateTable", ["table:public.a"]),
204
+ mockChange("CreateTable", ["table:public.b"]),
205
+ ];
206
+
207
+ const constraint: Constraint = {
208
+ sourceChangeIndex: 0,
209
+ targetChangeIndex: 1,
210
+ source: "custom",
211
+ };
212
+
213
+ const message = formatCycleError([0, 1], changes, [
214
+ { sourceIndex: 0, targetIndex: 1, constraint },
215
+ ]);
216
+ expect(message).toContain("source: custom");
217
+ expect(message).toContain("Custom constraint (never filtered)");
218
+ });
219
+
220
+ test("edge not found in cycleEdges", () => {
221
+ const changes = [
222
+ mockChange("CreateTable", ["table:public.a"]),
223
+ mockChange("CreateTable", ["table:public.b"]),
224
+ mockChange("CreateView", ["view:public.v"]),
225
+ ];
226
+
227
+ const unrelatedConstraint: Constraint = {
228
+ sourceChangeIndex: 2,
229
+ targetChangeIndex: 0,
230
+ source: "custom",
231
+ };
232
+
233
+ const message = formatCycleError([0, 1], changes, [
234
+ { sourceIndex: 2, targetIndex: 0, constraint: unrelatedConstraint },
235
+ ]);
236
+ expect(message).toContain("(edge not found)");
237
+ });
238
+
239
+ test("explicit source with dependentStableId uses filter message", () => {
240
+ const changes = [
241
+ mockChange("CreateTable", ["table:public.a"]),
242
+ mockChange("CreateView", ["view:public.v"]),
243
+ ];
244
+
245
+ const constraint: Constraint = {
246
+ sourceChangeIndex: 0,
247
+ targetChangeIndex: 1,
248
+ source: "explicit",
249
+ reason: {
250
+ dependentStableId: "view:public.v",
251
+ referencedStableId: "table:public.a",
252
+ },
253
+ };
254
+
255
+ const message = formatCycleError([0, 1], changes, [
256
+ { sourceIndex: 0, targetIndex: 1, constraint },
257
+ ]);
258
+ expect(message).toContain("Dependency: view:public.v → table:public.a");
259
+ expect(message).toContain("Cycle-breaking filter did not match");
260
+ });
261
+
262
+ test("change with many creates truncates", () => {
263
+ const changes = [
264
+ mockChange("CreateTable", [
265
+ "table:public.a",
266
+ "table:public.b",
267
+ "table:public.c",
268
+ ]),
269
+ ];
270
+
271
+ const message = formatCycleError([0], changes);
272
+ expect(message).toContain("table:public.a, table:public.b...");
273
+ expect(message).not.toContain("table:public.c");
274
+ });
275
+ });
@@ -0,0 +1,184 @@
1
+ import type { Change } from "../change.types.ts";
2
+ import type { Constraint } from "./types.ts";
3
+
4
+ /**
5
+ * Stable topological sort. If multiple zero-indegree nodes exist, picks the
6
+ * smallest original index first to preserve input order among unconstrained items.
7
+ * Returns null on cycles.
8
+ */
9
+ export function performStableTopologicalSort(
10
+ nodeCount: number,
11
+ edges: Array<[number, number]>,
12
+ ): number[] | null {
13
+ const adjacencyList: Array<Set<number>> = Array.from(
14
+ { length: nodeCount },
15
+ () => new Set<number>(),
16
+ );
17
+ const inDegreeCounts = new Array<number>(nodeCount).fill(0);
18
+
19
+ for (const [sourceIndex, targetIndex] of edges) {
20
+ if (!adjacencyList[sourceIndex].has(targetIndex)) {
21
+ adjacencyList[sourceIndex].add(targetIndex);
22
+ inDegreeCounts[targetIndex]++;
23
+ }
24
+ }
25
+
26
+ const candidateQueue: number[] = [];
27
+ for (let nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
28
+ if (inDegreeCounts[nodeIndex] === 0) candidateQueue.push(nodeIndex);
29
+ }
30
+ candidateQueue.sort((left, right) => left - right);
31
+
32
+ const orderedNodeIndexes: number[] = [];
33
+ while (candidateQueue.length > 0) {
34
+ const nodeIndex = candidateQueue.shift() as number;
35
+ orderedNodeIndexes.push(nodeIndex);
36
+ for (const neighborIndex of adjacencyList[nodeIndex]) {
37
+ inDegreeCounts[neighborIndex]--;
38
+ if (inDegreeCounts[neighborIndex] === 0) {
39
+ let inserted = false;
40
+ for (
41
+ let queuePosition = 0;
42
+ queuePosition < candidateQueue.length;
43
+ queuePosition++
44
+ ) {
45
+ if (neighborIndex < candidateQueue[queuePosition]) {
46
+ candidateQueue.splice(queuePosition, 0, neighborIndex);
47
+ inserted = true;
48
+ break;
49
+ }
50
+ }
51
+ if (!inserted) candidateQueue.push(neighborIndex);
52
+ }
53
+ }
54
+ }
55
+
56
+ if (orderedNodeIndexes.length !== nodeCount) return null; // cycle detected
57
+ return orderedNodeIndexes;
58
+ }
59
+
60
+ /**
61
+ * Find one cycle (if any) and return its node indices in order.
62
+ */
63
+ export function findCycle(
64
+ nodeCount: number,
65
+ edges: Array<[number, number]>,
66
+ ): number[] | null {
67
+ const adjacencyList: Array<number[]> = Array.from(
68
+ { length: nodeCount },
69
+ () => [],
70
+ );
71
+ for (const [sourceIndex, targetIndex] of edges) {
72
+ adjacencyList[sourceIndex].push(targetIndex);
73
+ }
74
+
75
+ // 0 = unvisited, 1 = visiting, 2 = completed
76
+ const visitState = new Array<number>(nodeCount).fill(0);
77
+ const pathStack: number[] = [];
78
+ let cycleNodeIndexes: number[] | null = null;
79
+
80
+ const depthFirstSearch = (nodeIndex: number) => {
81
+ if (cycleNodeIndexes) return;
82
+ visitState[nodeIndex] = 1;
83
+ pathStack.push(nodeIndex);
84
+
85
+ for (const neighborIndex of adjacencyList[nodeIndex]) {
86
+ if (visitState[neighborIndex] === 0) {
87
+ depthFirstSearch(neighborIndex);
88
+ } else if (visitState[neighborIndex] === 1) {
89
+ const cycleStartIndex = pathStack.lastIndexOf(neighborIndex);
90
+ if (cycleStartIndex !== -1) {
91
+ cycleNodeIndexes = pathStack.slice(cycleStartIndex);
92
+ }
93
+ return;
94
+ }
95
+ if (cycleNodeIndexes) return;
96
+ }
97
+
98
+ pathStack.pop();
99
+ visitState[nodeIndex] = 2;
100
+ };
101
+
102
+ for (
103
+ let nodeIndex = 0;
104
+ nodeIndex < nodeCount && !cycleNodeIndexes;
105
+ nodeIndex++
106
+ ) {
107
+ if (visitState[nodeIndex] === 0) depthFirstSearch(nodeIndex);
108
+ }
109
+
110
+ return cycleNodeIndexes;
111
+ }
112
+
113
+ /**
114
+ * Format a cycle error message with details about the changes involved and the edges forming the cycle.
115
+ */
116
+ export function formatCycleError(
117
+ cycleNodeIndexes: number[],
118
+ phaseChanges: Change[],
119
+ cycleEdges?: Array<{
120
+ sourceIndex: number;
121
+ targetIndex: number;
122
+ constraint: Constraint;
123
+ }>,
124
+ ): string {
125
+ const cycleChanges = cycleNodeIndexes.map((idx) => phaseChanges[idx]);
126
+ const changeDescriptions = cycleChanges.map((change, i) => {
127
+ const className = change?.constructor?.name ?? "Change";
128
+ const creates = change.creates.slice(0, 2).join(", ");
129
+ return ` ${i + 1}. [${cycleNodeIndexes[i]}] ${className}${creates ? ` (creates: ${creates}${change.creates.length > 2 ? "..." : ""})` : ""}`;
130
+ });
131
+
132
+ let message = `CycleError: dependency graph contains a cycle involving ${cycleNodeIndexes.length} changes:\n${changeDescriptions.join("\n")}`;
133
+
134
+ // Add cycle path information if edges are provided
135
+ if (cycleEdges && cycleEdges.length > 0) {
136
+ message += `\n\nCycle path (edges forming the cycle):`;
137
+ for (let i = 0; i < cycleNodeIndexes.length; i++) {
138
+ const sourceIndex = cycleNodeIndexes[i];
139
+ const targetIndex = cycleNodeIndexes[(i + 1) % cycleNodeIndexes.length];
140
+ const edge = cycleEdges.find(
141
+ (e) => e.sourceIndex === sourceIndex && e.targetIndex === targetIndex,
142
+ );
143
+
144
+ if (edge) {
145
+ const constraint = edge.constraint;
146
+ let edgeInfo = `\n [${sourceIndex}] → [${targetIndex}] (source: ${constraint.source})`;
147
+
148
+ if (
149
+ constraint.source === "catalog" ||
150
+ constraint.source === "explicit"
151
+ ) {
152
+ if (constraint.reason.dependentStableId) {
153
+ edgeInfo += `\n Dependency: ${constraint.reason.dependentStableId} → ${constraint.reason.referencedStableId}`;
154
+ } else {
155
+ edgeInfo += `\n Requires: ${constraint.reason.referencedStableId}`;
156
+ }
157
+ }
158
+
159
+ // Add why it wasn't filtered
160
+ if (constraint.source === "custom") {
161
+ edgeInfo += `\n Reason: Custom constraint (never filtered)`;
162
+ } else if (
163
+ constraint.source === "explicit" &&
164
+ !constraint.reason.dependentStableId
165
+ ) {
166
+ edgeInfo += `\n Reason: Explicit requirement without created IDs (not filtered)`;
167
+ } else {
168
+ edgeInfo += `\n Reason: Cycle-breaking filter did not match (edge preserved)`;
169
+ }
170
+
171
+ message += edgeInfo;
172
+ } else {
173
+ message += `\n [${sourceIndex}] → [${targetIndex}] (edge not found)`;
174
+ }
175
+ }
176
+ }
177
+
178
+ message += `\n\nThis usually indicates a circular dependency in the schema changes that cannot be resolved.`;
179
+ if (cycleEdges && cycleEdges.length > 0) {
180
+ message += `\nThe cycle-breaking filters were unable to break this cycle.`;
181
+ }
182
+
183
+ return message;
184
+ }