@supabase/pg-delta 1.0.0-alpha.2 → 1.0.0-alpha.4

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 (464) hide show
  1. package/README.md +22 -0
  2. package/dist/cli/bin/cli.js +0 -0
  3. package/dist/cli/commands/plan.js +21 -0
  4. package/dist/cli/utils.d.ts +2 -0
  5. package/dist/cli/utils.js +1 -1
  6. package/dist/core/integrations/supabase.js +2 -0
  7. package/dist/core/objects/table/table.model.d.ts +4 -2
  8. package/dist/core/objects/table/table.model.js +3 -0
  9. package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
  10. package/dist/core/objects/trigger/changes/trigger.create.js +2 -1
  11. package/dist/core/objects/trigger/trigger.model.d.ts +1 -0
  12. package/dist/core/objects/trigger/trigger.model.js +3 -0
  13. package/dist/core/plan/apply.js +3 -3
  14. package/dist/core/plan/create.js +34 -15
  15. package/dist/core/plan/sql-format/constants.d.ts +2 -0
  16. package/dist/core/plan/sql-format/constants.js +11 -0
  17. package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
  18. package/dist/core/plan/sql-format/fixtures.js +2449 -0
  19. package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
  20. package/dist/core/plan/sql-format/format-utils.js +274 -0
  21. package/dist/core/plan/sql-format/formatters.d.ts +20 -0
  22. package/dist/core/plan/sql-format/formatters.js +737 -0
  23. package/dist/core/plan/sql-format/index.d.ts +2 -0
  24. package/dist/core/plan/sql-format/index.js +98 -0
  25. package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
  26. package/dist/core/plan/sql-format/keyword-case.js +868 -0
  27. package/dist/core/plan/sql-format/protect.d.ts +3 -0
  28. package/dist/core/plan/sql-format/protect.js +269 -0
  29. package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
  30. package/dist/core/plan/sql-format/sql-scanner.js +202 -0
  31. package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
  32. package/dist/core/plan/sql-format/tokenizer.js +118 -0
  33. package/dist/core/plan/sql-format/types.d.ts +28 -0
  34. package/dist/core/plan/sql-format/types.js +1 -0
  35. package/dist/core/plan/sql-format/wrap.d.ts +2 -0
  36. package/dist/core/plan/sql-format/wrap.js +165 -0
  37. package/dist/core/plan/sql-format.d.ts +2 -0
  38. package/dist/core/plan/sql-format.js +1 -0
  39. package/dist/core/plan/statements.d.ts +2 -1
  40. package/dist/core/plan/statements.js +6 -2
  41. package/dist/core/postgres-config.d.ts +15 -0
  42. package/dist/core/postgres-config.js +30 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.js +1 -0
  45. package/package.json +37 -22
  46. package/src/cli/app.ts +28 -0
  47. package/src/cli/bin/cli.ts +9 -0
  48. package/src/cli/commands/apply.ts +101 -0
  49. package/src/cli/commands/plan.ts +195 -0
  50. package/src/cli/commands/sync.ts +185 -0
  51. package/src/cli/formatters/index.ts +5 -0
  52. package/src/cli/formatters/tree/tree-builder.ts +380 -0
  53. package/src/cli/formatters/tree/tree-renderer.ts +372 -0
  54. package/src/cli/formatters/tree/tree.ts +237 -0
  55. package/src/cli/utils/integrations.ts +42 -0
  56. package/src/cli/utils.ts +231 -0
  57. package/src/core/catalog.diff.ts +246 -0
  58. package/src/core/catalog.model.ts +384 -0
  59. package/src/core/change.types.ts +44 -0
  60. package/src/core/context.ts +26 -0
  61. package/src/core/depend.ts +1870 -0
  62. package/src/core/expand-replace-dependencies.ts +380 -0
  63. package/src/core/fingerprint.ts +204 -0
  64. package/src/core/integrations/filter/dsl.ts +204 -0
  65. package/src/core/integrations/filter/extractors.ts +145 -0
  66. package/src/core/integrations/filter/filter.types.ts +3 -0
  67. package/src/core/integrations/integration-dsl.ts +24 -0
  68. package/src/core/integrations/integration.types.ts +7 -0
  69. package/src/core/integrations/serialize/dsl.ts +77 -0
  70. package/src/core/integrations/serialize/serialize.types.ts +3 -0
  71. package/src/core/integrations/supabase.ts +121 -0
  72. package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
  73. package/src/core/objects/aggregate/aggregate.diff.ts +278 -0
  74. package/src/core/objects/aggregate/aggregate.model.ts +317 -0
  75. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +64 -0
  76. package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
  77. package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
  78. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +86 -0
  79. package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
  80. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +101 -0
  81. package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
  82. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +78 -0
  83. package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
  84. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +130 -0
  85. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
  86. package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
  87. package/src/core/objects/base.change.ts +62 -0
  88. package/src/core/objects/base.default-privileges.ts +204 -0
  89. package/src/core/objects/base.diff.ts +20 -0
  90. package/src/core/objects/base.model.ts +82 -0
  91. package/src/core/objects/base.privilege-diff.ts +299 -0
  92. package/src/core/objects/base.privilege.ts +184 -0
  93. package/src/core/objects/collation/changes/collation.alter.test.ts +63 -0
  94. package/src/core/objects/collation/changes/collation.alter.ts +79 -0
  95. package/src/core/objects/collation/changes/collation.base.ts +20 -0
  96. package/src/core/objects/collation/changes/collation.comment.ts +68 -0
  97. package/src/core/objects/collation/changes/collation.create.test.ts +51 -0
  98. package/src/core/objects/collation/changes/collation.create.ts +106 -0
  99. package/src/core/objects/collation/changes/collation.drop.test.ts +28 -0
  100. package/src/core/objects/collation/changes/collation.drop.ts +37 -0
  101. package/src/core/objects/collation/changes/collation.types.ts +10 -0
  102. package/src/core/objects/collation/collation.diff.test.ts +100 -0
  103. package/src/core/objects/collation/collation.diff.ts +126 -0
  104. package/src/core/objects/collation/collation.model.ts +224 -0
  105. package/src/core/objects/domain/changes/domain.alter.test.ts +316 -0
  106. package/src/core/objects/domain/changes/domain.alter.ts +286 -0
  107. package/src/core/objects/domain/changes/domain.base.ts +20 -0
  108. package/src/core/objects/domain/changes/domain.comment.ts +59 -0
  109. package/src/core/objects/domain/changes/domain.create.test.ts +65 -0
  110. package/src/core/objects/domain/changes/domain.create.ts +118 -0
  111. package/src/core/objects/domain/changes/domain.drop.test.ts +30 -0
  112. package/src/core/objects/domain/changes/domain.drop.ts +34 -0
  113. package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
  114. package/src/core/objects/domain/changes/domain.types.ts +12 -0
  115. package/src/core/objects/domain/domain.diff.test.ts +284 -0
  116. package/src/core/objects/domain/domain.diff.ts +358 -0
  117. package/src/core/objects/domain/domain.model.ts +190 -0
  118. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +50 -0
  119. package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
  120. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
  121. package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
  122. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +24 -0
  123. package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
  124. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +22 -0
  125. package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
  126. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
  127. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +126 -0
  128. package/src/core/objects/event-trigger/event-trigger.diff.ts +126 -0
  129. package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
  130. package/src/core/objects/extension/changes/extension.alter.test.ts +58 -0
  131. package/src/core/objects/extension/changes/extension.alter.ts +78 -0
  132. package/src/core/objects/extension/changes/extension.base.ts +20 -0
  133. package/src/core/objects/extension/changes/extension.comment.ts +64 -0
  134. package/src/core/objects/extension/changes/extension.create.test.ts +25 -0
  135. package/src/core/objects/extension/changes/extension.create.ts +63 -0
  136. package/src/core/objects/extension/changes/extension.drop.test.ts +23 -0
  137. package/src/core/objects/extension/changes/extension.drop.ts +34 -0
  138. package/src/core/objects/extension/changes/extension.types.ts +10 -0
  139. package/src/core/objects/extension/extension.diff.test.ts +42 -0
  140. package/src/core/objects/extension/extension.diff.ts +90 -0
  141. package/src/core/objects/extension/extension.model.ts +280 -0
  142. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +125 -0
  143. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
  144. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
  145. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
  146. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +125 -0
  147. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
  148. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +23 -0
  149. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
  150. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
  151. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
  152. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +179 -0
  153. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +341 -0
  154. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
  155. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
  156. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +309 -0
  157. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
  158. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
  159. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
  160. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +201 -0
  161. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
  162. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +43 -0
  163. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
  164. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
  165. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
  166. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
  167. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +406 -0
  168. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
  169. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +168 -0
  170. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
  171. package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
  172. package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
  173. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +131 -0
  174. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
  175. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +24 -0
  176. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
  177. package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
  178. package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
  179. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +167 -0
  180. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +317 -0
  181. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
  182. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +82 -0
  183. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
  184. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
  185. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +85 -0
  186. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
  187. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +53 -0
  188. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
  189. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
  190. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
  191. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
  192. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
  193. package/src/core/objects/index/changes/index.alter.test.ts +200 -0
  194. package/src/core/objects/index/changes/index.alter.ts +144 -0
  195. package/src/core/objects/index/changes/index.base.ts +20 -0
  196. package/src/core/objects/index/changes/index.comment.ts +63 -0
  197. package/src/core/objects/index/changes/index.create.test.ts +66 -0
  198. package/src/core/objects/index/changes/index.create.ts +68 -0
  199. package/src/core/objects/index/changes/index.drop.test.ts +44 -0
  200. package/src/core/objects/index/changes/index.drop.ts +34 -0
  201. package/src/core/objects/index/changes/index.types.ts +6 -0
  202. package/src/core/objects/index/changes/utils.ts +16 -0
  203. package/src/core/objects/index/index.diff.test.ts +153 -0
  204. package/src/core/objects/index/index.diff.ts +243 -0
  205. package/src/core/objects/index/index.model.ts +370 -0
  206. package/src/core/objects/language/changes/language.alter.test.ts +33 -0
  207. package/src/core/objects/language/changes/language.alter.ts +53 -0
  208. package/src/core/objects/language/changes/language.base.ts +20 -0
  209. package/src/core/objects/language/changes/language.comment.ts +58 -0
  210. package/src/core/objects/language/changes/language.create.test.ts +27 -0
  211. package/src/core/objects/language/changes/language.create.ts +104 -0
  212. package/src/core/objects/language/changes/language.drop.test.ts +25 -0
  213. package/src/core/objects/language/changes/language.drop.ts +39 -0
  214. package/src/core/objects/language/changes/language.privilege.ts +172 -0
  215. package/src/core/objects/language/changes/language.types.ts +12 -0
  216. package/src/core/objects/language/language.diff.test.ts +53 -0
  217. package/src/core/objects/language/language.diff.ts +176 -0
  218. package/src/core/objects/language/language.model.ts +150 -0
  219. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +123 -0
  220. package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
  221. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
  222. package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
  223. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +64 -0
  224. package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
  225. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +34 -0
  226. package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
  227. package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
  228. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
  229. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +102 -0
  230. package/src/core/objects/materialized-view/materialized-view.diff.ts +451 -0
  231. package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
  232. package/src/core/objects/procedure/changes/procedure.alter.test.ts +1005 -0
  233. package/src/core/objects/procedure/changes/procedure.alter.ts +287 -0
  234. package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
  235. package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
  236. package/src/core/objects/procedure/changes/procedure.create.test.ts +48 -0
  237. package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
  238. package/src/core/objects/procedure/changes/procedure.drop.test.ts +85 -0
  239. package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
  240. package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
  241. package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
  242. package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
  243. package/src/core/objects/procedure/procedure.diff.ts +404 -0
  244. package/src/core/objects/procedure/procedure.model.ts +264 -0
  245. package/src/core/objects/procedure/utils.ts +58 -0
  246. package/src/core/objects/publication/changes/publication.alter.test.ts +223 -0
  247. package/src/core/objects/publication/changes/publication.alter.ts +243 -0
  248. package/src/core/objects/publication/changes/publication.base.ts +20 -0
  249. package/src/core/objects/publication/changes/publication.comment.test.ts +70 -0
  250. package/src/core/objects/publication/changes/publication.comment.ts +64 -0
  251. package/src/core/objects/publication/changes/publication.create.test.ts +87 -0
  252. package/src/core/objects/publication/changes/publication.create.ts +82 -0
  253. package/src/core/objects/publication/changes/publication.drop.test.ts +46 -0
  254. package/src/core/objects/publication/changes/publication.drop.ts +29 -0
  255. package/src/core/objects/publication/changes/publication.types.ts +26 -0
  256. package/src/core/objects/publication/publication.diff.test.ts +292 -0
  257. package/src/core/objects/publication/publication.diff.ts +253 -0
  258. package/src/core/objects/publication/publication.model.ts +206 -0
  259. package/src/core/objects/publication/utils.ts +55 -0
  260. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +250 -0
  261. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
  262. package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
  263. package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
  264. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +74 -0
  265. package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
  266. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +28 -0
  267. package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
  268. package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
  269. package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
  270. package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
  271. package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
  272. package/src/core/objects/role/changes/role.alter.test.ts +346 -0
  273. package/src/core/objects/role/changes/role.alter.ts +110 -0
  274. package/src/core/objects/role/changes/role.base.ts +24 -0
  275. package/src/core/objects/role/changes/role.comment.ts +55 -0
  276. package/src/core/objects/role/changes/role.create.test.ts +52 -0
  277. package/src/core/objects/role/changes/role.create.ts +102 -0
  278. package/src/core/objects/role/changes/role.drop.test.ts +29 -0
  279. package/src/core/objects/role/changes/role.drop.ts +34 -0
  280. package/src/core/objects/role/changes/role.privilege.ts +376 -0
  281. package/src/core/objects/role/changes/role.types.ts +12 -0
  282. package/src/core/objects/role/role.diff.test.ts +44 -0
  283. package/src/core/objects/role/role.diff.ts +479 -0
  284. package/src/core/objects/role/role.model.ts +344 -0
  285. package/src/core/objects/rule/changes/rule.alter.test.ts +78 -0
  286. package/src/core/objects/rule/changes/rule.alter.ts +72 -0
  287. package/src/core/objects/rule/changes/rule.base.ts +20 -0
  288. package/src/core/objects/rule/changes/rule.comment.test.ts +55 -0
  289. package/src/core/objects/rule/changes/rule.comment.ts +62 -0
  290. package/src/core/objects/rule/changes/rule.create.test.ts +59 -0
  291. package/src/core/objects/rule/changes/rule.create.ts +42 -0
  292. package/src/core/objects/rule/changes/rule.drop.test.ts +38 -0
  293. package/src/core/objects/rule/changes/rule.drop.ts +29 -0
  294. package/src/core/objects/rule/changes/rule.types.ts +12 -0
  295. package/src/core/objects/rule/rule.diff.test.ts +132 -0
  296. package/src/core/objects/rule/rule.diff.ts +79 -0
  297. package/src/core/objects/rule/rule.model.ts +173 -0
  298. package/src/core/objects/schema/changes/schema.alter.test.ts +28 -0
  299. package/src/core/objects/schema/changes/schema.alter.ts +45 -0
  300. package/src/core/objects/schema/changes/schema.base.ts +20 -0
  301. package/src/core/objects/schema/changes/schema.comment.ts +56 -0
  302. package/src/core/objects/schema/changes/schema.create.test.ts +22 -0
  303. package/src/core/objects/schema/changes/schema.create.ts +47 -0
  304. package/src/core/objects/schema/changes/schema.drop.test.ts +20 -0
  305. package/src/core/objects/schema/changes/schema.drop.ts +34 -0
  306. package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
  307. package/src/core/objects/schema/changes/schema.types.ts +12 -0
  308. package/src/core/objects/schema/schema.diff.test.ts +42 -0
  309. package/src/core/objects/schema/schema.diff.ts +209 -0
  310. package/src/core/objects/schema/schema.model.ts +107 -0
  311. package/src/core/objects/sequence/changes/sequence.alter.test.ts +151 -0
  312. package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
  313. package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
  314. package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
  315. package/src/core/objects/sequence/changes/sequence.create.test.ts +84 -0
  316. package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
  317. package/src/core/objects/sequence/changes/sequence.drop.test.ts +32 -0
  318. package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
  319. package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
  320. package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
  321. package/src/core/objects/sequence/sequence.diff.test.ts +141 -0
  322. package/src/core/objects/sequence/sequence.diff.ts +359 -0
  323. package/src/core/objects/sequence/sequence.model.ts +185 -0
  324. package/src/core/objects/subscription/changes/subscription.alter.test.ts +124 -0
  325. package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
  326. package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
  327. package/src/core/objects/subscription/changes/subscription.comment.test.ts +67 -0
  328. package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
  329. package/src/core/objects/subscription/changes/subscription.create.test.ts +77 -0
  330. package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
  331. package/src/core/objects/subscription/changes/subscription.drop.test.ts +46 -0
  332. package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
  333. package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
  334. package/src/core/objects/subscription/subscription.diff.test.ts +232 -0
  335. package/src/core/objects/subscription/subscription.diff.ts +241 -0
  336. package/src/core/objects/subscription/subscription.model.ts +190 -0
  337. package/src/core/objects/subscription/utils.ts +156 -0
  338. package/src/core/objects/table/changes/table.alter.test.ts +823 -0
  339. package/src/core/objects/table/changes/table.alter.ts +806 -0
  340. package/src/core/objects/table/changes/table.base.ts +20 -0
  341. package/src/core/objects/table/changes/table.comment.ts +266 -0
  342. package/src/core/objects/table/changes/table.create.test.ts +150 -0
  343. package/src/core/objects/table/changes/table.create.ts +188 -0
  344. package/src/core/objects/table/changes/table.drop.test.ts +34 -0
  345. package/src/core/objects/table/changes/table.drop.ts +45 -0
  346. package/src/core/objects/table/changes/table.privilege.ts +200 -0
  347. package/src/core/objects/table/changes/table.types.ts +12 -0
  348. package/src/core/objects/table/table.diff.test.ts +711 -0
  349. package/src/core/objects/table/table.diff.ts +953 -0
  350. package/src/core/objects/table/table.model.ts +460 -0
  351. package/src/core/objects/trigger/changes/trigger.alter.test.ts +46 -0
  352. package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
  353. package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
  354. package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
  355. package/src/core/objects/trigger/changes/trigger.create.test.ts +43 -0
  356. package/src/core/objects/trigger/changes/trigger.create.ts +85 -0
  357. package/src/core/objects/trigger/changes/trigger.drop.test.ts +43 -0
  358. package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
  359. package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
  360. package/src/core/objects/trigger/trigger.diff.test.ts +83 -0
  361. package/src/core/objects/trigger/trigger.diff.ts +116 -0
  362. package/src/core/objects/trigger/trigger.model.ts +252 -0
  363. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +202 -0
  364. package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
  365. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
  366. package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
  367. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +101 -0
  368. package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
  369. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +33 -0
  370. package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
  371. package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
  372. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
  373. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +191 -0
  374. package/src/core/objects/type/composite-type/composite-type.diff.ts +372 -0
  375. package/src/core/objects/type/composite-type/composite-type.model.ts +252 -0
  376. package/src/core/objects/type/enum/changes/enum.alter.test.ts +104 -0
  377. package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
  378. package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
  379. package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
  380. package/src/core/objects/type/enum/changes/enum.create.test.ts +28 -0
  381. package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
  382. package/src/core/objects/type/enum/changes/enum.drop.test.ts +25 -0
  383. package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
  384. package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
  385. package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
  386. package/src/core/objects/type/enum/enum.diff.test.ts +191 -0
  387. package/src/core/objects/type/enum/enum.diff.ts +396 -0
  388. package/src/core/objects/type/enum/enum.model.ts +194 -0
  389. package/src/core/objects/type/range/changes/range.alter.test.ts +27 -0
  390. package/src/core/objects/type/range/changes/range.alter.ts +51 -0
  391. package/src/core/objects/type/range/changes/range.base.ts +20 -0
  392. package/src/core/objects/type/range/changes/range.comment.ts +64 -0
  393. package/src/core/objects/type/range/changes/range.create.test.ts +51 -0
  394. package/src/core/objects/type/range/changes/range.create.ts +151 -0
  395. package/src/core/objects/type/range/changes/range.drop.test.ts +26 -0
  396. package/src/core/objects/type/range/changes/range.drop.ts +34 -0
  397. package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
  398. package/src/core/objects/type/range/changes/range.types.ts +12 -0
  399. package/src/core/objects/type/range/range.diff.test.ts +70 -0
  400. package/src/core/objects/type/range/range.diff.ts +259 -0
  401. package/src/core/objects/type/range/range.model.ts +187 -0
  402. package/src/core/objects/type/type.types.ts +5 -0
  403. package/src/core/objects/utils.ts +171 -0
  404. package/src/core/objects/view/changes/view.alter.test.ts +110 -0
  405. package/src/core/objects/view/changes/view.alter.ts +112 -0
  406. package/src/core/objects/view/changes/view.base.ts +20 -0
  407. package/src/core/objects/view/changes/view.comment.ts +59 -0
  408. package/src/core/objects/view/changes/view.create.test.ts +65 -0
  409. package/src/core/objects/view/changes/view.create.ts +73 -0
  410. package/src/core/objects/view/changes/view.drop.test.ts +34 -0
  411. package/src/core/objects/view/changes/view.drop.ts +40 -0
  412. package/src/core/objects/view/changes/view.privilege.ts +200 -0
  413. package/src/core/objects/view/changes/view.types.ts +12 -0
  414. package/src/core/objects/view/view.diff.test.ts +91 -0
  415. package/src/core/objects/view/view.diff.ts +365 -0
  416. package/src/core/objects/view/view.model.ts +276 -0
  417. package/src/core/plan/apply.ts +190 -0
  418. package/src/core/plan/create.ts +432 -0
  419. package/src/core/plan/hierarchy.ts +574 -0
  420. package/src/core/plan/index.ts +29 -0
  421. package/src/core/plan/io.ts +20 -0
  422. package/src/core/plan/risk.ts +48 -0
  423. package/src/core/plan/serialize.ts +195 -0
  424. package/src/core/plan/sql-format/constants.ts +13 -0
  425. package/src/core/plan/sql-format/fixtures.ts +2806 -0
  426. package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
  427. package/src/core/plan/sql-format/format-functions.test.ts +127 -0
  428. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +67 -0
  429. package/src/core/plan/sql-format/format-off.test.ts +809 -0
  430. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1056 -0
  431. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1283 -0
  432. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1052 -0
  433. package/src/core/plan/sql-format/format-pretty-upper.test.ts +1045 -0
  434. package/src/core/plan/sql-format/format-stress.test.ts +616 -0
  435. package/src/core/plan/sql-format/format-utils.test.ts +91 -0
  436. package/src/core/plan/sql-format/format-utils.ts +391 -0
  437. package/src/core/plan/sql-format/formatters.ts +921 -0
  438. package/src/core/plan/sql-format/index.ts +149 -0
  439. package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
  440. package/src/core/plan/sql-format/keyword-case.ts +1085 -0
  441. package/src/core/plan/sql-format/protect.test.ts +127 -0
  442. package/src/core/plan/sql-format/protect.ts +337 -0
  443. package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
  444. package/src/core/plan/sql-format/sql-scanner.ts +252 -0
  445. package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
  446. package/src/core/plan/sql-format/tokenizer.ts +152 -0
  447. package/src/core/plan/sql-format/types.ts +31 -0
  448. package/src/core/plan/sql-format/wrap.test.ts +119 -0
  449. package/src/core/plan/sql-format/wrap.ts +196 -0
  450. package/src/core/plan/sql-format.ts +2 -0
  451. package/src/core/plan/statements.ts +22 -0
  452. package/src/core/plan/types.ts +165 -0
  453. package/src/core/postgres-config.ts +169 -0
  454. package/src/core/sort/custom-constraints.ts +161 -0
  455. package/src/core/sort/debug-visualization.ts +239 -0
  456. package/src/core/sort/dependency-filter.ts +224 -0
  457. package/src/core/sort/graph-builder.ts +223 -0
  458. package/src/core/sort/graph-utils.ts +51 -0
  459. package/src/core/sort/logical-sort.ts +590 -0
  460. package/src/core/sort/sort-changes.ts +234 -0
  461. package/src/core/sort/topological-sort.ts +184 -0
  462. package/src/core/sort/types.ts +112 -0
  463. package/src/core/sort/utils.ts +69 -0
  464. package/src/index.ts +14 -0
