@supabase/pg-delta 1.0.0-alpha.3 → 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 (463) 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/objects/table/table.model.d.ts +4 -2
  7. package/dist/core/objects/table/table.model.js +3 -0
  8. package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
  9. package/dist/core/objects/trigger/changes/trigger.create.js +2 -1
  10. package/dist/core/objects/trigger/trigger.model.d.ts +1 -0
  11. package/dist/core/objects/trigger/trigger.model.js +3 -0
  12. package/dist/core/plan/apply.js +3 -3
  13. package/dist/core/plan/create.js +34 -15
  14. package/dist/core/plan/sql-format/constants.d.ts +2 -0
  15. package/dist/core/plan/sql-format/constants.js +11 -0
  16. package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
  17. package/dist/core/plan/sql-format/fixtures.js +2449 -0
  18. package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
  19. package/dist/core/plan/sql-format/format-utils.js +274 -0
  20. package/dist/core/plan/sql-format/formatters.d.ts +20 -0
  21. package/dist/core/plan/sql-format/formatters.js +737 -0
  22. package/dist/core/plan/sql-format/index.d.ts +2 -0
  23. package/dist/core/plan/sql-format/index.js +98 -0
  24. package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
  25. package/dist/core/plan/sql-format/keyword-case.js +868 -0
  26. package/dist/core/plan/sql-format/protect.d.ts +3 -0
  27. package/dist/core/plan/sql-format/protect.js +269 -0
  28. package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
  29. package/dist/core/plan/sql-format/sql-scanner.js +202 -0
  30. package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
  31. package/dist/core/plan/sql-format/tokenizer.js +118 -0
  32. package/dist/core/plan/sql-format/types.d.ts +28 -0
  33. package/dist/core/plan/sql-format/types.js +1 -0
  34. package/dist/core/plan/sql-format/wrap.d.ts +2 -0
  35. package/dist/core/plan/sql-format/wrap.js +165 -0
  36. package/dist/core/plan/sql-format.d.ts +2 -0
  37. package/dist/core/plan/sql-format.js +1 -0
  38. package/dist/core/plan/statements.d.ts +2 -1
  39. package/dist/core/plan/statements.js +6 -2
  40. package/dist/core/postgres-config.d.ts +15 -0
  41. package/dist/core/postgres-config.js +30 -0
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.js +1 -0
  44. package/package.json +37 -22
  45. package/src/cli/app.ts +28 -0
  46. package/src/cli/bin/cli.ts +9 -0
  47. package/src/cli/commands/apply.ts +101 -0
  48. package/src/cli/commands/plan.ts +195 -0
  49. package/src/cli/commands/sync.ts +185 -0
  50. package/src/cli/formatters/index.ts +5 -0
  51. package/src/cli/formatters/tree/tree-builder.ts +380 -0
  52. package/src/cli/formatters/tree/tree-renderer.ts +372 -0
  53. package/src/cli/formatters/tree/tree.ts +237 -0
  54. package/src/cli/utils/integrations.ts +42 -0
  55. package/src/cli/utils.ts +231 -0
  56. package/src/core/catalog.diff.ts +246 -0
  57. package/src/core/catalog.model.ts +384 -0
  58. package/src/core/change.types.ts +44 -0
  59. package/src/core/context.ts +26 -0
  60. package/src/core/depend.ts +1870 -0
  61. package/src/core/expand-replace-dependencies.ts +380 -0
  62. package/src/core/fingerprint.ts +204 -0
  63. package/src/core/integrations/filter/dsl.ts +204 -0
  64. package/src/core/integrations/filter/extractors.ts +145 -0
  65. package/src/core/integrations/filter/filter.types.ts +3 -0
  66. package/src/core/integrations/integration-dsl.ts +24 -0
  67. package/src/core/integrations/integration.types.ts +7 -0
  68. package/src/core/integrations/serialize/dsl.ts +77 -0
  69. package/src/core/integrations/serialize/serialize.types.ts +3 -0
  70. package/src/core/integrations/supabase.ts +121 -0
  71. package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
  72. package/src/core/objects/aggregate/aggregate.diff.ts +278 -0
  73. package/src/core/objects/aggregate/aggregate.model.ts +317 -0
  74. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +64 -0
  75. package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
  76. package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
  77. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +86 -0
  78. package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
  79. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +101 -0
  80. package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
  81. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +78 -0
  82. package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
  83. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +130 -0
  84. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
  85. package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
  86. package/src/core/objects/base.change.ts +62 -0
  87. package/src/core/objects/base.default-privileges.ts +204 -0
  88. package/src/core/objects/base.diff.ts +20 -0
  89. package/src/core/objects/base.model.ts +82 -0
  90. package/src/core/objects/base.privilege-diff.ts +299 -0
  91. package/src/core/objects/base.privilege.ts +184 -0
  92. package/src/core/objects/collation/changes/collation.alter.test.ts +63 -0
  93. package/src/core/objects/collation/changes/collation.alter.ts +79 -0
  94. package/src/core/objects/collation/changes/collation.base.ts +20 -0
  95. package/src/core/objects/collation/changes/collation.comment.ts +68 -0
  96. package/src/core/objects/collation/changes/collation.create.test.ts +51 -0
  97. package/src/core/objects/collation/changes/collation.create.ts +106 -0
  98. package/src/core/objects/collation/changes/collation.drop.test.ts +28 -0
  99. package/src/core/objects/collation/changes/collation.drop.ts +37 -0
  100. package/src/core/objects/collation/changes/collation.types.ts +10 -0
  101. package/src/core/objects/collation/collation.diff.test.ts +100 -0
  102. package/src/core/objects/collation/collation.diff.ts +126 -0
  103. package/src/core/objects/collation/collation.model.ts +224 -0
  104. package/src/core/objects/domain/changes/domain.alter.test.ts +316 -0
  105. package/src/core/objects/domain/changes/domain.alter.ts +286 -0
  106. package/src/core/objects/domain/changes/domain.base.ts +20 -0
  107. package/src/core/objects/domain/changes/domain.comment.ts +59 -0
  108. package/src/core/objects/domain/changes/domain.create.test.ts +65 -0
  109. package/src/core/objects/domain/changes/domain.create.ts +118 -0
  110. package/src/core/objects/domain/changes/domain.drop.test.ts +30 -0
  111. package/src/core/objects/domain/changes/domain.drop.ts +34 -0
  112. package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
  113. package/src/core/objects/domain/changes/domain.types.ts +12 -0
  114. package/src/core/objects/domain/domain.diff.test.ts +284 -0
  115. package/src/core/objects/domain/domain.diff.ts +358 -0
  116. package/src/core/objects/domain/domain.model.ts +190 -0
  117. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +50 -0
  118. package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
  119. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
  120. package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
  121. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +24 -0
  122. package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
  123. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +22 -0
  124. package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
  125. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
  126. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +126 -0
  127. package/src/core/objects/event-trigger/event-trigger.diff.ts +126 -0
  128. package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
  129. package/src/core/objects/extension/changes/extension.alter.test.ts +58 -0
  130. package/src/core/objects/extension/changes/extension.alter.ts +78 -0
  131. package/src/core/objects/extension/changes/extension.base.ts +20 -0
  132. package/src/core/objects/extension/changes/extension.comment.ts +64 -0
  133. package/src/core/objects/extension/changes/extension.create.test.ts +25 -0
  134. package/src/core/objects/extension/changes/extension.create.ts +63 -0
  135. package/src/core/objects/extension/changes/extension.drop.test.ts +23 -0
  136. package/src/core/objects/extension/changes/extension.drop.ts +34 -0
  137. package/src/core/objects/extension/changes/extension.types.ts +10 -0
  138. package/src/core/objects/extension/extension.diff.test.ts +42 -0
  139. package/src/core/objects/extension/extension.diff.ts +90 -0
  140. package/src/core/objects/extension/extension.model.ts +280 -0
  141. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +125 -0
  142. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
  143. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
  144. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
  145. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +125 -0
  146. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
  147. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +23 -0
  148. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
  149. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
  150. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
  151. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +179 -0
  152. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +341 -0
  153. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
  154. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
  155. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +309 -0
  156. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
  157. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
  158. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
  159. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +201 -0
  160. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
  161. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +43 -0
  162. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
  163. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
  164. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
  165. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
  166. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +406 -0
  167. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
  168. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +168 -0
  169. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
  170. package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
  171. package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
  172. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +131 -0
  173. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
  174. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +24 -0
  175. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
  176. package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
  177. package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
  178. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +167 -0
  179. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +317 -0
  180. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
  181. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +82 -0
  182. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
  183. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
  184. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +85 -0
  185. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
  186. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +53 -0
  187. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
  188. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
  189. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
  190. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
  191. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
  192. package/src/core/objects/index/changes/index.alter.test.ts +200 -0
  193. package/src/core/objects/index/changes/index.alter.ts +144 -0
  194. package/src/core/objects/index/changes/index.base.ts +20 -0
  195. package/src/core/objects/index/changes/index.comment.ts +63 -0
  196. package/src/core/objects/index/changes/index.create.test.ts +66 -0
  197. package/src/core/objects/index/changes/index.create.ts +68 -0
  198. package/src/core/objects/index/changes/index.drop.test.ts +44 -0
  199. package/src/core/objects/index/changes/index.drop.ts +34 -0
  200. package/src/core/objects/index/changes/index.types.ts +6 -0
  201. package/src/core/objects/index/changes/utils.ts +16 -0
  202. package/src/core/objects/index/index.diff.test.ts +153 -0
  203. package/src/core/objects/index/index.diff.ts +243 -0
  204. package/src/core/objects/index/index.model.ts +370 -0
  205. package/src/core/objects/language/changes/language.alter.test.ts +33 -0
  206. package/src/core/objects/language/changes/language.alter.ts +53 -0
  207. package/src/core/objects/language/changes/language.base.ts +20 -0
  208. package/src/core/objects/language/changes/language.comment.ts +58 -0
  209. package/src/core/objects/language/changes/language.create.test.ts +27 -0
  210. package/src/core/objects/language/changes/language.create.ts +104 -0
  211. package/src/core/objects/language/changes/language.drop.test.ts +25 -0
  212. package/src/core/objects/language/changes/language.drop.ts +39 -0
  213. package/src/core/objects/language/changes/language.privilege.ts +172 -0
  214. package/src/core/objects/language/changes/language.types.ts +12 -0
  215. package/src/core/objects/language/language.diff.test.ts +53 -0
  216. package/src/core/objects/language/language.diff.ts +176 -0
  217. package/src/core/objects/language/language.model.ts +150 -0
  218. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +123 -0
  219. package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
  220. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
  221. package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
  222. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +64 -0
  223. package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
  224. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +34 -0
  225. package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
  226. package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
  227. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
  228. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +102 -0
  229. package/src/core/objects/materialized-view/materialized-view.diff.ts +451 -0
  230. package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
  231. package/src/core/objects/procedure/changes/procedure.alter.test.ts +1005 -0
  232. package/src/core/objects/procedure/changes/procedure.alter.ts +287 -0
  233. package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
  234. package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
  235. package/src/core/objects/procedure/changes/procedure.create.test.ts +48 -0
  236. package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
  237. package/src/core/objects/procedure/changes/procedure.drop.test.ts +85 -0
  238. package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
  239. package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
  240. package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
  241. package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
  242. package/src/core/objects/procedure/procedure.diff.ts +404 -0
  243. package/src/core/objects/procedure/procedure.model.ts +264 -0
  244. package/src/core/objects/procedure/utils.ts +58 -0
  245. package/src/core/objects/publication/changes/publication.alter.test.ts +223 -0
  246. package/src/core/objects/publication/changes/publication.alter.ts +243 -0
  247. package/src/core/objects/publication/changes/publication.base.ts +20 -0
  248. package/src/core/objects/publication/changes/publication.comment.test.ts +70 -0
  249. package/src/core/objects/publication/changes/publication.comment.ts +64 -0
  250. package/src/core/objects/publication/changes/publication.create.test.ts +87 -0
  251. package/src/core/objects/publication/changes/publication.create.ts +82 -0
  252. package/src/core/objects/publication/changes/publication.drop.test.ts +46 -0
  253. package/src/core/objects/publication/changes/publication.drop.ts +29 -0
  254. package/src/core/objects/publication/changes/publication.types.ts +26 -0
  255. package/src/core/objects/publication/publication.diff.test.ts +292 -0
  256. package/src/core/objects/publication/publication.diff.ts +253 -0
  257. package/src/core/objects/publication/publication.model.ts +206 -0
  258. package/src/core/objects/publication/utils.ts +55 -0
  259. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +250 -0
  260. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
  261. package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
  262. package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
  263. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +74 -0
  264. package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
  265. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +28 -0
  266. package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
  267. package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
  268. package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
  269. package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
  270. package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
  271. package/src/core/objects/role/changes/role.alter.test.ts +346 -0
  272. package/src/core/objects/role/changes/role.alter.ts +110 -0
  273. package/src/core/objects/role/changes/role.base.ts +24 -0
  274. package/src/core/objects/role/changes/role.comment.ts +55 -0
  275. package/src/core/objects/role/changes/role.create.test.ts +52 -0
  276. package/src/core/objects/role/changes/role.create.ts +102 -0
  277. package/src/core/objects/role/changes/role.drop.test.ts +29 -0
  278. package/src/core/objects/role/changes/role.drop.ts +34 -0
  279. package/src/core/objects/role/changes/role.privilege.ts +376 -0
  280. package/src/core/objects/role/changes/role.types.ts +12 -0
  281. package/src/core/objects/role/role.diff.test.ts +44 -0
  282. package/src/core/objects/role/role.diff.ts +479 -0
  283. package/src/core/objects/role/role.model.ts +344 -0
  284. package/src/core/objects/rule/changes/rule.alter.test.ts +78 -0
  285. package/src/core/objects/rule/changes/rule.alter.ts +72 -0
  286. package/src/core/objects/rule/changes/rule.base.ts +20 -0
  287. package/src/core/objects/rule/changes/rule.comment.test.ts +55 -0
  288. package/src/core/objects/rule/changes/rule.comment.ts +62 -0
  289. package/src/core/objects/rule/changes/rule.create.test.ts +59 -0
  290. package/src/core/objects/rule/changes/rule.create.ts +42 -0
  291. package/src/core/objects/rule/changes/rule.drop.test.ts +38 -0
  292. package/src/core/objects/rule/changes/rule.drop.ts +29 -0
  293. package/src/core/objects/rule/changes/rule.types.ts +12 -0
  294. package/src/core/objects/rule/rule.diff.test.ts +132 -0
  295. package/src/core/objects/rule/rule.diff.ts +79 -0
  296. package/src/core/objects/rule/rule.model.ts +173 -0
  297. package/src/core/objects/schema/changes/schema.alter.test.ts +28 -0
  298. package/src/core/objects/schema/changes/schema.alter.ts +45 -0
  299. package/src/core/objects/schema/changes/schema.base.ts +20 -0
  300. package/src/core/objects/schema/changes/schema.comment.ts +56 -0
  301. package/src/core/objects/schema/changes/schema.create.test.ts +22 -0
  302. package/src/core/objects/schema/changes/schema.create.ts +47 -0
  303. package/src/core/objects/schema/changes/schema.drop.test.ts +20 -0
  304. package/src/core/objects/schema/changes/schema.drop.ts +34 -0
  305. package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
  306. package/src/core/objects/schema/changes/schema.types.ts +12 -0
  307. package/src/core/objects/schema/schema.diff.test.ts +42 -0
  308. package/src/core/objects/schema/schema.diff.ts +209 -0
  309. package/src/core/objects/schema/schema.model.ts +107 -0
  310. package/src/core/objects/sequence/changes/sequence.alter.test.ts +151 -0
  311. package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
  312. package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
  313. package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
  314. package/src/core/objects/sequence/changes/sequence.create.test.ts +84 -0
  315. package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
  316. package/src/core/objects/sequence/changes/sequence.drop.test.ts +32 -0
  317. package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
  318. package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
  319. package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
  320. package/src/core/objects/sequence/sequence.diff.test.ts +141 -0
  321. package/src/core/objects/sequence/sequence.diff.ts +359 -0
  322. package/src/core/objects/sequence/sequence.model.ts +185 -0
  323. package/src/core/objects/subscription/changes/subscription.alter.test.ts +124 -0
  324. package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
  325. package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
  326. package/src/core/objects/subscription/changes/subscription.comment.test.ts +67 -0
  327. package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
  328. package/src/core/objects/subscription/changes/subscription.create.test.ts +77 -0
  329. package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
  330. package/src/core/objects/subscription/changes/subscription.drop.test.ts +46 -0
  331. package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
  332. package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
  333. package/src/core/objects/subscription/subscription.diff.test.ts +232 -0
  334. package/src/core/objects/subscription/subscription.diff.ts +241 -0
  335. package/src/core/objects/subscription/subscription.model.ts +190 -0
  336. package/src/core/objects/subscription/utils.ts +156 -0
  337. package/src/core/objects/table/changes/table.alter.test.ts +823 -0
  338. package/src/core/objects/table/changes/table.alter.ts +806 -0
  339. package/src/core/objects/table/changes/table.base.ts +20 -0
  340. package/src/core/objects/table/changes/table.comment.ts +266 -0
  341. package/src/core/objects/table/changes/table.create.test.ts +150 -0
  342. package/src/core/objects/table/changes/table.create.ts +188 -0
  343. package/src/core/objects/table/changes/table.drop.test.ts +34 -0
  344. package/src/core/objects/table/changes/table.drop.ts +45 -0
  345. package/src/core/objects/table/changes/table.privilege.ts +200 -0
  346. package/src/core/objects/table/changes/table.types.ts +12 -0
  347. package/src/core/objects/table/table.diff.test.ts +711 -0
  348. package/src/core/objects/table/table.diff.ts +953 -0
  349. package/src/core/objects/table/table.model.ts +460 -0
  350. package/src/core/objects/trigger/changes/trigger.alter.test.ts +46 -0
  351. package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
  352. package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
  353. package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
  354. package/src/core/objects/trigger/changes/trigger.create.test.ts +43 -0
  355. package/src/core/objects/trigger/changes/trigger.create.ts +85 -0
  356. package/src/core/objects/trigger/changes/trigger.drop.test.ts +43 -0
  357. package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
  358. package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
  359. package/src/core/objects/trigger/trigger.diff.test.ts +83 -0
  360. package/src/core/objects/trigger/trigger.diff.ts +116 -0
  361. package/src/core/objects/trigger/trigger.model.ts +252 -0
  362. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +202 -0
  363. package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
  364. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
  365. package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
  366. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +101 -0
  367. package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
  368. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +33 -0
  369. package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
  370. package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
  371. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
  372. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +191 -0
  373. package/src/core/objects/type/composite-type/composite-type.diff.ts +372 -0
  374. package/src/core/objects/type/composite-type/composite-type.model.ts +252 -0
  375. package/src/core/objects/type/enum/changes/enum.alter.test.ts +104 -0
  376. package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
  377. package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
  378. package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
  379. package/src/core/objects/type/enum/changes/enum.create.test.ts +28 -0
  380. package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
  381. package/src/core/objects/type/enum/changes/enum.drop.test.ts +25 -0
  382. package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
  383. package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
  384. package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
  385. package/src/core/objects/type/enum/enum.diff.test.ts +191 -0
  386. package/src/core/objects/type/enum/enum.diff.ts +396 -0
  387. package/src/core/objects/type/enum/enum.model.ts +194 -0
  388. package/src/core/objects/type/range/changes/range.alter.test.ts +27 -0
  389. package/src/core/objects/type/range/changes/range.alter.ts +51 -0
  390. package/src/core/objects/type/range/changes/range.base.ts +20 -0
  391. package/src/core/objects/type/range/changes/range.comment.ts +64 -0
  392. package/src/core/objects/type/range/changes/range.create.test.ts +51 -0
  393. package/src/core/objects/type/range/changes/range.create.ts +151 -0
  394. package/src/core/objects/type/range/changes/range.drop.test.ts +26 -0
  395. package/src/core/objects/type/range/changes/range.drop.ts +34 -0
  396. package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
  397. package/src/core/objects/type/range/changes/range.types.ts +12 -0
  398. package/src/core/objects/type/range/range.diff.test.ts +70 -0
  399. package/src/core/objects/type/range/range.diff.ts +259 -0
  400. package/src/core/objects/type/range/range.model.ts +187 -0
  401. package/src/core/objects/type/type.types.ts +5 -0
  402. package/src/core/objects/utils.ts +171 -0
  403. package/src/core/objects/view/changes/view.alter.test.ts +110 -0
  404. package/src/core/objects/view/changes/view.alter.ts +112 -0
  405. package/src/core/objects/view/changes/view.base.ts +20 -0
  406. package/src/core/objects/view/changes/view.comment.ts +59 -0
  407. package/src/core/objects/view/changes/view.create.test.ts +65 -0
  408. package/src/core/objects/view/changes/view.create.ts +73 -0
  409. package/src/core/objects/view/changes/view.drop.test.ts +34 -0
  410. package/src/core/objects/view/changes/view.drop.ts +40 -0
  411. package/src/core/objects/view/changes/view.privilege.ts +200 -0
  412. package/src/core/objects/view/changes/view.types.ts +12 -0
  413. package/src/core/objects/view/view.diff.test.ts +91 -0
  414. package/src/core/objects/view/view.diff.ts +365 -0
  415. package/src/core/objects/view/view.model.ts +276 -0
  416. package/src/core/plan/apply.ts +190 -0
  417. package/src/core/plan/create.ts +432 -0
  418. package/src/core/plan/hierarchy.ts +574 -0
  419. package/src/core/plan/index.ts +29 -0
  420. package/src/core/plan/io.ts +20 -0
  421. package/src/core/plan/risk.ts +48 -0
  422. package/src/core/plan/serialize.ts +195 -0
  423. package/src/core/plan/sql-format/constants.ts +13 -0
  424. package/src/core/plan/sql-format/fixtures.ts +2806 -0
  425. package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
  426. package/src/core/plan/sql-format/format-functions.test.ts +127 -0
  427. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +67 -0
  428. package/src/core/plan/sql-format/format-off.test.ts +809 -0
  429. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1056 -0
  430. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1283 -0
  431. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1052 -0
  432. package/src/core/plan/sql-format/format-pretty-upper.test.ts +1045 -0
  433. package/src/core/plan/sql-format/format-stress.test.ts +616 -0
  434. package/src/core/plan/sql-format/format-utils.test.ts +91 -0
  435. package/src/core/plan/sql-format/format-utils.ts +391 -0
  436. package/src/core/plan/sql-format/formatters.ts +921 -0
  437. package/src/core/plan/sql-format/index.ts +149 -0
  438. package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
  439. package/src/core/plan/sql-format/keyword-case.ts +1085 -0
  440. package/src/core/plan/sql-format/protect.test.ts +127 -0
  441. package/src/core/plan/sql-format/protect.ts +337 -0
  442. package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
  443. package/src/core/plan/sql-format/sql-scanner.ts +252 -0
  444. package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
  445. package/src/core/plan/sql-format/tokenizer.ts +152 -0
  446. package/src/core/plan/sql-format/types.ts +31 -0
  447. package/src/core/plan/sql-format/wrap.test.ts +119 -0
  448. package/src/core/plan/sql-format/wrap.ts +196 -0
  449. package/src/core/plan/sql-format.ts +2 -0
  450. package/src/core/plan/statements.ts +22 -0
  451. package/src/core/plan/types.ts +165 -0
  452. package/src/core/postgres-config.ts +169 -0
  453. package/src/core/sort/custom-constraints.ts +161 -0
  454. package/src/core/sort/debug-visualization.ts +239 -0
  455. package/src/core/sort/dependency-filter.ts +224 -0
  456. package/src/core/sort/graph-builder.ts +223 -0
  457. package/src/core/sort/graph-utils.ts +51 -0
  458. package/src/core/sort/logical-sort.ts +590 -0
  459. package/src/core/sort/sort-changes.ts +234 -0
  460. package/src/core/sort/topological-sort.ts +184 -0
  461. package/src/core/sort/types.ts +112 -0
  462. package/src/core/sort/utils.ts +69 -0
  463. package/src/index.ts +14 -0
