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

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 (359) hide show
  1. package/README.md +40 -23
  2. package/dist/cli/app.js +26 -3
  3. package/dist/cli/bin/cli.js +5 -0
  4. package/dist/cli/commands/catalog-export.d.ts +5 -0
  5. package/dist/cli/commands/catalog-export.js +64 -0
  6. package/dist/cli/commands/declarative-apply.d.ts +6 -0
  7. package/dist/cli/commands/declarative-apply.js +288 -0
  8. package/dist/cli/commands/declarative-export.d.ts +5 -0
  9. package/dist/cli/commands/declarative-export.js +245 -0
  10. package/dist/cli/commands/plan.js +19 -6
  11. package/dist/cli/exit-code.d.ts +2 -0
  12. package/dist/cli/exit-code.js +7 -0
  13. package/dist/cli/formatters/tree/tree.js +3 -2
  14. package/dist/cli/utils/apply-display.d.ts +52 -0
  15. package/dist/cli/utils/apply-display.js +183 -0
  16. package/dist/cli/utils/export-display.d.ts +43 -0
  17. package/dist/cli/utils/export-display.js +202 -0
  18. package/dist/cli/utils/resolve-input.d.ts +7 -0
  19. package/dist/cli/utils/resolve-input.js +13 -0
  20. package/dist/core/catalog-export/index.d.ts +11 -0
  21. package/dist/core/catalog-export/index.js +10 -0
  22. package/dist/core/catalog.diff.d.ts +1 -0
  23. package/dist/core/catalog.diff.js +64 -48
  24. package/dist/core/catalog.model.d.ts +14 -1
  25. package/dist/core/catalog.model.js +103 -1
  26. package/dist/core/catalog.snapshot.d.ts +66 -0
  27. package/dist/core/catalog.snapshot.js +206 -0
  28. package/dist/core/declarative-apply/discover-sql.d.ts +18 -0
  29. package/dist/core/declarative-apply/discover-sql.js +86 -0
  30. package/dist/core/declarative-apply/extract-catalog-providers.d.ts +23 -0
  31. package/dist/core/declarative-apply/extract-catalog-providers.js +159 -0
  32. package/dist/core/declarative-apply/index.d.ts +49 -0
  33. package/dist/core/declarative-apply/index.js +134 -0
  34. package/dist/core/declarative-apply/round-apply.d.ts +100 -0
  35. package/dist/core/declarative-apply/round-apply.js +378 -0
  36. package/dist/core/export/file-mapper.d.ts +71 -0
  37. package/dist/core/export/file-mapper.js +474 -0
  38. package/dist/core/export/grouper.d.ts +13 -0
  39. package/dist/core/export/grouper.js +76 -0
  40. package/dist/core/export/index.d.ts +45 -0
  41. package/dist/core/export/index.js +63 -0
  42. package/dist/core/export/types.d.ts +84 -0
  43. package/dist/core/export/types.js +25 -0
  44. package/dist/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  45. package/dist/core/integrations/filter/dsl.d.ts +38 -1
  46. package/dist/core/integrations/filter/dsl.js +20 -2
  47. package/dist/core/integrations/filter/extractors.js +42 -0
  48. package/dist/core/integrations/integration-dsl.d.ts +10 -0
  49. package/dist/core/integrations/supabase.d.ts +8 -0
  50. package/dist/core/integrations/supabase.js +9 -0
  51. package/dist/core/objects/aggregate/aggregate.diff.d.ts +2 -8
  52. package/dist/core/objects/aggregate/aggregate.diff.js +16 -70
  53. package/dist/core/objects/aggregate/aggregate.model.d.ts +8 -8
  54. package/dist/core/objects/aggregate/aggregate.model.js +1 -1
  55. package/dist/core/objects/aggregate/changes/aggregate.create.js +1 -1
  56. package/dist/core/objects/aggregate/changes/aggregate.drop.js +1 -1
  57. package/dist/core/objects/base.privilege-diff.d.ts +38 -13
  58. package/dist/core/objects/base.privilege-diff.js +104 -22
  59. package/dist/core/objects/base.privilege.d.ts +1 -0
  60. package/dist/core/objects/base.privilege.js +9 -2
  61. package/dist/core/objects/collation/collation.diff.d.ts +2 -3
  62. package/dist/core/objects/diff-context.d.ts +15 -0
  63. package/dist/core/objects/diff-context.js +1 -0
  64. package/dist/core/objects/domain/changes/domain.create.js +4 -2
  65. package/dist/core/objects/domain/domain.diff.d.ts +2 -8
  66. package/dist/core/objects/domain/domain.diff.js +16 -77
  67. package/dist/core/objects/domain/domain.model.js +1 -1
  68. package/dist/core/objects/event-trigger/event-trigger.diff.d.ts +2 -3
  69. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.d.ts +2 -8
  70. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.js +13 -77
  71. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +2 -2
  72. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.d.ts +2 -8
  73. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -77
  74. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +1 -1
  75. package/dist/core/objects/foreign-data-wrapper/server/server.diff.d.ts +2 -8
  76. package/dist/core/objects/foreign-data-wrapper/server/server.diff.js +13 -77
  77. package/dist/core/objects/language/language.diff.d.ts +2 -5
  78. package/dist/core/objects/language/language.diff.js +7 -39
  79. package/dist/core/objects/materialized-view/materialized-view.diff.d.ts +2 -8
  80. package/dist/core/objects/materialized-view/materialized-view.diff.js +16 -158
  81. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +3 -3
  82. package/dist/core/objects/materialized-view/materialized-view.model.js +1 -1
  83. package/dist/core/objects/procedure/changes/procedure.alter.js +12 -12
  84. package/dist/core/objects/procedure/procedure.diff.d.ts +2 -8
  85. package/dist/core/objects/procedure/procedure.diff.js +16 -77
  86. package/dist/core/objects/procedure/procedure.model.d.ts +9 -9
  87. package/dist/core/objects/procedure/procedure.model.js +1 -1
  88. package/dist/core/objects/publication/changes/publication.alter.d.ts +0 -9
  89. package/dist/core/objects/publication/changes/publication.alter.js +0 -14
  90. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -2
  91. package/dist/core/objects/publication/publication.diff.d.ts +2 -3
  92. package/dist/core/objects/publication/publication.diff.js +8 -13
  93. package/dist/core/objects/rls-policy/changes/rls-policy.alter.js +3 -3
  94. package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
  95. package/dist/core/objects/role/role.diff.js +22 -1
  96. package/dist/core/objects/role/role.model.d.ts +4 -3
  97. package/dist/core/objects/role/role.model.js +118 -12
  98. package/dist/core/objects/rule/rule.model.d.ts +1 -1
  99. package/dist/core/objects/schema/schema.diff.d.ts +2 -8
  100. package/dist/core/objects/schema/schema.diff.js +16 -77
  101. package/dist/core/objects/schema/schema.model.js +1 -1
  102. package/dist/core/objects/sequence/sequence.diff.d.ts +2 -8
  103. package/dist/core/objects/sequence/sequence.diff.js +16 -79
  104. package/dist/core/objects/sequence/sequence.model.js +1 -1
  105. package/dist/core/objects/subscription/subscription.diff.d.ts +2 -3
  106. package/dist/core/objects/table/changes/table.create.js +3 -0
  107. package/dist/core/objects/table/table.diff.d.ts +2 -8
  108. package/dist/core/objects/table/table.diff.js +26 -157
  109. package/dist/core/objects/table/table.model.d.ts +23 -22
  110. package/dist/core/objects/table/table.model.js +1 -1
  111. package/dist/core/objects/trigger/changes/trigger.create.js +2 -4
  112. package/dist/core/objects/trigger/trigger.model.d.ts +8 -0
  113. package/dist/core/objects/trigger/trigger.model.js +11 -0
  114. package/dist/core/objects/type/composite-type/composite-type.diff.d.ts +2 -8
  115. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -77
  116. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +3 -3
  117. package/dist/core/objects/type/composite-type/composite-type.model.js +2 -1
  118. package/dist/core/objects/type/enum/enum.diff.d.ts +2 -8
  119. package/dist/core/objects/type/enum/enum.diff.js +25 -112
  120. package/dist/core/objects/type/enum/enum.model.js +1 -1
  121. package/dist/core/objects/type/range/changes/range.create.js +6 -3
  122. package/dist/core/objects/type/range/range.diff.d.ts +2 -8
  123. package/dist/core/objects/type/range/range.diff.js +16 -77
  124. package/dist/core/objects/type/range/range.model.js +1 -1
  125. package/dist/core/objects/view/view.diff.d.ts +2 -8
  126. package/dist/core/objects/view/view.diff.js +16 -158
  127. package/dist/core/objects/view/view.model.d.ts +18 -4
  128. package/dist/core/objects/view/view.model.js +3 -13
  129. package/dist/core/plan/apply.js +9 -26
  130. package/dist/core/plan/create.d.ts +19 -6
  131. package/dist/core/plan/create.js +134 -174
  132. package/dist/core/plan/serialize.js +16 -4
  133. package/dist/core/plan/sql-format/fixtures.js +3 -5
  134. package/dist/core/plan/sql-format/keyword-case.js +26 -1
  135. package/dist/core/plan/ssl-config.d.ts +32 -0
  136. package/dist/core/plan/ssl-config.js +115 -0
  137. package/dist/core/plan/types.d.ts +6 -0
  138. package/dist/core/postgres-config.d.ts +14 -0
  139. package/dist/core/postgres-config.js +53 -2
  140. package/dist/core/sort/graph-builder.js +10 -0
  141. package/dist/core/sort/logical-sort.js +31 -23
  142. package/dist/core/test-utils/assert-valid-sql.d.ts +10 -0
  143. package/dist/core/test-utils/assert-valid-sql.js +19 -0
  144. package/dist/index.d.ts +6 -0
  145. package/dist/index.js +6 -1
  146. package/package.json +21 -4
  147. package/src/cli/app.ts +27 -3
  148. package/src/cli/bin/cli.ts +6 -0
  149. package/src/cli/commands/catalog-export.ts +78 -0
  150. package/src/cli/commands/declarative-apply.diagnostics.test.ts +77 -0
  151. package/src/cli/commands/declarative-apply.ts +380 -0
  152. package/src/cli/commands/declarative-export.ts +330 -0
  153. package/src/cli/commands/plan.ts +28 -7
  154. package/src/cli/exit-code.test.ts +19 -0
  155. package/src/cli/exit-code.ts +7 -0
  156. package/src/cli/formatters/tree/tree.ts +3 -2
  157. package/src/cli/utils/apply-display.test.ts +348 -0
  158. package/src/cli/utils/apply-display.ts +238 -0
  159. package/src/cli/utils/export-display.test.ts +103 -0
  160. package/src/cli/utils/export-display.ts +275 -0
  161. package/src/cli/utils/integrations.test.ts +44 -0
  162. package/src/cli/utils/resolve-input.test.ts +38 -0
  163. package/src/cli/utils/resolve-input.ts +17 -0
  164. package/src/core/catalog-export/index.ts +20 -0
  165. package/src/core/catalog.diff.ts +79 -78
  166. package/src/core/catalog.model.test.ts +122 -0
  167. package/src/core/catalog.model.ts +127 -1
  168. package/src/core/catalog.snapshot.test.ts +464 -0
  169. package/src/core/catalog.snapshot.ts +289 -0
  170. package/src/core/declarative-apply/discover-sql.test.ts +103 -0
  171. package/src/core/declarative-apply/discover-sql.ts +107 -0
  172. package/src/core/declarative-apply/extract-catalog-providers.ts +220 -0
  173. package/src/core/declarative-apply/index.test.ts +67 -0
  174. package/src/core/declarative-apply/index.ts +205 -0
  175. package/src/core/declarative-apply/round-apply.test.ts +504 -0
  176. package/src/core/declarative-apply/round-apply.ts +562 -0
  177. package/src/core/expand-replace-dependencies.test.ts +70 -0
  178. package/src/core/export/file-mapper.test.ts +816 -0
  179. package/src/core/export/file-mapper.ts +574 -0
  180. package/src/core/export/grouper.ts +108 -0
  181. package/src/core/export/index.ts +129 -0
  182. package/src/core/export/types.ts +104 -0
  183. package/src/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  184. package/src/core/integrations/filter/dsl.test.ts +211 -0
  185. package/src/core/integrations/filter/dsl.ts +65 -3
  186. package/src/core/integrations/filter/extractors.test.ts +244 -0
  187. package/src/core/integrations/filter/extractors.ts +42 -0
  188. package/src/core/integrations/integration-dsl.ts +10 -0
  189. package/src/core/integrations/serialize/dsl.test.ts +91 -0
  190. package/src/core/integrations/supabase.ts +9 -0
  191. package/src/core/objects/aggregate/aggregate.diff.ts +39 -95
  192. package/src/core/objects/aggregate/aggregate.model.ts +1 -1
  193. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +3 -1
  194. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +5 -2
  195. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +6 -3
  196. package/src/core/objects/aggregate/changes/aggregate.create.ts +1 -1
  197. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +7 -3
  198. package/src/core/objects/aggregate/changes/aggregate.drop.ts +1 -1
  199. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +9 -3
  200. package/src/core/objects/base.privilege-diff.ts +178 -30
  201. package/src/core/objects/base.privilege.ts +9 -2
  202. package/src/core/objects/collation/changes/collation.alter.test.ts +7 -2
  203. package/src/core/objects/collation/changes/collation.create.test.ts +7 -2
  204. package/src/core/objects/collation/changes/collation.drop.test.ts +4 -1
  205. package/src/core/objects/collation/collation.diff.test.ts +9 -12
  206. package/src/core/objects/collation/collation.diff.ts +2 -1
  207. package/src/core/objects/diff-context.ts +16 -0
  208. package/src/core/objects/domain/changes/domain.alter.test.ts +28 -9
  209. package/src/core/objects/domain/changes/domain.create.test.ts +32 -2
  210. package/src/core/objects/domain/changes/domain.create.ts +7 -1
  211. package/src/core/objects/domain/changes/domain.drop.test.ts +4 -1
  212. package/src/core/objects/domain/domain.diff.ts +39 -102
  213. package/src/core/objects/domain/domain.model.ts +1 -1
  214. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +10 -3
  215. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +4 -1
  216. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +4 -1
  217. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +12 -7
  218. package/src/core/objects/event-trigger/event-trigger.diff.ts +2 -1
  219. package/src/core/objects/extension/changes/extension.alter.test.ts +7 -2
  220. package/src/core/objects/extension/changes/extension.create.test.ts +4 -1
  221. package/src/core/objects/extension/changes/extension.drop.test.ts +4 -1
  222. package/src/core/objects/extension/extension.model.test.ts +98 -0
  223. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +16 -5
  224. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +51 -16
  225. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +4 -1
  226. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +111 -4
  227. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +31 -101
  228. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +2 -2
  229. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +46 -15
  230. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +13 -4
  231. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +4 -1
  232. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +39 -102
  233. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +1 -1
  234. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +22 -7
  235. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +19 -6
  236. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +4 -1
  237. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +95 -0
  238. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +31 -101
  239. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +13 -4
  240. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +16 -5
  241. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +10 -3
  242. package/src/core/objects/index/changes/index.alter.test.ts +13 -4
  243. package/src/core/objects/index/changes/index.create.test.ts +4 -1
  244. package/src/core/objects/index/changes/index.drop.test.ts +4 -1
  245. package/src/core/objects/language/changes/language.alter.test.ts +4 -1
  246. package/src/core/objects/language/changes/language.create.test.ts +4 -1
  247. package/src/core/objects/language/changes/language.drop.test.ts +4 -1
  248. package/src/core/objects/language/language.diff.test.ts +86 -4
  249. package/src/core/objects/language/language.diff.ts +17 -49
  250. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +10 -3
  251. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +7 -2
  252. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +4 -1
  253. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +162 -0
  254. package/src/core/objects/materialized-view/materialized-view.diff.ts +41 -191
  255. package/src/core/objects/materialized-view/materialized-view.model.ts +1 -1
  256. package/src/core/objects/procedure/changes/procedure.alter.test.ts +121 -49
  257. package/src/core/objects/procedure/changes/procedure.alter.ts +15 -12
  258. package/src/core/objects/procedure/changes/procedure.create.test.ts +4 -1
  259. package/src/core/objects/procedure/changes/procedure.drop.test.ts +7 -2
  260. package/src/core/objects/procedure/procedure.diff.ts +39 -102
  261. package/src/core/objects/procedure/procedure.model.ts +1 -1
  262. package/src/core/objects/publication/changes/publication.alter.test.ts +15 -21
  263. package/src/core/objects/publication/changes/publication.alter.ts +0 -18
  264. package/src/core/objects/publication/changes/publication.comment.test.ts +5 -2
  265. package/src/core/objects/publication/changes/publication.create.test.ts +5 -2
  266. package/src/core/objects/publication/changes/publication.drop.test.ts +3 -1
  267. package/src/core/objects/publication/changes/publication.types.ts +0 -2
  268. package/src/core/objects/publication/publication.diff.test.ts +24 -19
  269. package/src/core/objects/publication/publication.diff.ts +9 -15
  270. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +31 -14
  271. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +3 -3
  272. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +10 -3
  273. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +4 -1
  274. package/src/core/objects/role/changes/role.alter.test.ts +31 -15
  275. package/src/core/objects/role/changes/role.create.test.ts +6 -2
  276. package/src/core/objects/role/changes/role.drop.test.ts +4 -1
  277. package/src/core/objects/role/role.diff.test.ts +235 -0
  278. package/src/core/objects/role/role.diff.ts +21 -1
  279. package/src/core/objects/role/role.model.ts +122 -14
  280. package/src/core/objects/rule/changes/rule.alter.test.ts +7 -3
  281. package/src/core/objects/rule/changes/rule.comment.test.ts +5 -2
  282. package/src/core/objects/rule/changes/rule.create.test.ts +6 -2
  283. package/src/core/objects/rule/changes/rule.drop.test.ts +3 -1
  284. package/src/core/objects/schema/changes/schema.alter.test.ts +4 -1
  285. package/src/core/objects/schema/changes/schema.create.test.ts +4 -1
  286. package/src/core/objects/schema/changes/schema.drop.test.ts +4 -1
  287. package/src/core/objects/schema/schema.diff.ts +39 -102
  288. package/src/core/objects/schema/schema.model.ts +1 -1
  289. package/src/core/objects/sequence/changes/sequence.alter.test.ts +11 -5
  290. package/src/core/objects/sequence/changes/sequence.create.test.ts +8 -3
  291. package/src/core/objects/sequence/changes/sequence.drop.test.ts +4 -1
  292. package/src/core/objects/sequence/sequence.diff.test.ts +114 -0
  293. package/src/core/objects/sequence/sequence.diff.ts +39 -104
  294. package/src/core/objects/sequence/sequence.model.ts +1 -1
  295. package/src/core/objects/subscription/changes/subscription.alter.test.ts +15 -5
  296. package/src/core/objects/subscription/changes/subscription.comment.test.ts +5 -2
  297. package/src/core/objects/subscription/changes/subscription.create.test.ts +5 -2
  298. package/src/core/objects/subscription/changes/subscription.drop.test.ts +3 -1
  299. package/src/core/objects/subscription/subscription.diff.test.ts +16 -11
  300. package/src/core/objects/subscription/subscription.diff.ts +2 -1
  301. package/src/core/objects/table/changes/table.alter.test.ts +38 -15
  302. package/src/core/objects/table/changes/table.create.test.ts +41 -3
  303. package/src/core/objects/table/changes/table.create.ts +4 -0
  304. package/src/core/objects/table/changes/table.drop.test.ts +3 -1
  305. package/src/core/objects/table/table.diff.test.ts +157 -0
  306. package/src/core/objects/table/table.diff.ts +54 -190
  307. package/src/core/objects/table/table.model.ts +1 -1
  308. package/src/core/objects/trigger/changes/trigger.alter.test.ts +8 -4
  309. package/src/core/objects/trigger/changes/trigger.create.test.ts +5 -1
  310. package/src/core/objects/trigger/changes/trigger.create.ts +7 -4
  311. package/src/core/objects/trigger/changes/trigger.drop.test.ts +5 -1
  312. package/src/core/objects/trigger/trigger.diff.test.ts +1 -0
  313. package/src/core/objects/trigger/trigger.model.ts +12 -0
  314. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +10 -4
  315. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +7 -2
  316. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +4 -1
  317. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +78 -0
  318. package/src/core/objects/type/composite-type/composite-type.diff.ts +39 -101
  319. package/src/core/objects/type/composite-type/composite-type.model.ts +2 -1
  320. package/src/core/objects/type/enum/changes/enum.alter.test.ts +14 -5
  321. package/src/core/objects/type/enum/changes/enum.create.test.ts +4 -1
  322. package/src/core/objects/type/enum/changes/enum.drop.test.ts +4 -1
  323. package/src/core/objects/type/enum/enum.diff.test.ts +181 -0
  324. package/src/core/objects/type/enum/enum.diff.ts +58 -146
  325. package/src/core/objects/type/enum/enum.model.ts +1 -1
  326. package/src/core/objects/type/range/changes/range.alter.test.ts +3 -1
  327. package/src/core/objects/type/range/changes/range.create.test.ts +5 -2
  328. package/src/core/objects/type/range/changes/range.create.ts +6 -2
  329. package/src/core/objects/type/range/changes/range.drop.test.ts +3 -1
  330. package/src/core/objects/type/range/range.diff.test.ts +77 -0
  331. package/src/core/objects/type/range/range.diff.ts +39 -101
  332. package/src/core/objects/type/range/range.model.ts +1 -1
  333. package/src/core/objects/view/changes/view.alter.test.ts +8 -3
  334. package/src/core/objects/view/changes/view.create.test.ts +7 -2
  335. package/src/core/objects/view/changes/view.drop.test.ts +4 -1
  336. package/src/core/objects/view/view.diff.test.ts +82 -0
  337. package/src/core/objects/view/view.diff.ts +41 -191
  338. package/src/core/objects/view/view.model.ts +3 -17
  339. package/src/core/plan/apply.ts +9 -27
  340. package/src/core/plan/create.ts +173 -237
  341. package/src/core/plan/serialize.test.ts +317 -0
  342. package/src/core/plan/serialize.ts +18 -4
  343. package/src/core/plan/sql-format/fixtures.ts +2 -5
  344. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +52 -0
  345. package/src/core/plan/sql-format/format-off.test.ts +14 -17
  346. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +27 -22
  347. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +17 -21
  348. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +25 -20
  349. package/src/core/plan/sql-format/format-pretty-upper.test.ts +23 -20
  350. package/src/core/plan/sql-format/keyword-case.ts +36 -1
  351. package/src/core/plan/ssl-config.ts +172 -0
  352. package/src/core/plan/types.ts +6 -0
  353. package/src/core/postgres-config.ts +71 -2
  354. package/src/core/sort/graph-builder.ts +12 -0
  355. package/src/core/sort/logical-sort.test.ts +371 -0
  356. package/src/core/sort/logical-sort.ts +32 -25
  357. package/src/core/sort/topological-sort.test.ts +275 -0
  358. package/src/core/test-utils/assert-valid-sql.ts +20 -0
  359. package/src/index.ts +26 -2