@@ -0,0 +1,590 @@
1
+ /**
2
+ * Logical pre-sorting for migration scripts.
3
+ *
4
+ * Groups changes by object type, stable ID, and scope to create a readable,
5
+ * logically organized migration script before dependency resolution.
6
+ *
7
+ * This is a pre-sorting step that runs before the dependency-based topological sort.
8
+ * It groups related changes together while preserving the ability for the dependency
9
+ * resolver to reorder within groups when necessary.
10
+ */
11
+
12
+ import type { Change } from "../change.types.ts";
13
+ import { getSchema } from "../integrations/filter/extractors.ts";
14
+ import { getExecutionPhase, isMetadataStableId, type Phase } from "./utils.ts";
15
+
16
+ /**
17
+ * Object type ordering for logical grouping.
18
+ * Lower numbers come first in the migration script.
19
+ */
20
+ const OBJECT_TYPE_ORDER: Record<string, number> = {
21
+ // CREATE/ALTER phase order (forward dependency)
22
+ schema: 1,
23
+ extension: 2,
24
+ role: 3,
25
+ language: 4,
26
+ collation: 5,
27
+ domain: 6,
28
+ enum: 7,
29
+ composite_type: 8,
30
+ range: 9,
31
+ sequence: 10,
32
+ procedure: 11,
33
+ aggregate: 12,
34
+ table: 13,
35
+ index: 14, // Grouped with tables/materialized views
36
+ view: 15,
37
+ materialized_view: 16,
38
+ trigger: 17, // Grouped with tables
39
+ rls_policy: 18, // Grouped with tables
40
+ rule: 19, // Grouped with tables/views
41
+ event_trigger: 20,
42
+ publication: 21,
43
+ subscription: 22,
44
+ };
45
+
46
+ /**
47
+ * Scope ordering within each stable ID group.
48
+ * Lower numbers come first.
49
+ */
50
+ const SCOPE_ORDER_CREATE_ALTER: Record<string, number> = {
51
+ default_privilege: 1,
52
+ object: 2,
53
+ comment: 3,
54
+ privilege: 4,
55
+ membership: 5,
56
+ };
57
+
58
+ const SCOPE_ORDER_DROP: Record<string, number> = {
59
+ privilege: 1,
60
+ comment: 2,
61
+ object: 3,
62
+ };
63
+
64
+ /**
65
+ * Sub-entity object types that should be grouped by their parent's stable ID.
66
+ */
67
+ const SUB_ENTITY_TYPES = new Set(["index", "trigger", "rls_policy", "rule"]);
68
+
69
+ /**
70
+ * Regex for parsing stable IDs.
71
+ */
72
+ const CONSTRAINT_REGEX = /^constraint:([^.]+)\.([^.]+)\./;
73
+ const COLUMN_REGEX = /^column:([^.]+)\.([^.]+)\./;
74
+
75
+ /**
76
+ * Find the object stable ID from an array of stable IDs, skipping metadata stable IDs.
77
+ * Iterates through all stable IDs to find the first non-metadata one.
78
+ */
79
+ function findObjectStableId(stableIds: string[]): string | null {
80
+ for (const id of stableIds) {
81
+ if (!isMetadataStableId(id)) {
82
+ return id;
83
+ }
84
+ }
85
+ // If all are metadata, return null (shouldn't happen, but safe fallback)
86
+ return stableIds.length > 0 ? stableIds[0] : null;
87
+ }
88
+
89
+ /**
90
+ * Extract the main stable ID that a change is touching.
91
+ *
92
+ * For sub-entities (indexes, triggers, constraints, etc.), returns the parent's stable ID.
93
+ * For other changes, returns the primary stable ID being created/dropped/modified.
94
+ */
95
+ function getMainStableId(change: Change): string | null {
96
+ // For sub-entities, extract parent stable ID from requires
97
+ if (SUB_ENTITY_TYPES.has(change.objectType)) {
98
+ return getParentStableId(change);
99
+ }
100
+
101
+ // For metadata operations (comment, privilege): use requires to find object stable ID
102
+ // Check these BEFORE CREATE/DROP/ALTER logic to ensure they group with their target objects
103
+ if (change.scope === "comment" || change.scope === "privilege") {
104
+ // For CREATE comments/privileges: check creates first, but extract object stable ID from requires
105
+ if (change.operation === "create" && change.creates.length > 0) {
106
+ const createdId = change.creates[0];
107
+ // If creating a comment/privilege, find the object stable ID from requires
108
+ if (isMetadataStableId(createdId)) {
109
+ const objectId = findObjectStableId(change.requires);
110
+ if (objectId) {
111
+ // Check if commenting on a constraint - extract table from it
112
+ if (objectId.startsWith("constraint:")) {
113
+ const match = objectId.match(CONSTRAINT_REGEX);
114
+ if (match) {
115
+ const [, schema, table] = match;
116
+ return `table:${schema}.${table}`;
117
+ }
118
+ }
119
+ // Check if commenting on a column - extract table from it
120
+ // Format: column:schema.table.column
121
+ if (objectId.startsWith("column:")) {
122
+ const match = objectId.match(COLUMN_REGEX);
123
+ if (match) {
124
+ const [, schema, table] = match;
125
+ return `table:${schema}.${table}`;
126
+ }
127
+ }
128
+ return objectId;
129
+ }
130
+ }
131
+ }
132
+ // For DROP/ALTER comments/privileges: find object stable ID from requires
133
+ if (change.requires.length > 0) {
134
+ const objectId = findObjectStableId(change.requires);
135
+ if (objectId) {
136
+ // Check if commenting on a constraint - extract table from it
137
+ if (objectId.startsWith("constraint:")) {
138
+ const match = objectId.match(CONSTRAINT_REGEX);
139
+ if (match) {
140
+ const [, schema, table] = match;
141
+ return `table:${schema}.${table}`;
142
+ }
143
+ }
144
+ // Check if commenting on a column - extract table from it
145
+ // Format: column:schema.table.column
146
+ if (objectId.startsWith("column:")) {
147
+ const match = objectId.match(COLUMN_REGEX);
148
+ if (match) {
149
+ const [, schema, table] = match;
150
+ return `table:${schema}.${table}`;
151
+ }
152
+ }
153
+ return objectId;
154
+ }
155
+ }
156
+ return null;
157
+ }
158
+
159
+ // For CREATE operations: check if creating a constraint (sub-entity of table)
160
+ if (change.operation === "create" && change.creates.length > 0) {
161
+ // Iterate through creates to find the first non-metadata stable ID
162
+ const createdId = findObjectStableId(change.creates);
163
+ if (createdId) {
164
+ if (createdId.startsWith("constraint:")) {
165
+ // Extract table stable ID from constraint stable ID
166
+ // Format: constraint:schema.table.constraint_name
167
+ const match = createdId.match(CONSTRAINT_REGEX);
168
+ if (match) {
169
+ const [, schema, table] = match;
170
+ return `table:${schema}.${table}`;
171
+ }
172
+ }
173
+ return createdId;
174
+ }
175
+ // Fallback: if all creates are metadata (shouldn't happen for non-comment scopes), use first
176
+ return change.creates[0] ?? null;
177
+ }
178
+
179
+ // For DROP operations: check if dropping a constraint (sub-entity of table)
180
+ if (change.operation === "drop" && change.drops.length > 0) {
181
+ // Iterate through drops to find the first non-metadata stable ID
182
+ const droppedId = findObjectStableId(change.drops);
183
+ if (droppedId) {
184
+ if (droppedId.startsWith("constraint:")) {
185
+ // Extract table stable ID from constraint stable ID
186
+ const match = droppedId.match(CONSTRAINT_REGEX);
187
+ if (match) {
188
+ const [, schema, table] = match;
189
+ return `table:${schema}.${table}`;
190
+ }
191
+ }
192
+ return droppedId;
193
+ }
194
+ // Fallback: if all drops are metadata, use first
195
+ return change.drops[0] ?? null;
196
+ }
197
+
198
+ // For default_privilege operations: group by role + schema combination
199
+ // This groups all "FOR ROLE X IN SCHEMA Y" statements together
200
+ if (change.scope === "default_privilege") {
201
+ if (change.requires.length > 0) {
202
+ // Iterate through requires to find role and schema
203
+ let grantingRole: string | null = null;
204
+ let schemaId: string | null = null;
205
+
206
+ for (const id of change.requires) {
207
+ if (id.startsWith("role:")) {
208
+ grantingRole = id;
209
+ } else if (id.startsWith("schema:")) {
210
+ schemaId = id;
211
+ }
212
+ }
213
+
214
+ if (schemaId && grantingRole) {
215
+ // Create composite key: "role:postgres:schema:public"
216
+ return `${grantingRole}:${schemaId}`;
217
+ }
218
+ // If no schema, just group by role
219
+ return grantingRole ?? null;
220
+ }
221
+ }
222
+
223
+ // For ALTER operations: check if creating/dropping a constraint
224
+ // Skip this for privilege/comment/default_privilege scopes (handled above)
225
+ if (change.operation === "alter") {
226
+ // Check creates first (ADD CONSTRAINT, ADD COLUMN, etc.)
227
+ if (change.creates.length > 0) {
228
+ const createdId = findObjectStableId(change.creates);
229
+ if (createdId) {
230
+ if (createdId.startsWith("constraint:")) {
231
+ const match = createdId.match(CONSTRAINT_REGEX);
232
+ if (match) {
233
+ const [, schema, table] = match;
234
+ return `table:${schema}.${table}`;
235
+ }
236
+ }
237
+ // Extract table stable ID from column stable IDs (for ALTER TABLE ADD COLUMN)
238
+ // Format: column:schema.table.column
239
+ if (createdId.startsWith("column:")) {
240
+ const match = createdId.match(COLUMN_REGEX);
241
+ if (match) {
242
+ const [, schema, table] = match;
243
+ return `table:${schema}.${table}`;
244
+ }
245
+ }
246
+ return createdId;
247
+ }
248
+ // Fallback: if all creates are metadata, use first
249
+ return change.creates[0] ?? null;
250
+ }
251
+ // Check drops (DROP CONSTRAINT)
252
+ if (change.drops && change.drops.length > 0) {
253
+ const droppedId = findObjectStableId(change.drops);
254
+ if (droppedId) {
255
+ if (droppedId.startsWith("constraint:")) {
256
+ const match = droppedId.match(CONSTRAINT_REGEX);
257
+ if (match) {
258
+ const [, schema, table] = match;
259
+ return `table:${schema}.${table}`;
260
+ }
261
+ }
262
+ return droppedId;
263
+ }
264
+ // Fallback: if all drops are metadata, use first
265
+ return change.drops[0] ?? null;
266
+ }
267
+ // Otherwise use requires (VALIDATE CONSTRAINT, etc.)
268
+ if (change.requires.length > 0) {
269
+ const requiredId = findObjectStableId(change.requires);
270
+ if (requiredId) {
271
+ // Check if requiring a constraint - extract table from it
272
+ if (requiredId.startsWith("constraint:")) {
273
+ const match = requiredId.match(CONSTRAINT_REGEX);
274
+ if (match) {
275
+ const [, schema, table] = match;
276
+ return `table:${schema}.${table}`;
277
+ }
278
+ }
279
+ return requiredId;
280
+ }
281
+ // Fallback: if all requires are metadata, use first
282
+ return change.requires[0] ?? null;
283
+ }
284
+ }
285
+
286
+ // Fallback: try requires if available
287
+ if (change.requires.length > 0) {
288
+ return findObjectStableId(change.requires) ?? null;
289
+ }
290
+
291
+ return null;
292
+ }
293
+
294
+ /**
295
+ * Extract parent stable ID for sub-entities (indexes, triggers, RLS policies, rules).
296
+ *
297
+ * Looks for table/view/materialized view stable IDs in the change's requirements.
298
+ */
299
+ function getParentStableId(change: Change): string | null {
300
+ const requires = change.requires;
301
+
302
+ // Look for table, view, or materialized view stable IDs
303
+ for (const stableId of requires) {
304
+ if (
305
+ stableId.startsWith("table:") ||
306
+ stableId.startsWith("view:") ||
307
+ stableId.startsWith("materializedView:")
308
+ ) {
309
+ return stableId;
310
+ }
311
+ }
312
+
313
+ // Fallback: return first requires if available
314
+ return requires.length > 0 ? requires[0] : null;
315
+ }
316
+
317
+ /**
318
+ * Extract schema name from a change.
319
+ * Returns the schema name if present, or null for non-schema objects.
320
+ *
321
+ * Uses the getSchema helper which directly accesses schema properties from change objects.
322
+ * For default_privilege changes, accesses the inSchema property directly.
323
+ * For event_trigger changes, groups by their function's schema.
324
+ */
325
+ function extractSchemaFromChange(change: Change): string | null {
326
+ // Handle default_privilege changes specially (they have inSchema property)
327
+ if (change.scope === "default_privilege") {
328
+ // TypeScript doesn't know about inSchema, but we know it exists for default_privilege changes
329
+ return (change as { inSchema: string | null }).inSchema ?? null;
330
+ }
331
+
332
+ // Handle event_trigger changes specially - group by their function's schema
333
+ if (change.objectType === "event_trigger") {
334
+ return change.eventTrigger.function_schema;
335
+ }
336
+
337
+ // Use the getSchema helper for all other changes
338
+ return getSchema(change);
339
+ }
340
+
341
+ /**
342
+ * Get the effective object type for sorting purposes.
343
+ * For sub-entities, returns the parent's object type (table/view/materialized_view).
344
+ * For other objects, returns the object type as-is.
345
+ */
346
+ function getEffectiveObjectType(change: Change): string {
347
+ // For sub-entities, determine parent type from stable ID
348
+ if (SUB_ENTITY_TYPES.has(change.objectType)) {
349
+ const parentStableId = getParentStableId(change);
350
+ if (parentStableId) {
351
+ if (parentStableId.startsWith("table:")) {
352
+ return "table";
353
+ }
354
+ if (parentStableId.startsWith("view:")) {
355
+ return "view";
356
+ }
357
+ if (parentStableId.startsWith("materializedView:")) {
358
+ return "materialized_view";
359
+ }
360
+ }
361
+ }
362
+ return change.objectType;
363
+ }
364
+
365
+ /**
366
+ * Get the object type order for sorting.
367
+ * Returns a high number for unknown types to sort them last.
368
+ */
369
+ function getObjectTypeOrder(objectType: string): number {
370
+ return OBJECT_TYPE_ORDER[objectType] ?? 999;
371
+ }
372
+
373
+ /**
374
+ * Get the scope order for sorting within a stable ID group.
375
+ */
376
+ function getScopeOrder(scope: string, phase: Phase): number {
377
+ const orderMap =
378
+ phase === "drop" ? SCOPE_ORDER_DROP : SCOPE_ORDER_CREATE_ALTER;
379
+ return orderMap[scope] ?? 999;
380
+ }
381
+
382
+ /**
383
+ * Logically pre-sort changes by grouping them into a readable structure.
384
+ *
385
+ * Groups changes by:
386
+ * 1. Phase (DROP vs CREATE/ALTER)
387
+ * 2. Object type (schema, table, index, etc.)
388
+ * 3. Main stable ID (table:public.users, etc.)
389
+ * 4. Scope (object, comment, privilege, etc.)
390
+ *
391
+ * Within each group, preserves the original order (stability).
392
+ *
393
+ * @param changes - Array of changes to sort
394
+ * @returns Logically grouped and sorted array of changes
395
+ */
396
+ export function logicalSort(changes: Change[]): Change[] {
397
+ if (changes.length === 0) {
398
+ return changes;
399
+ }
400
+
401
+ // Step 1: Partition by phase
402
+ const changesByPhase: Record<Phase, Change[]> = {
403
+ drop: [],
404
+ create_alter_object: [],
405
+ };
406
+
407
+ for (const change of changes) {
408
+ const phase = getExecutionPhase(change);
409
+ changesByPhase[phase].push(change);
410
+ }
411
+
412
+ // Step 2: Sort each phase
413
+ const sortedDrop = sortPhase(changesByPhase.drop, "drop");
414
+ const sortedCreateAlter = sortPhase(
415
+ changesByPhase.create_alter_object,
416
+ "create_alter_object",
417
+ );
418
+
419
+ // Step 3: Combine phases (DROP first, then CREATE/ALTER)
420
+ return [...sortedDrop, ...sortedCreateAlter];
421
+ }
422
+
423
+ /**
424
+ * Sort changes within a phase by object type, stable ID, and scope.
425
+ */
426
+ function sortPhase(changes: Change[], phase: Phase): Change[] {
427
+ if (changes.length === 0) {
428
+ return changes;
429
+ }
430
+
431
+ // Create a map to preserve original indices for stability
432
+ const changesWithIndices = changes.map((change, index) => ({
433
+ change,
434
+ originalIndex: index,
435
+ }));
436
+
437
+ // Sort by: schema → effective object type (only when schemas differ) → stable ID → actual object type → scope → original index
438
+ // Schema groups all objects within the same schema together
439
+ // Effective object type ensures schemas come before tables when comparing across schemas
440
+ // Stable ID groups sub-entities with their parents
441
+ // Actual object type orders sub-entities within their parent group
442
+ changesWithIndices.sort((a, b) => {
443
+ const changeA = a.change;
444
+ const changeB = b.change;
445
+
446
+ // 1. Compare schemas (group objects by schema)
447
+ const schemaA = extractSchemaFromChange(changeA);
448
+ const schemaB = extractSchemaFromChange(changeB);
449
+
450
+ // Non-schema objects (roles, languages, extensions, etc.) sort first
451
+ // Use a special prefix to ensure they come before schema objects
452
+ const schemaKeyA = schemaA === null ? "::" : schemaA;
453
+ const schemaKeyB = schemaB === null ? "::" : schemaB;
454
+ const schemaCompare = schemaKeyA.localeCompare(schemaKeyB);
455
+ if (schemaCompare !== 0) {
456
+ return schemaCompare;
457
+ }
458
+
459
+ // 2. Compare effective object types (parent type for sub-entities)
460
+ // Only apply this ordering when schemas differ (for cross-schema ordering)
461
+ // Within the same schema, we want all objects grouped together
462
+ const effectiveTypeA = getEffectiveObjectType(changeA);
463
+ const effectiveTypeB = getEffectiveObjectType(changeB);
464
+ const effectiveTypeOrderA = getObjectTypeOrder(effectiveTypeA);
465
+ const effectiveTypeOrderB = getObjectTypeOrder(effectiveTypeB);
466
+ if (effectiveTypeOrderA !== effectiveTypeOrderB) {
467
+ return effectiveTypeOrderA - effectiveTypeOrderB;
468
+ }
469
+
470
+ // 3. Compare main stable IDs (groups sub-entities with parents)
471
+ const stableIdA = getMainStableId(changeA);
472
+ const stableIdB = getMainStableId(changeB);
473
+ const stableIdCompare = (stableIdA ?? "").localeCompare(stableIdB ?? "");
474
+ if (stableIdCompare !== 0) {
475
+ return stableIdCompare;
476
+ }
477
+
478
+ // 4. Compare actual object types (orders sub-entities within parent group)
479
+ const typeOrderA = getObjectTypeOrder(changeA.objectType);
480
+ const typeOrderB = getObjectTypeOrder(changeB.objectType);
481
+ if (typeOrderA !== typeOrderB) {
482
+ return typeOrderA - typeOrderB;
483
+ }
484
+
485
+ // 5. Compare scopes (within same stable ID and object type)
486
+ // Special handling: comments should come after CREATE object but before ALTER object
487
+ const scopeA = changeA.scope;
488
+ const scopeB = changeB.scope;
489
+ const operationA = changeA.operation;
490
+ const operationB = changeB.operation;
491
+
492
+ // Special case: if one is "object" scope and one is "comment" scope
493
+ if (scopeA === "object" && scopeB === "comment") {
494
+ // Comment comes after CREATE object, but before ALTER object
495
+ if (operationA === "create") {
496
+ return -1; // CREATE object comes before comment (A < B)
497
+ } else if (operationA === "alter") {
498
+ return 1; // ALTER object comes after comment (A > B)
499
+ }
500
+ } else if (scopeA === "comment" && scopeB === "object") {
501
+ // Comment comes after CREATE object, but before ALTER object
502
+ if (operationB === "create") {
503
+ return 1; // CREATE object comes before comment (B < A, so A > B)
504
+ } else if (operationB === "alter") {
505
+ return -1; // ALTER object comes after comment (B > A, so A < B)
506
+ }
507
+ }
508
+
509
+ // Special case: if one is ALTER TABLE ADD COLUMN and one is a column comment for that column
510
+ // Column comment should come right after ADD COLUMN
511
+ if (
512
+ scopeA === "object" &&
513
+ operationA === "alter" &&
514
+ changeA.creates.length > 0 &&
515
+ changeA.creates[0]?.startsWith("column:")
516
+ ) {
517
+ // This is ALTER TABLE ADD COLUMN
518
+ const addedColumnId = changeA.creates[0];
519
+ if (scopeB === "comment" && changeB.requires.length > 0) {
520
+ const commentColumnId = changeB.requires[0];
521
+ if (commentColumnId === addedColumnId) {
522
+ return -1; // ADD COLUMN comes before its column comment
523
+ }
524
+ }
525
+ }
526
+ if (
527
+ scopeB === "object" &&
528
+ operationB === "alter" &&
529
+ changeB.creates.length > 0 &&
530
+ changeB.creates[0]?.startsWith("column:")
531
+ ) {
532
+ // This is ALTER TABLE ADD COLUMN
533
+ const addedColumnId = changeB.creates[0];
534
+ if (scopeA === "comment" && changeA.requires.length > 0) {
535
+ const commentColumnId = changeA.requires[0];
536
+ if (commentColumnId === addedColumnId) {
537
+ return 1; // Column comment comes after ADD COLUMN
538
+ }
539
+ }
540
+ }
541
+
542
+ // Special case: if both are comments, ensure table comments come before column comments
543
+ if (scopeA === "comment" && scopeB === "comment") {
544
+ // Check if one is a table comment and one is a column comment
545
+ const requiresA =
546
+ changeA.requires.length > 0 ? changeA.requires[0] : null;
547
+ const requiresB =
548
+ changeB.requires.length > 0 ? changeB.requires[0] : null;
549
+
550
+ // Table comments require table stable ID, column comments require column stable ID
551
+ const isTableCommentA = requiresA?.startsWith("table:");
552
+ const isTableCommentB = requiresB?.startsWith("table:");
553
+ const isColumnCommentA = requiresA?.startsWith("column:");
554
+ const isColumnCommentB = requiresB?.startsWith("column:");
555
+
556
+ // Table comments come before column comments
557
+ if (isTableCommentA && isColumnCommentB) {
558
+ return -1; // Table comment comes before column comment
559
+ }
560
+ if (isColumnCommentA && isTableCommentB) {
561
+ return 1; // Column comment comes after table comment
562
+ }
563
+ }
564
+
565
+ // Default scope comparison
566
+ const scopeOrderA = getScopeOrder(scopeA, phase);
567
+ const scopeOrderB = getScopeOrder(scopeB, phase);
568
+ if (scopeOrderA !== scopeOrderB) {
569
+ return scopeOrderA - scopeOrderB;
570
+ }
571
+
572
+ // 6. Compare operations (CREATE before ALTER within same stable ID, scope, and object type)
573
+ // This ensures CREATE ROLE comes before ALTER ROLE, CREATE SCHEMA before GRANT, etc.
574
+ const operationOrder: Record<string, number> = {
575
+ create: 1,
576
+ alter: 2,
577
+ drop: 3,
578
+ };
579
+ const operationOrderA = operationOrder[operationA] ?? 999;
580
+ const operationOrderB = operationOrder[operationB] ?? 999;
581
+ if (operationOrderA !== operationOrderB) {
582
+ return operationOrderA - operationOrderB;
583
+ }
584
+
585
+ // 7. Preserve original order (stability)
586
+ return a.originalIndex - b.originalIndex;
587
+ });
588
+
589
+ return changesWithIndices.map((item) => item.change);
590
+ }