@@ -0,0 +1,191 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { DefaultPrivilegeState } from "../../base.default-privileges.ts";
3
+ import {
4
+ AlterEnumAddValue,
5
+ AlterEnumChangeOwner,
6
+ } from "./changes/enum.alter.ts";
7
+ import { CreateEnum } from "./changes/enum.create.ts";
8
+ import { DropEnum } from "./changes/enum.drop.ts";
9
+ import { diffEnums } from "./enum.diff.ts";
10
+ import { Enum, type EnumProps } from "./enum.model.ts";
11
+
12
+ const testContext = {
13
+ version: 170000,
14
+ currentUser: "postgres",
15
+ defaultPrivilegeState: new DefaultPrivilegeState({}),
16
+ mainRoles: {},
17
+ };
18
+
19
+ describe.concurrent("enum.diff", () => {
20
+ test("create and drop", () => {
21
+ const props: EnumProps = {
22
+ schema: "public",
23
+ name: "e1",
24
+ owner: "o1",
25
+ labels: [
26
+ { label: "a", sort_order: 1 },
27
+ { label: "b", sort_order: 2 },
28
+ ],
29
+ comment: null,
30
+ privileges: [],
31
+ };
32
+ const e = new Enum(props);
33
+
34
+ const created = diffEnums(testContext, {}, { [e.stableId]: e });
35
+ expect(created[0]).toBeInstanceOf(CreateEnum);
36
+
37
+ const dropped = diffEnums(testContext, { [e.stableId]: e }, {});
38
+ expect(dropped[0]).toBeInstanceOf(DropEnum);
39
+ });
40
+
41
+ test("alter: owner change and add value positioning", () => {
42
+ const main = new Enum({
43
+ schema: "public",
44
+ name: "e1",
45
+ owner: "o1",
46
+ labels: [
47
+ { label: "a", sort_order: 1 },
48
+ { label: "c", sort_order: 3 },
49
+ ],
50
+ comment: null,
51
+ privileges: [],
52
+ });
53
+ const branch = new Enum({
54
+ schema: "public",
55
+ name: "e1",
56
+ owner: "o2",
57
+ labels: [
58
+ { label: "a", sort_order: 1 },
59
+ { label: "b", sort_order: 2 },
60
+ { label: "c", sort_order: 3 },
61
+ ],
62
+ comment: null,
63
+ privileges: [],
64
+ });
65
+
66
+ const changes = diffEnums(
67
+ testContext,
68
+ { [main.stableId]: main },
69
+ { [branch.stableId]: branch },
70
+ );
71
+ expect(changes.some((c) => c instanceof AlterEnumChangeOwner)).toBe(true);
72
+ const add = changes.find((c) => c instanceof AlterEnumAddValue) as
73
+ | AlterEnumAddValue
74
+ | undefined;
75
+ expect(add).toBeDefined();
76
+ });
77
+
78
+ test("add value at beginning (BEFORE first)", () => {
79
+ const main = new Enum({
80
+ schema: "public",
81
+ name: "e1",
82
+ owner: "o1",
83
+ labels: [
84
+ { label: "b", sort_order: 2 },
85
+ { label: "c", sort_order: 3 },
86
+ ],
87
+ comment: null,
88
+ privileges: [],
89
+ });
90
+ const branch = new Enum({
91
+ schema: "public",
92
+ name: "e1",
93
+ owner: "o1",
94
+ labels: [
95
+ { label: "a", sort_order: 1 },
96
+ { label: "b", sort_order: 2 },
97
+ { label: "c", sort_order: 3 },
98
+ ],
99
+ comment: null,
100
+ privileges: [],
101
+ });
102
+
103
+ const changes = diffEnums(
104
+ testContext,
105
+ { [main.stableId]: main },
106
+ { [branch.stableId]: branch },
107
+ );
108
+ const add = changes.find((c) => c instanceof AlterEnumAddValue) as
109
+ | AlterEnumAddValue
110
+ | undefined;
111
+ expect(add).toBeDefined();
112
+ expect(add?.position?.before).toBe("b");
113
+ expect(add?.position?.after).toBeUndefined();
114
+ });
115
+
116
+ test("add value in middle (AFTER previous)", () => {
117
+ const main = new Enum({
118
+ schema: "public",
119
+ name: "e1",
120
+ owner: "o1",
121
+ labels: [
122
+ { label: "a", sort_order: 1 },
123
+ { label: "c", sort_order: 3 },
124
+ ],
125
+ comment: null,
126
+ privileges: [],
127
+ });
128
+ const branch = new Enum({
129
+ schema: "public",
130
+ name: "e1",
131
+ owner: "o1",
132
+ labels: [
133
+ { label: "a", sort_order: 1 },
134
+ { label: "b", sort_order: 2 },
135
+ { label: "c", sort_order: 3 },
136
+ ],
137
+ comment: null,
138
+ privileges: [],
139
+ });
140
+
141
+ const changes = diffEnums(
142
+ testContext,
143
+ { [main.stableId]: main },
144
+ { [branch.stableId]: branch },
145
+ );
146
+ const add = changes.find((c) => c instanceof AlterEnumAddValue) as
147
+ | AlterEnumAddValue
148
+ | undefined;
149
+ expect(add).toBeDefined();
150
+ expect(add?.position?.after).toBe("a");
151
+ expect(add?.position?.before).toBeUndefined();
152
+ });
153
+
154
+ test("add value at end (AFTER last)", () => {
155
+ const main = new Enum({
156
+ schema: "public",
157
+ name: "e1",
158
+ owner: "o1",
159
+ labels: [
160
+ { label: "a", sort_order: 1 },
161
+ { label: "b", sort_order: 2 },
162
+ ],
163
+ comment: null,
164
+ privileges: [],
165
+ });
166
+ const branch = new Enum({
167
+ schema: "public",
168
+ name: "e1",
169
+ owner: "o1",
170
+ labels: [
171
+ { label: "a", sort_order: 1 },
172
+ { label: "b", sort_order: 2 },
173
+ { label: "c", sort_order: 3 },
174
+ ],
175
+ comment: null,
176
+ privileges: [],
177
+ });
178
+
179
+ const changes = diffEnums(
180
+ testContext,
181
+ { [main.stableId]: main },
182
+ { [branch.stableId]: branch },
183
+ );
184
+ const add = changes.find((c) => c instanceof AlterEnumAddValue) as
185
+ | AlterEnumAddValue
186
+ | undefined;
187
+ expect(add).toBeDefined();
188
+ expect(add?.position?.after).toBe("b");
189
+ expect(add?.position?.before).toBeUndefined();
190
+ });
191
+ });
@@ -0,0 +1,396 @@
1
+ import type { DefaultPrivilegeState } from "../../base.default-privileges.ts";
2
+ import { diffObjects } from "../../base.diff.ts";
3
+ import {
4
+ diffPrivileges,
5
+ filterPublicBuiltInDefaults,
6
+ groupPrivilegesByGrantable,
7
+ } from "../../base.privilege-diff.ts";
8
+ import type { Role } from "../../role/role.model.ts";
9
+ import {
10
+ AlterEnumAddValue,
11
+ AlterEnumChangeOwner,
12
+ } from "./changes/enum.alter.ts";
13
+ import {
14
+ CreateCommentOnEnum,
15
+ DropCommentOnEnum,
16
+ } from "./changes/enum.comment.ts";
17
+ import { CreateEnum } from "./changes/enum.create.ts";
18
+ import { DropEnum } from "./changes/enum.drop.ts";
19
+ import {
20
+ GrantEnumPrivileges,
21
+ RevokeEnumPrivileges,
22
+ RevokeGrantOptionEnumPrivileges,
23
+ } from "./changes/enum.privilege.ts";
24
+ import type { EnumChange } from "./changes/enum.types.ts";
25
+ import type { Enum } from "./enum.model.ts";
26
+
27
+ /**
28
+ * Diff two sets of enums from main and branch catalogs.
29
+ *
30
+ * @param ctx - Context containing version, currentUser, and defaultPrivilegeState
31
+ * @param main - The enums in the main catalog.
32
+ * @param branch - The enums in the branch catalog.
33
+ * @returns A list of changes to apply to main to make it match branch.
34
+ */
35
+ export function diffEnums(
36
+ ctx: {
37
+ version: number;
38
+ currentUser: string;
39
+ defaultPrivilegeState: DefaultPrivilegeState;
40
+ mainRoles: Record<string, Role>;
41
+ },
42
+ main: Record<string, Enum>,
43
+ branch: Record<string, Enum>,
44
+ ): EnumChange[] {
45
+ const { created, dropped, altered } = diffObjects(main, branch);
46
+
47
+ const changes: EnumChange[] = [];
48
+
49
+ for (const enumId of created) {
50
+ const createdEnum = branch[enumId];
51
+ changes.push(new CreateEnum({ enum: createdEnum }));
52
+
53
+ // OWNER: If the enum should be owned by someone other than the current user,
54
+ // emit ALTER TYPE ... OWNER TO after creation
55
+ if (createdEnum.owner !== ctx.currentUser) {
56
+ changes.push(
57
+ new AlterEnumChangeOwner({
58
+ enum: createdEnum,
59
+ owner: createdEnum.owner,
60
+ }),
61
+ );
62
+ }
63
+
64
+ if (createdEnum.comment !== null) {
65
+ changes.push(new CreateCommentOnEnum({ enum: createdEnum }));
66
+ }
67
+
68
+ // PRIVILEGES: For created objects, compare against default privileges state
69
+ // The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
70
+ // so objects are created with the default privileges state in effect.
71
+ // We compare default privileges against desired privileges to generate REVOKE/GRANT statements
72
+ // needed to reach the final desired state.
73
+ const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(
74
+ ctx.currentUser,
75
+ "enum",
76
+ createdEnum.schema ?? "",
77
+ );
78
+ // Filter out PUBLIC's built-in default USAGE privilege (PostgreSQL grants it automatically)
79
+ // Reference: https://www.postgresql.org/docs/17/ddl-priv.html Table 5.2
80
+ // This prevents generating unnecessary "GRANT USAGE TO PUBLIC" statements
81
+ const desiredPrivileges = filterPublicBuiltInDefaults(
82
+ "enum",
83
+ createdEnum.privileges,
84
+ );
85
+ // Filter out owner privileges - owner always has ALL privileges implicitly
86
+ // and shouldn't be compared. Use the enum owner as the reference.
87
+ const privilegeResults = diffPrivileges(
88
+ effectiveDefaults,
89
+ desiredPrivileges,
90
+ createdEnum.owner,
91
+ ctx.mainRoles,
92
+ );
93
+
94
+ // Generate grant changes
95
+ for (const [grantee, result] of privilegeResults) {
96
+ if (result.grants.length > 0) {
97
+ const grantGroups = groupPrivilegesByGrantable(result.grants);
98
+ for (const [grantable, list] of grantGroups) {
99
+ void grantable;
100
+ changes.push(
101
+ new GrantEnumPrivileges({
102
+ enum: createdEnum,
103
+ grantee,
104
+ privileges: list,
105
+ version: ctx.version,
106
+ }),
107
+ );
108
+ }
109
+ }
110
+
111
+ // Generate revoke changes
112
+ if (result.revokes.length > 0) {
113
+ const revokeGroups = groupPrivilegesByGrantable(result.revokes);
114
+ for (const [grantable, list] of revokeGroups) {
115
+ void grantable;
116
+ changes.push(
117
+ new RevokeEnumPrivileges({
118
+ enum: createdEnum,
119
+ grantee,
120
+ privileges: list,
121
+ version: ctx.version,
122
+ }),
123
+ );
124
+ }
125
+ }
126
+
127
+ // Generate revoke grant option changes
128
+ if (result.revokeGrantOption.length > 0) {
129
+ changes.push(
130
+ new RevokeGrantOptionEnumPrivileges({
131
+ enum: createdEnum,
132
+ grantee,
133
+ privilegeNames: result.revokeGrantOption,
134
+ version: ctx.version,
135
+ }),
136
+ );
137
+ }
138
+ }
139
+ }
140
+
141
+ for (const enumId of dropped) {
142
+ changes.push(new DropEnum({ enum: main[enumId] }));
143
+ }
144
+
145
+ for (const enumId of altered) {
146
+ const mainEnum = main[enumId];
147
+ const branchEnum = branch[enumId];
148
+
149
+ // If labels were removed (branch is missing labels present in main),
150
+ // recreate the enum to avoid relying on unsupported DROP VALUE operations.
151
+ const removedLabels = mainEnum.labels
152
+ .map((l) => l.label)
153
+ .filter((label) => !branchEnum.labels.some((b) => b.label === label));
154
+ if (removedLabels.length > 0) {
155
+ changes.push(new DropEnum({ enum: mainEnum }));
156
+ changes.push(new CreateEnum({ enum: branchEnum }));
157
+
158
+ if (branchEnum.owner !== ctx.currentUser) {
159
+ changes.push(
160
+ new AlterEnumChangeOwner({
161
+ enum: branchEnum,
162
+ owner: branchEnum.owner,
163
+ }),
164
+ );
165
+ }
166
+
167
+ if (branchEnum.comment !== null) {
168
+ changes.push(new CreateCommentOnEnum({ enum: branchEnum }));
169
+ }
170
+
171
+ const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(
172
+ ctx.currentUser,
173
+ "enum",
174
+ branchEnum.schema ?? "",
175
+ );
176
+ const desiredPrivileges = filterPublicBuiltInDefaults(
177
+ "enum",
178
+ branchEnum.privileges,
179
+ );
180
+ const privilegeResults = diffPrivileges(
181
+ effectiveDefaults,
182
+ desiredPrivileges,
183
+ branchEnum.owner,
184
+ ctx.mainRoles,
185
+ );
186
+
187
+ for (const [grantee, result] of privilegeResults) {
188
+ if (result.grants.length > 0) {
189
+ const grantGroups = groupPrivilegesByGrantable(result.grants);
190
+ for (const [grantable, list] of grantGroups) {
191
+ void grantable;
192
+ changes.push(
193
+ new GrantEnumPrivileges({
194
+ enum: branchEnum,
195
+ grantee,
196
+ privileges: list,
197
+ version: ctx.version,
198
+ }),
199
+ );
200
+ }
201
+ }
202
+
203
+ if (result.revokes.length > 0) {
204
+ const revokeGroups = groupPrivilegesByGrantable(result.revokes);
205
+ for (const [grantable, list] of revokeGroups) {
206
+ void grantable;
207
+ changes.push(
208
+ new RevokeEnumPrivileges({
209
+ enum: branchEnum,
210
+ grantee,
211
+ privileges: list,
212
+ version: ctx.version,
213
+ }),
214
+ );
215
+ }
216
+ }
217
+
218
+ if (result.revokeGrantOption.length > 0) {
219
+ changes.push(
220
+ new RevokeGrantOptionEnumPrivileges({
221
+ enum: branchEnum,
222
+ grantee,
223
+ privilegeNames: result.revokeGrantOption,
224
+ version: ctx.version,
225
+ }),
226
+ );
227
+ }
228
+ }
229
+
230
+ continue;
231
+ }
232
+
233
+ // OWNER
234
+ if (mainEnum.owner !== branchEnum.owner) {
235
+ changes.push(
236
+ new AlterEnumChangeOwner({ enum: mainEnum, owner: branchEnum.owner }),
237
+ );
238
+ }
239
+
240
+ // LABELS (enum values)
241
+ if (JSON.stringify(mainEnum.labels) !== JSON.stringify(branchEnum.labels)) {
242
+ const labelChanges = diffEnumLabels(mainEnum, branchEnum);
243
+ changes.push(...labelChanges);
244
+ }
245
+
246
+ // COMMENT
247
+ if (mainEnum.comment !== branchEnum.comment) {
248
+ if (branchEnum.comment === null) {
249
+ changes.push(new DropCommentOnEnum({ enum: mainEnum }));
250
+ } else {
251
+ changes.push(new CreateCommentOnEnum({ enum: branchEnum }));
252
+ }
253
+ }
254
+
255
+ // PRIVILEGES
256
+ // Filter out PUBLIC's built-in default USAGE privilege from main catalog
257
+ // (PostgreSQL grants it automatically, so we shouldn't compare it)
258
+ const mainPrivilegesFiltered = filterPublicBuiltInDefaults(
259
+ "enum",
260
+ mainEnum.privileges,
261
+ );
262
+ // Filter out PUBLIC's built-in default USAGE privilege from branch catalog
263
+ const branchPrivilegesFiltered = filterPublicBuiltInDefaults(
264
+ "enum",
265
+ branchEnum.privileges,
266
+ );
267
+ // Filter out owner privileges - owner always has ALL privileges implicitly
268
+ // and shouldn't be compared. Use branch owner as the reference.
269
+ const privilegeResults = diffPrivileges(
270
+ mainPrivilegesFiltered,
271
+ branchPrivilegesFiltered,
272
+ branchEnum.owner,
273
+ ctx.mainRoles,
274
+ );
275
+
276
+ for (const [grantee, result] of privilegeResults) {
277
+ // Generate grant changes
278
+ if (result.grants.length > 0) {
279
+ const grantGroups = groupPrivilegesByGrantable(result.grants);
280
+ for (const [grantable, list] of grantGroups) {
281
+ void grantable;
282
+ changes.push(
283
+ new GrantEnumPrivileges({
284
+ enum: branchEnum,
285
+ grantee,
286
+ privileges: list,
287
+ version: ctx.version,
288
+ }),
289
+ );
290
+ }
291
+ }
292
+
293
+ // Generate revoke changes
294
+ if (result.revokes.length > 0) {
295
+ const revokeGroups = groupPrivilegesByGrantable(result.revokes);
296
+ for (const [grantable, list] of revokeGroups) {
297
+ void grantable;
298
+ changes.push(
299
+ new RevokeEnumPrivileges({
300
+ enum: mainEnum,
301
+ grantee,
302
+ privileges: list,
303
+ version: ctx.version,
304
+ }),
305
+ );
306
+ }
307
+ }
308
+
309
+ // Generate revoke grant option changes
310
+ if (result.revokeGrantOption.length > 0) {
311
+ changes.push(
312
+ new RevokeGrantOptionEnumPrivileges({
313
+ enum: mainEnum,
314
+ grantee,
315
+ privilegeNames: result.revokeGrantOption,
316
+ version: ctx.version,
317
+ }),
318
+ );
319
+ }
320
+ }
321
+
322
+ // Note: Enum renaming would also use ALTER TYPE ... RENAME TO ...
323
+ // But since our Enum model uses 'name' as the identity field,
324
+ // a name change would be handled as drop + create by diffObjects()
325
+ }
326
+
327
+ return changes;
328
+ }
329
+
330
+ /**
331
+ * Diff enum labels to determine what ALTER TYPE statements are needed.
332
+ * This implementation properly handles enum value positioning using sort_order.
333
+ * Note: We cannot reliably detect renames, so we only handle additions.
334
+ */
335
+ function diffEnumLabels(mainEnum: Enum, branchEnum: Enum): EnumChange[] {
336
+ const changes: EnumChange[] = [];
337
+
338
+ // Create maps for efficient lookup
339
+ const mainLabelMap = new Map(
340
+ mainEnum.labels.map((label) => [label.label, label.sort_order]),
341
+ );
342
+ const branchLabelMap = new Map(
343
+ branchEnum.labels.map((label) => [label.label, label.sort_order]),
344
+ );
345
+
346
+ // Find added values (values in branch but not in main)
347
+ const addedValues = Array.from(branchLabelMap.keys()).filter(
348
+ (label) => !mainLabelMap.has(label),
349
+ );
350
+
351
+ // Maintain a working list of labels (by name) to calculate correct BEFORE/AFTER
352
+ // anchors as we simulate applying the additions in order.
353
+ const branchOrdered = [...branchEnum.labels].sort(
354
+ (a, b) => a.sort_order - b.sort_order,
355
+ );
356
+ const workingLabels = [...mainEnum.labels].map((l) => l.label);
357
+
358
+ for (const newValue of addedValues) {
359
+ const branchIdx = branchOrdered.findIndex((l) => l.label === newValue);
360
+ if (branchIdx === -1) continue;
361
+
362
+ const prevBranch = branchOrdered[branchIdx - 1]?.label;
363
+ const nextBranch = branchOrdered[branchIdx + 1]?.label;
364
+
365
+ let position: { before?: string; after?: string } | undefined;
366
+
367
+ // Prefer AFTER when prevBranch exists in workingLabels (more natural for sequential additions)
368
+ // Use BEFORE only when we need to insert before the first value or when prevBranch doesn't exist
369
+ if (prevBranch && workingLabels.includes(prevBranch)) {
370
+ position = { after: prevBranch };
371
+ // Insert after the previous label in our working list
372
+ const prevIdx = workingLabels.indexOf(prevBranch);
373
+ workingLabels.splice(prevIdx + 1, 0, newValue);
374
+ } else if (nextBranch && workingLabels.includes(nextBranch)) {
375
+ // Insert before nextBranch when prevBranch doesn't exist (e.g., adding at beginning)
376
+ position = { before: nextBranch };
377
+ const nextIdx = workingLabels.indexOf(nextBranch);
378
+ workingLabels.splice(nextIdx, 0, newValue);
379
+ } else if (nextBranch) {
380
+ // nextBranch exists but not in workingLabels yet (shouldn't happen in normal flow)
381
+ position = { before: nextBranch };
382
+ workingLabels.push(newValue);
383
+ } else {
384
+ // Fallback: append to the end
385
+ position = { after: workingLabels[workingLabels.length - 1] };
386
+ workingLabels.push(newValue);
387
+ }
388
+
389
+ changes.push(new AlterEnumAddValue({ enum: mainEnum, newValue, position }));
390
+ }
391
+
392
+ // Complex changes (removals, resorting) are currently not auto-handled.
393
+ // We intentionally avoid emitting drop+create to prevent data loss.
394
+
395
+ return changes;
396
+ }