@@ -0,0 +1,275 @@
1
+ /**
2
+ * CLI helpers for declarative export: file tree, diff, and summary formatting.
3
+ */
4
+
5
+ import { readdir, readFile } from "node:fs/promises";
6
+ import path from "node:path";
7
+ import chalk from "chalk";
8
+ import type { FileEntry } from "../../core/export/types.ts";
9
+
10
+ // ============================================================================
11
+ // Path safety
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Ensure a relative file path does not escape the output directory.
16
+ * Uses Node.js path.resolve + startsWith as the canonical traversal check.
17
+ */
18
+ export function assertSafePath(filePath: string, outputDir: string): void {
19
+ const resolvedOutput = path.resolve(outputDir);
20
+ const resolvedFile = path.resolve(outputDir, filePath);
21
+ if (
22
+ resolvedFile !== resolvedOutput &&
23
+ !resolvedFile.startsWith(resolvedOutput + path.sep)
24
+ ) {
25
+ throw new Error(
26
+ `Export path traversal detected: '${filePath}' resolves outside output directory`,
27
+ );
28
+ }
29
+ }
30
+
31
+ // ============================================================================
32
+ // Types
33
+ // ============================================================================
34
+
35
+ interface FileDiffResult {
36
+ created: string[];
37
+ updated: string[];
38
+ deleted: string[];
39
+ unchanged: string[];
40
+ }
41
+
42
+ // ============================================================================
43
+ // File tree
44
+ // ============================================================================
45
+
46
+ interface BuildFileTreeOptions {
47
+ /** When provided, leaf paths are prefixed with + / ~ / - and colorized (created / updated / deleted). */
48
+ diff?: FileDiffResult;
49
+ /** When true, only paths that are created, updated, or deleted are shown; unchanged are omitted. Includes diff.deleted in the tree. */
50
+ diffFocus?: boolean;
51
+ }
52
+
53
+ type FileStatus = "created" | "updated" | "deleted" | "unchanged";
54
+
55
+ function getFileStatus(path: string, diff: FileDiffResult): FileStatus {
56
+ if (diff.created.includes(path)) return "created";
57
+ if (diff.updated.includes(path)) return "updated";
58
+ if (diff.deleted.includes(path)) return "deleted";
59
+ return "unchanged";
60
+ }
61
+
62
+ function formatLeafSegment(segment: string, status: FileStatus): string {
63
+ switch (status) {
64
+ case "created":
65
+ return chalk.green(`+ ${segment}`);
66
+ case "updated":
67
+ return chalk.yellow(`~ ${segment}`);
68
+ case "deleted":
69
+ return chalk.red(`- ${segment}`);
70
+ default:
71
+ return chalk.dim(segment);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Build a directory tree string from file paths.
77
+ * Groups by directory, shows files as leaves with indentation.
78
+ * When options.diff is provided, leaf names are prefixed with + (created), ~ (updated), - (deleted) and colorized.
79
+ * When options.diffFocus is true, only changed paths (and their ancestors) are shown; unchanged files are omitted.
80
+ *
81
+ * @param files - Array of relative file paths (e.g. ["schemas/public/schema.sql", "schemas/public/tables/users.sql"])
82
+ * @param outputDir - Display name for the root (e.g. "declarative-schemas")
83
+ * @param options - Optional diff and diffFocus for symbols and filtering
84
+ */
85
+ export function buildFileTree(
86
+ files: string[],
87
+ outputDir: string,
88
+ options?: BuildFileTreeOptions,
89
+ ): string {
90
+ const { diff, diffFocus } = options ?? {};
91
+ let pathsToShow = files;
92
+
93
+ if (diffFocus && diff) {
94
+ const changed = new Set<string>([
95
+ ...diff.created,
96
+ ...diff.updated,
97
+ ...diff.deleted,
98
+ ]);
99
+ pathsToShow = [...changed];
100
+ if (pathsToShow.length === 0) {
101
+ return chalk.dim("(no file changes)");
102
+ }
103
+ }
104
+
105
+ const tree = new Map<string, Set<string>>();
106
+
107
+ for (const filePath of pathsToShow) {
108
+ const segments = filePath.split("/");
109
+ let parent = "";
110
+ for (let i = 0; i < segments.length; i++) {
111
+ const segment = segments[i];
112
+ const fullPath = parent ? `${parent}/${segment}` : segment;
113
+ let children = tree.get(parent);
114
+ if (!children) {
115
+ children = new Set();
116
+ tree.set(parent, children);
117
+ }
118
+ children.add(fullPath);
119
+ parent = fullPath;
120
+ }
121
+ }
122
+
123
+ const lines: string[] = [];
124
+
125
+ function emit(relPath: string, indent: number, isLast: boolean): void {
126
+ const segment = relPath ? path.basename(relPath) : outputDir;
127
+ const prefix =
128
+ indent === 0 ? "" : " ".repeat(indent) + (isLast ? "└── " : "├── ");
129
+ const isLeaf = !tree.has(relPath);
130
+ const displaySegment =
131
+ diff && isLeaf
132
+ ? formatLeafSegment(segment, getFileStatus(relPath, diff))
133
+ : segment;
134
+ lines.push(prefix + displaySegment);
135
+ const children = tree.get(relPath);
136
+ if (children) {
137
+ const sorted = [...children].sort((a, b) =>
138
+ path.basename(a).localeCompare(path.basename(b)),
139
+ );
140
+ for (let i = 0; i < sorted.length; i++) {
141
+ emit(sorted[i], indent + 1, i === sorted.length - 1);
142
+ }
143
+ }
144
+ }
145
+
146
+ emit("", 0, false);
147
+ return lines.join("\n");
148
+ }
149
+
150
+ // ============================================================================
151
+ // File diff
152
+ // ============================================================================
153
+
154
+ /**
155
+ * Recursively collect relative paths of managed (.sql) files under a directory.
156
+ * Non-SQL files (README, .gitkeep, etc.) are intentionally excluded so they
157
+ * are never flagged as "deleted" during diff.
158
+ */
159
+ async function collectExistingFiles(dir: string, base = ""): Promise<string[]> {
160
+ const entries = await readdir(path.join(dir, base), { withFileTypes: true });
161
+ const files: string[] = [];
162
+ for (const e of entries) {
163
+ const rel = base ? `${base}/${e.name}` : e.name;
164
+ if (e.isFile() && e.name.endsWith(".sql")) {
165
+ files.push(rel);
166
+ } else if (e.isDirectory()) {
167
+ files.push(...(await collectExistingFiles(dir, rel)));
168
+ }
169
+ }
170
+ return files;
171
+ }
172
+
173
+ /**
174
+ * Compare existing output directory with new file set.
175
+ * Returns created, updated, deleted, and unchanged paths.
176
+ */
177
+ export async function computeFileDiff(
178
+ outputDir: string,
179
+ newFiles: FileEntry[],
180
+ ): Promise<FileDiffResult> {
181
+ const newPaths = new Set(newFiles.map((f) => f.path));
182
+ const newByPath = new Map(newFiles.map((f) => [f.path, f]));
183
+
184
+ let existingPaths: string[] = [];
185
+ try {
186
+ existingPaths = await collectExistingFiles(outputDir);
187
+ } catch {
188
+ // Directory doesn't exist or not readable
189
+ return {
190
+ created: [...newPaths],
191
+ updated: [],
192
+ deleted: [],
193
+ unchanged: [],
194
+ };
195
+ }
196
+
197
+ const existingSet = new Set(existingPaths);
198
+ const created: string[] = [];
199
+ const updated: string[] = [];
200
+ const deleted: string[] = [];
201
+ const unchanged: string[] = [];
202
+
203
+ for (const p of newPaths) {
204
+ if (!existingSet.has(p)) {
205
+ created.push(p);
206
+ } else {
207
+ const entry = newByPath.get(p);
208
+ if (!entry) continue;
209
+ try {
210
+ const existingContent = await readFile(
211
+ path.join(outputDir, p),
212
+ "utf-8",
213
+ );
214
+ if (existingContent.trim() !== entry.sql.trim()) {
215
+ updated.push(p);
216
+ } else {
217
+ unchanged.push(p);
218
+ }
219
+ } catch {
220
+ updated.push(p);
221
+ }
222
+ }
223
+ }
224
+
225
+ for (const p of existingPaths) {
226
+ if (!newPaths.has(p)) {
227
+ deleted.push(p);
228
+ }
229
+ }
230
+
231
+ return { created, updated, deleted, unchanged };
232
+ }
233
+
234
+ // ============================================================================
235
+ // Summary formatting
236
+ // ============================================================================
237
+
238
+ /**
239
+ * Format the created/deleted/updated summary with colors.
240
+ * In dry-run mode, uses "would create/delete/update" phrasing.
241
+ */
242
+ export function formatExportSummary(
243
+ diff: FileDiffResult,
244
+ dryRun: boolean,
245
+ ): string {
246
+ const lines: string[] = [];
247
+ const verb = dryRun ? "Would" : "";
248
+
249
+ if (diff.created.length > 0) {
250
+ lines.push(
251
+ chalk.green(
252
+ `${verb ? `${verb} create` : "Created"}: ${diff.created.length} file(s)`,
253
+ ),
254
+ );
255
+ }
256
+ if (diff.updated.length > 0) {
257
+ lines.push(
258
+ chalk.yellow(
259
+ `${verb ? `${verb} update` : "Updated"}: ${diff.updated.length} file(s)`,
260
+ ),
261
+ );
262
+ }
263
+ if (diff.deleted.length > 0) {
264
+ lines.push(
265
+ chalk.red(
266
+ `${verb ? `${verb} delete` : "Deleted"}: ${diff.deleted.length} file(s)`,
267
+ ),
268
+ );
269
+ }
270
+ if (diff.unchanged.length > 0 && !dryRun) {
271
+ lines.push(chalk.dim(`Unchanged: ${diff.unchanged.length} file(s)`));
272
+ }
273
+
274
+ return lines.length > 0 ? lines.join("\n") : "";
275
+ }
@@ -0,0 +1,44 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { loadIntegrationDSL } from "./integrations.ts";
6
+
7
+ describe("loadIntegrationDSL", () => {
8
+ test("loads from .json file path", async () => {
9
+ const dir = await mkdtemp(path.join(tmpdir(), "pgd-integration-"));
10
+ const jsonPath = path.join(dir, "custom.json");
11
+ try {
12
+ await writeFile(
13
+ jsonPath,
14
+ JSON.stringify({
15
+ filter: { schema: "app" },
16
+ }),
17
+ );
18
+ const dsl = await loadIntegrationDSL(jsonPath);
19
+ expect(dsl).toBeDefined();
20
+ expect(dsl.filter).toEqual({ schema: "app" });
21
+ } finally {
22
+ await rm(dir, { recursive: true, force: true });
23
+ }
24
+ });
25
+
26
+ test("loads core integration by name (supabase)", async () => {
27
+ const dsl = await loadIntegrationDSL("supabase");
28
+ expect(dsl).toBeDefined();
29
+ expect(dsl.filter).toBeDefined();
30
+ expect(dsl.serialize).toBeDefined();
31
+ });
32
+
33
+ test("fallback to file path when core module not found", async () => {
34
+ const dir = await mkdtemp(path.join(tmpdir(), "pgd-integration-"));
35
+ const filePath = path.join(dir, "custom-dsl");
36
+ await writeFile(filePath, JSON.stringify({ serialize: [] }));
37
+ try {
38
+ const dsl = await loadIntegrationDSL(filePath);
39
+ expect(dsl).toEqual({ serialize: [] });
40
+ } finally {
41
+ await rm(dir, { recursive: true, force: true });
42
+ }
43
+ });
44
+ });
@@ -0,0 +1,38 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import path from "node:path";
3
+ import { isPostgresUrl, loadCatalogFromFile } from "./resolve-input.ts";
4
+
5
+ describe("isPostgresUrl", () => {
6
+ test("returns true for postgres:// URL", () => {
7
+ expect(isPostgresUrl("postgres://user:pass@localhost:5432/db")).toBe(true);
8
+ });
9
+
10
+ test("returns true for postgresql:// URL", () => {
11
+ expect(isPostgresUrl("postgresql://localhost/db")).toBe(true);
12
+ });
13
+
14
+ test("returns false for file path", () => {
15
+ expect(isPostgresUrl("/path/to/catalog.json")).toBe(false);
16
+ expect(isPostgresUrl("catalog.json")).toBe(false);
17
+ });
18
+
19
+ test("returns false for other strings", () => {
20
+ expect(isPostgresUrl("")).toBe(false);
21
+ expect(isPostgresUrl("postgres")).toBe(false);
22
+ });
23
+ });
24
+
25
+ describe("loadCatalogFromFile", () => {
26
+ test("loads and deserializes catalog from JSON file", async () => {
27
+ const fixturePath = path.join(
28
+ import.meta.dir,
29
+ "../../core/fixtures/empty-catalogs/postgres-15-16-baseline.json",
30
+ );
31
+ const catalog = await loadCatalogFromFile(fixturePath);
32
+ expect(catalog).toBeDefined();
33
+ expect(catalog.version).toBeGreaterThan(0);
34
+ expect(typeof catalog.currentUser).toBe("string");
35
+ expect(catalog.schemas).toBeDefined();
36
+ expect(catalog.depends).toEqual(expect.any(Array));
37
+ });
38
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Shared utilities for resolving CLI --source/--target inputs that
3
+ * can be either a PostgreSQL connection URL or a catalog snapshot file path.
4
+ */
5
+
6
+ import { readFile } from "node:fs/promises";
7
+ import type { Catalog } from "../../core/catalog.model.ts";
8
+ import { deserializeCatalog } from "../../core/catalog.snapshot.ts";
9
+
10
+ export function isPostgresUrl(input: string): boolean {
11
+ return input.startsWith("postgres://") || input.startsWith("postgresql://");
12
+ }
13
+
14
+ export async function loadCatalogFromFile(path: string): Promise<Catalog> {
15
+ const json = await readFile(path, "utf-8");
16
+ return deserializeCatalog(JSON.parse(json));
17
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Catalog export – programmatic API for extracting a database catalog
3
+ * and serializing it to a JSON snapshot.
4
+ *
5
+ * Use this subpath when you only need catalog export (e.g. Supabase CLI
6
+ * edge-runtime templates) without pulling in the full pg-delta API.
7
+ */
8
+
9
+ export {
10
+ Catalog,
11
+ createEmptyCatalog,
12
+ extractCatalog,
13
+ } from "../catalog.model.ts";
14
+ export type { CatalogSnapshot } from "../catalog.snapshot.ts";
15
+ export {
16
+ deserializeCatalog,
17
+ serializeCatalog,
18
+ stringifyCatalogSnapshot,
19
+ } from "../catalog.snapshot.ts";
20
+ export { createManagedPool } from "../postgres-config.ts";
@@ -37,10 +37,55 @@ import { diffRanges } from "./objects/type/range/range.diff.ts";
37
37
  import { stringifyWithBigInt } from "./objects/utils.ts";
38
38
  import { diffViews } from "./objects/view/view.diff.ts";
39
39
 
40
+ type PrivilegeChange = Extract<Change, { scope: "privilege" }>;
41
+
42
+ /**
43
+ * Get the stableId of the target object for a privilege change.
44
+ * Used to filter out redundant REVOKE statements for dropped objects.
45
+ */
46
+ function getPrivilegeTargetStableId(change: PrivilegeChange): string {
47
+ switch (change.objectType) {
48
+ case "composite_type":
49
+ return change.compositeType.stableId;
50
+ case "domain":
51
+ return change.domain.stableId;
52
+ case "enum":
53
+ return change.enum.stableId;
54
+ case "language":
55
+ return change.language.stableId;
56
+ case "materialized_view":
57
+ return change.materializedView.stableId;
58
+ case "aggregate":
59
+ return change.aggregate.stableId;
60
+ case "procedure":
61
+ return change.procedure.stableId;
62
+ case "range":
63
+ return change.range.stableId;
64
+ case "schema":
65
+ return change.schema.stableId;
66
+ case "sequence":
67
+ return change.sequence.stableId;
68
+ case "table":
69
+ return change.table.stableId;
70
+ case "view":
71
+ return change.view.stableId;
72
+ case "foreign_data_wrapper":
73
+ return change.foreignDataWrapper.stableId;
74
+ case "server":
75
+ return change.server.stableId;
76
+ case "foreign_table":
77
+ return change.foreignTable.stableId;
78
+ default: {
79
+ const _exhaustive: never = change;
80
+ return _exhaustive;
81
+ }
82
+ }
83
+ }
84
+
40
85
  export function diffCatalogs(
41
86
  main: Catalog,
42
87
  branch: Catalog,
43
- options?: { role?: string },
88
+ options?: { role?: string; skipDefaultPrivilegeSubtraction?: boolean },
44
89
  ) {
45
90
  const changes: Change[] = [];
46
91
 
@@ -56,24 +101,33 @@ export function diffCatalogs(
56
101
  // This represents what defaults will be in effect after all ALTER DEFAULT PRIVILEGES
57
102
  // Since ALTER DEFAULT PRIVILEGES runs before CREATE (via constraint spec),
58
103
  // all created objects will use these final defaults.
59
- const defaultPrivilegeState = new DefaultPrivilegeState(main.roles);
60
- for (const change of roleChanges) {
61
- if (change instanceof GrantRoleDefaultPrivileges) {
62
- defaultPrivilegeState.applyGrant(
63
- change.role.name,
64
- change.objtype,
65
- change.inSchema,
66
- change.grantee,
67
- change.privileges,
68
- );
69
- } else if (change instanceof RevokeRoleDefaultPrivileges) {
70
- defaultPrivilegeState.applyRevoke(
71
- change.role.name,
72
- change.objtype,
73
- change.inSchema,
74
- change.grantee,
75
- change.privileges,
76
- );
104
+ //
105
+ // When skipDefaultPrivilegeSubtraction is true, we use an empty state so that
106
+ // getEffectiveDefaults always returns [] -- no privileges are subtracted and
107
+ // every GRANT is emitted explicitly. This is needed for declarative export
108
+ // where the output must be self-contained regardless of statement execution order.
109
+ const defaultPrivilegeState = options?.skipDefaultPrivilegeSubtraction
110
+ ? new DefaultPrivilegeState({})
111
+ : new DefaultPrivilegeState(main.roles);
112
+ if (!options?.skipDefaultPrivilegeSubtraction) {
113
+ for (const change of roleChanges) {
114
+ if (change instanceof GrantRoleDefaultPrivileges) {
115
+ defaultPrivilegeState.applyGrant(
116
+ change.role.name,
117
+ change.objtype,
118
+ change.inSchema,
119
+ change.grantee,
120
+ change.privileges,
121
+ );
122
+ } else if (change instanceof RevokeRoleDefaultPrivileges) {
123
+ defaultPrivilegeState.applyRevoke(
124
+ change.role.name,
125
+ change.objtype,
126
+ change.inSchema,
127
+ change.grantee,
128
+ change.privileges,
129
+ );
130
+ }
77
131
  }
78
132
  }
79
133
 
@@ -88,6 +142,7 @@ export function diffCatalogs(
88
142
  currentUser: effectiveUser,
89
143
  defaultPrivilegeState,
90
144
  mainRoles: main.roles,
145
+ skipDefaultPrivilegeSubtraction: options?.skipDefaultPrivilegeSubtraction,
91
146
  };
92
147
 
93
148
  // Step 4: Diff all other objects with default privileges context
@@ -95,11 +150,7 @@ export function diffCatalogs(
95
150
  ...diffAggregates(diffContext, main.aggregates, branch.aggregates),
96
151
  );
97
152
  changes.push(
98
- ...diffCollations(
99
- { currentUser: effectiveUser },
100
- main.collations,
101
- branch.collations,
102
- ),
153
+ ...diffCollations(diffContext, main.collations, branch.collations),
103
154
  );
104
155
  changes.push(
105
156
  ...diffCompositeTypes(
@@ -122,18 +173,10 @@ export function diffCatalogs(
122
173
  ),
123
174
  );
124
175
  changes.push(
125
- ...diffSubscriptions(
126
- { currentUser: effectiveUser },
127
- main.subscriptions,
128
- branch.subscriptions,
129
- ),
176
+ ...diffSubscriptions(diffContext, main.subscriptions, branch.subscriptions),
130
177
  );
131
178
  changes.push(
132
- ...diffPublications(
133
- { currentUser: effectiveUser },
134
- main.publications,
135
- branch.publications,
136
- ),
179
+ ...diffPublications(diffContext, main.publications, branch.publications),
137
180
  );
138
181
  changes.push(
139
182
  ...diffProcedures(diffContext, main.procedures, branch.procedures),
@@ -153,11 +196,7 @@ export function diffCatalogs(
153
196
  ...diffTriggers(main.triggers, branch.triggers, branch.indexableObjects),
154
197
  );
155
198
  changes.push(
156
- ...diffEventTriggers(
157
- { currentUser: effectiveUser },
158
- main.eventTriggers,
159
- branch.eventTriggers,
160
- ),
199
+ ...diffEventTriggers(diffContext, main.eventTriggers, branch.eventTriggers),
161
200
  );
162
201
  changes.push(...diffRules(main.rules, branch.rules));
163
202
  changes.push(...diffRanges(diffContext, main.ranges, branch.ranges));
@@ -188,45 +227,7 @@ export function diffCatalogs(
188
227
  }
189
228
  let filteredChanges = changes.filter((change) => {
190
229
  if (change.operation === "alter" && change.scope === "privilege") {
191
- switch (change.objectType) {
192
- case "composite_type":
193
- return !droppedObjectStableIds.has(change.compositeType.stableId);
194
- case "domain":
195
- return !droppedObjectStableIds.has(change.domain.stableId);
196
- case "enum":
197
- return !droppedObjectStableIds.has(change.enum.stableId);
198
- case "language":
199
- return !droppedObjectStableIds.has(change.language.stableId);
200
- case "materialized_view":
201
- return !droppedObjectStableIds.has(change.materializedView.stableId);
202
- case "aggregate":
203
- return !droppedObjectStableIds.has(change.aggregate.stableId);
204
- case "procedure":
205
- return !droppedObjectStableIds.has(change.procedure.stableId);
206
- case "range":
207
- return !droppedObjectStableIds.has(change.range.stableId);
208
- case "schema":
209
- return !droppedObjectStableIds.has(change.schema.stableId);
210
- case "sequence":
211
- return !droppedObjectStableIds.has(change.sequence.stableId);
212
- case "table":
213
- return !droppedObjectStableIds.has(change.table.stableId);
214
- case "view":
215
- return !droppedObjectStableIds.has(change.view.stableId);
216
- case "foreign_data_wrapper":
217
- return !droppedObjectStableIds.has(
218
- change.foreignDataWrapper.stableId,
219
- );
220
- case "server":
221
- return !droppedObjectStableIds.has(change.server.stableId);
222
- case "foreign_table":
223
- return !droppedObjectStableIds.has(change.foreignTable.stableId);
224
- default: {
225
- // exhaustiveness check
226
- const _exhaustive: never = change;
227
- return _exhaustive;
228
- }
229
- }
230
+ return !droppedObjectStableIds.has(getPrivilegeTargetStableId(change));
230
231
  }
231
232
  return true;
232
233
  });