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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -1,5 +1,5 @@
1
1
  import { diffObjects } from "../base.diff.js";
2
- import { diffPrivileges, filterPublicBuiltInDefaults, groupPrivilegesByGrantable, } from "../base.privilege-diff.js";
2
+ import { diffPrivileges, emitObjectPrivilegeChanges, filterPublicBuiltInDefaults, } from "../base.privilege-diff.js";
3
3
  import { AlterDomainAddConstraint, AlterDomainChangeOwner, AlterDomainDropConstraint, AlterDomainDropDefault, AlterDomainDropNotNull, AlterDomainSetDefault, AlterDomainSetNotNull, AlterDomainValidateConstraint, } from "./changes/domain.alter.js";
4
4
  import { CreateCommentOnDomain, DropCommentOnDomain, } from "./changes/domain.comment.js";
5
5
  import { CreateDomain } from "./changes/domain.create.js";
@@ -50,50 +50,21 @@ export function diffDomains(ctx, main, branch) {
50
50
  // We compare default privileges against desired privileges to generate REVOKE/GRANT statements
51
51
  // needed to reach the final desired state.
52
52
  const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(ctx.currentUser, "domain", newDomain.schema ?? "");
53
+ const creatorFilteredDefaults = newDomain.owner !== ctx.currentUser
54
+ ? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
55
+ : effectiveDefaults;
53
56
  // Filter out PUBLIC's built-in default USAGE privilege (PostgreSQL grants it automatically)
54
57
  // Reference: https://www.postgresql.org/docs/17/ddl-priv.html Table 5.2
55
58
  // This prevents generating unnecessary "GRANT USAGE TO PUBLIC" statements
56
59
  const desiredPrivileges = filterPublicBuiltInDefaults("domain", newDomain.privileges);
57
60
  // Filter out owner privileges - owner always has ALL privileges implicitly
58
61
  // and shouldn't be compared. Use the domain owner as the reference.
59
- const privilegeResults = diffPrivileges(effectiveDefaults, desiredPrivileges, newDomain.owner, ctx.mainRoles);
60
- // Generate grant changes
61
- for (const [grantee, result] of privilegeResults) {
62
- if (result.grants.length > 0) {
63
- const grantGroups = groupPrivilegesByGrantable(result.grants);
64
- for (const [grantable, list] of grantGroups) {
65
- void grantable;
66
- changes.push(new GrantDomainPrivileges({
67
- domain: newDomain,
68
- grantee,
69
- privileges: list,
70
- version: ctx.version,
71
- }));
72
- }
73
- }
74
- // Generate revoke changes
75
- if (result.revokes.length > 0) {
76
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
77
- for (const [grantable, list] of revokeGroups) {
78
- void grantable;
79
- changes.push(new RevokeDomainPrivileges({
80
- domain: newDomain,
81
- grantee,
82
- privileges: list,
83
- version: ctx.version,
84
- }));
85
- }
86
- }
87
- // Generate revoke grant option changes
88
- if (result.revokeGrantOption.length > 0) {
89
- changes.push(new RevokeGrantOptionDomainPrivileges({
90
- domain: newDomain,
91
- grantee,
92
- privilegeNames: result.revokeGrantOption,
93
- version: ctx.version,
94
- }));
95
- }
96
- }
62
+ const privilegeResults = diffPrivileges(filterPublicBuiltInDefaults("domain", creatorFilteredDefaults), desiredPrivileges, newDomain.owner);
63
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, newDomain, newDomain, "domain", {
64
+ Grant: GrantDomainPrivileges,
65
+ Revoke: RevokeDomainPrivileges,
66
+ RevokeGrantOption: RevokeGrantOptionDomainPrivileges,
67
+ }, ctx.version));
97
68
  }
98
69
  for (const domainId of dropped) {
99
70
  changes.push(new DropDomain({ domain: main[domainId] }));
@@ -201,44 +172,12 @@ export function diffDomains(ctx, main, branch) {
201
172
  const branchPrivilegesFiltered = filterPublicBuiltInDefaults("domain", branchDomain.privileges);
202
173
  // Filter out owner privileges - owner always has ALL privileges implicitly
203
174
  // and shouldn't be compared. Use branch owner as the reference.
204
- const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchDomain.owner, ctx.mainRoles);
205
- for (const [grantee, result] of privilegeResults) {
206
- // Generate grant changes
207
- if (result.grants.length > 0) {
208
- const grantGroups = groupPrivilegesByGrantable(result.grants);
209
- for (const [grantable, list] of grantGroups) {
210
- void grantable;
211
- changes.push(new GrantDomainPrivileges({
212
- domain: branchDomain,
213
- grantee,
214
- privileges: list,
215
- version: ctx.version,
216
- }));
217
- }
218
- }
219
- // Generate revoke changes
220
- if (result.revokes.length > 0) {
221
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
222
- for (const [grantable, list] of revokeGroups) {
223
- void grantable;
224
- changes.push(new RevokeDomainPrivileges({
225
- domain: mainDomain,
226
- grantee,
227
- privileges: list,
228
- version: ctx.version,
229
- }));
230
- }
231
- }
232
- // Generate revoke grant option changes
233
- if (result.revokeGrantOption.length > 0) {
234
- changes.push(new RevokeGrantOptionDomainPrivileges({
235
- domain: mainDomain,
236
- grantee,
237
- privilegeNames: result.revokeGrantOption,
238
- version: ctx.version,
239
- }));
240
- }
241
- }
175
+ const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchDomain.owner);
176
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchDomain, mainDomain, "domain", {
177
+ Grant: GrantDomainPrivileges,
178
+ Revoke: RevokeDomainPrivileges,
179
+ RevokeGrantOption: RevokeGrantOptionDomainPrivileges,
180
+ }, ctx.version));
242
181
  }
243
182
  return changes;
244
183
  }
@@ -150,7 +150,7 @@ export async function extractDomains(pool) {
150
150
  )
151
151
  order by x.grantee, x.privilege_type
152
152
  )
153
- from lateral aclexplode(t.typacl) as x(grantor, grantee, privilege_type, is_grantable)
153
+ from lateral aclexplode(COALESCE(t.typacl, acldefault('T', t.typowner))) as x(grantor, grantee, privilege_type, is_grantable)
154
154
  ), '[]'
155
155
  ) as privileges
156
156
  from
@@ -1,3 +1,4 @@
1
+ import type { ObjectDiffContext } from "../diff-context.ts";
1
2
  import type { EventTriggerChange } from "./changes/event-trigger.types.ts";
2
3
  import type { EventTrigger } from "./event-trigger.model.ts";
3
4
  /**
@@ -8,6 +9,4 @@ import type { EventTrigger } from "./event-trigger.model.ts";
8
9
  * @param branch - The event triggers in the branch catalog.
9
10
  * @returns A list of changes to apply to main to make it match branch.
10
11
  */
11
- export declare function diffEventTriggers(ctx: {
12
- currentUser: string;
13
- }, main: Record<string, EventTrigger>, branch: Record<string, EventTrigger>): EventTriggerChange[];
12
+ export declare function diffEventTriggers(ctx: Pick<ObjectDiffContext, "currentUser">, main: Record<string, EventTrigger>, branch: Record<string, EventTrigger>): EventTriggerChange[];
@@ -1,5 +1,4 @@
1
- import type { DefaultPrivilegeState } from "../../base.default-privileges.ts";
2
- import type { Role } from "../../role/role.model.ts";
1
+ import type { ObjectDiffContext } from "../../diff-context.ts";
3
2
  import type { ForeignDataWrapperChange } from "./changes/foreign-data-wrapper.types.ts";
4
3
  import type { ForeignDataWrapper } from "./foreign-data-wrapper.model.ts";
5
4
  /**
@@ -10,9 +9,4 @@ import type { ForeignDataWrapper } from "./foreign-data-wrapper.model.ts";
10
9
  * @param branch - The foreign data wrappers in the branch catalog.
11
10
  * @returns A list of changes to apply to main to make it match branch.
12
11
  */
13
- export declare function diffForeignDataWrappers(ctx: {
14
- version: number;
15
- currentUser: string;
16
- defaultPrivilegeState: DefaultPrivilegeState;
17
- mainRoles: Record<string, Role>;
18
- }, main: Record<string, ForeignDataWrapper>, branch: Record<string, ForeignDataWrapper>): ForeignDataWrapperChange[];
12
+ export declare function diffForeignDataWrappers(ctx: Pick<ObjectDiffContext, "version" | "currentUser">, main: Record<string, ForeignDataWrapper>, branch: Record<string, ForeignDataWrapper>): ForeignDataWrapperChange[];
@@ -1,5 +1,5 @@
1
1
  import { diffObjects } from "../../base.diff.js";
2
- import { diffPrivileges, filterPublicBuiltInDefaults, groupPrivilegesByGrantable, } from "../../base.privilege-diff.js";
2
+ import { diffPrivileges, emitObjectPrivilegeChanges, filterPublicBuiltInDefaults, } from "../../base.privilege-diff.js";
3
3
  import { AlterForeignDataWrapperChangeOwner, AlterForeignDataWrapperSetOptions, } from "./changes/foreign-data-wrapper.alter.js";
4
4
  import { CreateCommentOnForeignDataWrapper, DropCommentOnForeignDataWrapper, } from "./changes/foreign-data-wrapper.comment.js";
5
5
  import { CreateForeignDataWrapper } from "./changes/foreign-data-wrapper.create.js";
@@ -37,44 +37,12 @@ export function diffForeignDataWrappers(ctx, main, branch) {
37
37
  const effectiveDefaults = [];
38
38
  const desiredPrivileges = filterPublicBuiltInDefaults("foreign_data_wrapper", createdFdw.privileges);
39
39
  // Filter out owner privileges - owner always has ALL privileges implicitly
40
- const privilegeResults = diffPrivileges(effectiveDefaults, desiredPrivileges, createdFdw.owner, ctx.mainRoles);
41
- // Generate grant changes
42
- for (const [grantee, result] of privilegeResults) {
43
- if (result.grants.length > 0) {
44
- const grantGroups = groupPrivilegesByGrantable(result.grants);
45
- for (const [grantable, list] of grantGroups) {
46
- void grantable;
47
- changes.push(new GrantForeignDataWrapperPrivileges({
48
- foreignDataWrapper: createdFdw,
49
- grantee,
50
- privileges: list,
51
- version: ctx.version,
52
- }));
53
- }
54
- }
55
- // Generate revoke changes
56
- if (result.revokes.length > 0) {
57
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
58
- for (const [grantable, list] of revokeGroups) {
59
- void grantable;
60
- changes.push(new RevokeForeignDataWrapperPrivileges({
61
- foreignDataWrapper: createdFdw,
62
- grantee,
63
- privileges: list,
64
- version: ctx.version,
65
- }));
66
- }
67
- }
68
- // Generate revoke grant option changes
69
- if (result.revokeGrantOption.length > 0) {
70
- changes.push(new RevokeGrantOptionForeignDataWrapperPrivileges({
71
- foreignDataWrapper: createdFdw,
72
- grantee,
73
- privilegeNames: result.revokeGrantOption,
74
- version: ctx.version,
75
- }));
76
- }
77
- }
40
+ const privilegeResults = diffPrivileges(effectiveDefaults, desiredPrivileges, createdFdw.owner);
41
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, createdFdw, createdFdw, "foreignDataWrapper", {
42
+ Grant: GrantForeignDataWrapperPrivileges,
43
+ Revoke: RevokeForeignDataWrapperPrivileges,
44
+ RevokeGrantOption: RevokeGrantOptionForeignDataWrapperPrivileges,
45
+ }, ctx.version));
78
46
  }
79
47
  for (const fdwId of dropped) {
80
48
  changes.push(new DropForeignDataWrapper({ foreignDataWrapper: main[fdwId] }));
@@ -133,44 +101,12 @@ export function diffForeignDataWrappers(ctx, main, branch) {
133
101
  // PRIVILEGES
134
102
  const mainPrivilegesFiltered = filterPublicBuiltInDefaults("foreign_data_wrapper", mainFdw.privileges);
135
103
  const branchPrivilegesFiltered = filterPublicBuiltInDefaults("foreign_data_wrapper", branchFdw.privileges);
136
- const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchFdw.owner, ctx.mainRoles);
137
- for (const [grantee, result] of privilegeResults) {
138
- // Generate grant changes
139
- if (result.grants.length > 0) {
140
- const grantGroups = groupPrivilegesByGrantable(result.grants);
141
- for (const [grantable, list] of grantGroups) {
142
- void grantable;
143
- changes.push(new GrantForeignDataWrapperPrivileges({
144
- foreignDataWrapper: branchFdw,
145
- grantee,
146
- privileges: list,
147
- version: ctx.version,
148
- }));
149
- }
150
- }
151
- // Generate revoke changes
152
- if (result.revokes.length > 0) {
153
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
154
- for (const [grantable, list] of revokeGroups) {
155
- void grantable;
156
- changes.push(new RevokeForeignDataWrapperPrivileges({
157
- foreignDataWrapper: mainFdw,
158
- grantee,
159
- privileges: list,
160
- version: ctx.version,
161
- }));
162
- }
163
- }
164
- // Generate revoke grant option changes
165
- if (result.revokeGrantOption.length > 0) {
166
- changes.push(new RevokeGrantOptionForeignDataWrapperPrivileges({
167
- foreignDataWrapper: mainFdw,
168
- grantee,
169
- privilegeNames: result.revokeGrantOption,
170
- version: ctx.version,
171
- }));
172
- }
173
- }
104
+ const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchFdw.owner);
105
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchFdw, mainFdw, "foreignDataWrapper", {
106
+ Grant: GrantForeignDataWrapperPrivileges,
107
+ Revoke: RevokeForeignDataWrapperPrivileges,
108
+ RevokeGrantOption: RevokeGrantOptionForeignDataWrapperPrivileges,
109
+ }, ctx.version));
174
110
  // Note: FDW renaming would also use ALTER FOREIGN DATA WRAPPER ... RENAME TO ...
175
111
  // But since our ForeignDataWrapper model uses 'name' as the identity field,
176
112
  // a name change would be handled as drop + create by diffObjects()
@@ -73,11 +73,11 @@ export async function extractForeignDataWrappers(pool) {
73
73
  fdw.fdwowner::regrole::text as owner,
74
74
  case
75
75
  when fdw.fdwhandler = 0 then null
76
- else p_handler.pronamespace::regnamespace::text || '.' || quote_ident(p_handler.proname) || '(' || pg_get_function_identity_arguments(fdw.fdwhandler) || ')'
76
+ else p_handler.pronamespace::regnamespace::text || '.' || quote_ident(p_handler.proname)
77
77
  end as handler,
78
78
  case
79
79
  when fdw.fdwvalidator = 0 then null
80
- else p_validator.pronamespace::regnamespace::text || '.' || quote_ident(p_validator.proname) || '(' || pg_get_function_identity_arguments(fdw.fdwvalidator) || ')'
80
+ else p_validator.pronamespace::regnamespace::text || '.' || quote_ident(p_validator.proname)
81
81
  end as validator,
82
82
  coalesce(fdw.fdwoptions, array[]::text[]) as options,
83
83
  obj_description(fdw.oid, 'pg_foreign_data_wrapper') as comment,
@@ -1,5 +1,4 @@
1
- import type { DefaultPrivilegeState } from "../../base.default-privileges.ts";
2
- import type { Role } from "../../role/role.model.ts";
1
+ import type { ObjectDiffContext } from "../../diff-context.ts";
3
2
  import type { ForeignTableChange } from "./changes/foreign-table.types.ts";
4
3
  import type { ForeignTable } from "./foreign-table.model.ts";
5
4
  /**
@@ -10,9 +9,4 @@ import type { ForeignTable } from "./foreign-table.model.ts";
10
9
  * @param branch - The foreign tables in the branch catalog.
11
10
  * @returns A list of changes to apply to main to make it match branch.
12
11
  */
13
- export declare function diffForeignTables(ctx: {
14
- version: number;
15
- currentUser: string;
16
- defaultPrivilegeState: DefaultPrivilegeState;
17
- mainRoles: Record<string, Role>;
18
- }, main: Record<string, ForeignTable>, branch: Record<string, ForeignTable>): ForeignTableChange[];
12
+ export declare function diffForeignTables(ctx: Pick<ObjectDiffContext, "version" | "currentUser" | "defaultPrivilegeState">, main: Record<string, ForeignTable>, branch: Record<string, ForeignTable>): ForeignTableChange[];
@@ -1,5 +1,5 @@
1
1
  import { diffObjects } from "../../base.diff.js";
2
- import { diffPrivileges, filterPublicBuiltInDefaults, groupPrivilegesByGrantable, } from "../../base.privilege-diff.js";
2
+ import { diffPrivileges, emitObjectPrivilegeChanges, filterPublicBuiltInDefaults, } from "../../base.privilege-diff.js";
3
3
  import { AlterForeignTableAddColumn, AlterForeignTableAlterColumnDropDefault, AlterForeignTableAlterColumnDropNotNull, AlterForeignTableAlterColumnSetDefault, AlterForeignTableAlterColumnSetNotNull, AlterForeignTableAlterColumnType, AlterForeignTableChangeOwner, AlterForeignTableDropColumn, AlterForeignTableSetOptions, } from "./changes/foreign-table.alter.js";
4
4
  import { CreateCommentOnForeignTable, DropCommentOnForeignTable, } from "./changes/foreign-table.comment.js";
5
5
  import { CreateForeignTable } from "./changes/foreign-table.create.js";
@@ -32,45 +32,16 @@ export function diffForeignTables(ctx, main, branch) {
32
32
  }
33
33
  // PRIVILEGES: For created objects, compare against default privileges state
34
34
  const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(ctx.currentUser, "foreign_table", createdTable.schema ?? "");
35
+ const creatorFilteredDefaults = createdTable.owner !== ctx.currentUser
36
+ ? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
37
+ : effectiveDefaults;
35
38
  const desiredPrivileges = filterPublicBuiltInDefaults("foreign_table", createdTable.privileges);
36
- const privilegeResults = diffPrivileges(effectiveDefaults, desiredPrivileges, createdTable.owner, ctx.mainRoles);
37
- // Generate grant changes
38
- for (const [grantee, result] of privilegeResults) {
39
- if (result.grants.length > 0) {
40
- const grantGroups = groupPrivilegesByGrantable(result.grants);
41
- for (const [grantable, list] of grantGroups) {
42
- void grantable;
43
- changes.push(new GrantForeignTablePrivileges({
44
- foreignTable: createdTable,
45
- grantee,
46
- privileges: list,
47
- version: ctx.version,
48
- }));
49
- }
50
- }
51
- // Generate revoke changes
52
- if (result.revokes.length > 0) {
53
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
54
- for (const [grantable, list] of revokeGroups) {
55
- void grantable;
56
- changes.push(new RevokeForeignTablePrivileges({
57
- foreignTable: createdTable,
58
- grantee,
59
- privileges: list,
60
- version: ctx.version,
61
- }));
62
- }
63
- }
64
- // Generate revoke grant option changes
65
- if (result.revokeGrantOption.length > 0) {
66
- changes.push(new RevokeGrantOptionForeignTablePrivileges({
67
- foreignTable: createdTable,
68
- grantee,
69
- privilegeNames: result.revokeGrantOption,
70
- version: ctx.version,
71
- }));
72
- }
73
- }
39
+ const privilegeResults = diffPrivileges(filterPublicBuiltInDefaults("foreign_table", creatorFilteredDefaults), desiredPrivileges, createdTable.owner);
40
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, createdTable, createdTable, "foreignTable", {
41
+ Grant: GrantForeignTablePrivileges,
42
+ Revoke: RevokeForeignTablePrivileges,
43
+ RevokeGrantOption: RevokeGrantOptionForeignTablePrivileges,
44
+ }, ctx.version));
74
45
  }
75
46
  for (const tableId of dropped) {
76
47
  changes.push(new DropForeignTable({ foreignTable: main[tableId] }));
@@ -180,44 +151,12 @@ export function diffForeignTables(ctx, main, branch) {
180
151
  // PRIVILEGES
181
152
  const mainPrivilegesFiltered = filterPublicBuiltInDefaults("foreign_table", mainTable.privileges);
182
153
  const branchPrivilegesFiltered = filterPublicBuiltInDefaults("foreign_table", branchTable.privileges);
183
- const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchTable.owner, ctx.mainRoles);
184
- for (const [grantee, result] of privilegeResults) {
185
- // Generate grant changes
186
- if (result.grants.length > 0) {
187
- const grantGroups = groupPrivilegesByGrantable(result.grants);
188
- for (const [grantable, list] of grantGroups) {
189
- void grantable;
190
- changes.push(new GrantForeignTablePrivileges({
191
- foreignTable: branchTable,
192
- grantee,
193
- privileges: list,
194
- version: ctx.version,
195
- }));
196
- }
197
- }
198
- // Generate revoke changes
199
- if (result.revokes.length > 0) {
200
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
201
- for (const [grantable, list] of revokeGroups) {
202
- void grantable;
203
- changes.push(new RevokeForeignTablePrivileges({
204
- foreignTable: mainTable,
205
- grantee,
206
- privileges: list,
207
- version: ctx.version,
208
- }));
209
- }
210
- }
211
- // Generate revoke grant option changes
212
- if (result.revokeGrantOption.length > 0) {
213
- changes.push(new RevokeGrantOptionForeignTablePrivileges({
214
- foreignTable: mainTable,
215
- grantee,
216
- privilegeNames: result.revokeGrantOption,
217
- version: ctx.version,
218
- }));
219
- }
220
- }
154
+ const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchTable.owner);
155
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchTable, mainTable, "foreignTable", {
156
+ Grant: GrantForeignTablePrivileges,
157
+ Revoke: RevokeForeignTablePrivileges,
158
+ RevokeGrantOption: RevokeGrantOptionForeignTablePrivileges,
159
+ }, ctx.version));
221
160
  // Note: Foreign table renaming would also use ALTER FOREIGN TABLE ... RENAME TO ...
222
161
  // But since our ForeignTable model uses 'name' as the identity field,
223
162
  // a name change would be handled as drop + create by diffObjects()
@@ -168,7 +168,7 @@ export async function extractForeignTables(pool) {
168
168
  from (
169
169
  -- one row for object ACL + one row per column ACL
170
170
  select null::name as attname, ft.oid as relacl_oid, (
171
- select c_rel.relacl from pg_class c_rel where c_rel.oid = ft.oid
171
+ select COALESCE(c_rel.relacl, acldefault('r', c_rel.relowner)) from pg_class c_rel where c_rel.oid = ft.oid
172
172
  ) as acl
173
173
  union all
174
174
  select a2.attname, ft.oid as relacl_oid, a2.attacl
@@ -1,5 +1,4 @@
1
- import type { DefaultPrivilegeState } from "../../base.default-privileges.ts";
2
- import type { Role } from "../../role/role.model.ts";
1
+ import type { ObjectDiffContext } from "../../diff-context.ts";
3
2
  import type { ServerChange } from "./changes/server.types.ts";
4
3
  import type { Server } from "./server.model.ts";
5
4
  /**
@@ -10,9 +9,4 @@ import type { Server } from "./server.model.ts";
10
9
  * @param branch - The servers in the branch catalog.
11
10
  * @returns A list of changes to apply to main to make it match branch.
12
11
  */
13
- export declare function diffServers(ctx: {
14
- version: number;
15
- currentUser: string;
16
- defaultPrivilegeState: DefaultPrivilegeState;
17
- mainRoles: Record<string, Role>;
18
- }, main: Record<string, Server>, branch: Record<string, Server>): ServerChange[];
12
+ export declare function diffServers(ctx: Pick<ObjectDiffContext, "version" | "currentUser">, main: Record<string, Server>, branch: Record<string, Server>): ServerChange[];
@@ -1,5 +1,5 @@
1
1
  import { diffObjects } from "../../base.diff.js";
2
- import { diffPrivileges, filterPublicBuiltInDefaults, groupPrivilegesByGrantable, } from "../../base.privilege-diff.js";
2
+ import { diffPrivileges, emitObjectPrivilegeChanges, filterPublicBuiltInDefaults, } from "../../base.privilege-diff.js";
3
3
  import { AlterServerChangeOwner, AlterServerSetOptions, AlterServerSetVersion, } from "./changes/server.alter.js";
4
4
  import { CreateCommentOnServer, DropCommentOnServer, } from "./changes/server.comment.js";
5
5
  import { CreateServer } from "./changes/server.create.js";
@@ -33,44 +33,12 @@ export function diffServers(ctx, main, branch) {
33
33
  // PRIVILEGES: Servers don't have default privileges
34
34
  const effectiveDefaults = [];
35
35
  const desiredPrivileges = filterPublicBuiltInDefaults("server", createdServer.privileges);
36
- const privilegeResults = diffPrivileges(effectiveDefaults, desiredPrivileges, createdServer.owner, ctx.mainRoles);
37
- // Generate grant changes
38
- for (const [grantee, result] of privilegeResults) {
39
- if (result.grants.length > 0) {
40
- const grantGroups = groupPrivilegesByGrantable(result.grants);
41
- for (const [grantable, list] of grantGroups) {
42
- void grantable;
43
- changes.push(new GrantServerPrivileges({
44
- server: createdServer,
45
- grantee,
46
- privileges: list,
47
- version: ctx.version,
48
- }));
49
- }
50
- }
51
- // Generate revoke changes
52
- if (result.revokes.length > 0) {
53
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
54
- for (const [grantable, list] of revokeGroups) {
55
- void grantable;
56
- changes.push(new RevokeServerPrivileges({
57
- server: createdServer,
58
- grantee,
59
- privileges: list,
60
- version: ctx.version,
61
- }));
62
- }
63
- }
64
- // Generate revoke grant option changes
65
- if (result.revokeGrantOption.length > 0) {
66
- changes.push(new RevokeGrantOptionServerPrivileges({
67
- server: createdServer,
68
- grantee,
69
- privilegeNames: result.revokeGrantOption,
70
- version: ctx.version,
71
- }));
72
- }
73
- }
36
+ const privilegeResults = diffPrivileges(effectiveDefaults, desiredPrivileges, createdServer.owner);
37
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, createdServer, createdServer, "server", {
38
+ Grant: GrantServerPrivileges,
39
+ Revoke: RevokeServerPrivileges,
40
+ RevokeGrantOption: RevokeGrantOptionServerPrivileges,
41
+ }, ctx.version));
74
42
  }
75
43
  for (const serverId of dropped) {
76
44
  changes.push(new DropServer({ server: main[serverId] }));
@@ -121,44 +89,12 @@ export function diffServers(ctx, main, branch) {
121
89
  // PRIVILEGES
122
90
  const mainPrivilegesFiltered = filterPublicBuiltInDefaults("server", mainServer.privileges);
123
91
  const branchPrivilegesFiltered = filterPublicBuiltInDefaults("server", branchServer.privileges);
124
- const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchServer.owner, ctx.mainRoles);
125
- for (const [grantee, result] of privilegeResults) {
126
- // Generate grant changes
127
- if (result.grants.length > 0) {
128
- const grantGroups = groupPrivilegesByGrantable(result.grants);
129
- for (const [grantable, list] of grantGroups) {
130
- void grantable;
131
- changes.push(new GrantServerPrivileges({
132
- server: branchServer,
133
- grantee,
134
- privileges: list,
135
- version: ctx.version,
136
- }));
137
- }
138
- }
139
- // Generate revoke changes
140
- if (result.revokes.length > 0) {
141
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
142
- for (const [grantable, list] of revokeGroups) {
143
- void grantable;
144
- changes.push(new RevokeServerPrivileges({
145
- server: mainServer,
146
- grantee,
147
- privileges: list,
148
- version: ctx.version,
149
- }));
150
- }
151
- }
152
- // Generate revoke grant option changes
153
- if (result.revokeGrantOption.length > 0) {
154
- changes.push(new RevokeGrantOptionServerPrivileges({
155
- server: mainServer,
156
- grantee,
157
- privilegeNames: result.revokeGrantOption,
158
- version: ctx.version,
159
- }));
160
- }
161
- }
92
+ const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchServer.owner);
93
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchServer, mainServer, "server", {
94
+ Grant: GrantServerPrivileges,
95
+ Revoke: RevokeServerPrivileges,
96
+ RevokeGrantOption: RevokeGrantOptionServerPrivileges,
97
+ }, ctx.version));
162
98
  // Note: Server renaming would also use ALTER SERVER ... RENAME TO ...
163
99
  // But since our Server model uses 'name' as the identity field,
164
100
  // a name change would be handled as drop + create by diffObjects()
@@ -1,5 +1,5 @@
1
1
  import type { Change } from "../../change.types.ts";
2
- import type { Role } from "../role/role.model.ts";
2
+ import type { ObjectDiffContext } from "../diff-context.ts";
3
3
  import type { Language } from "./language.model.ts";
4
4
  /**
5
5
  * Diff two sets of languages from main and branch catalogs.
@@ -9,7 +9,4 @@ import type { Language } from "./language.model.ts";
9
9
  * @param branch - The languages in the branch catalog.
10
10
  * @returns A list of changes to apply to main to make it match branch.
11
11
  */
12
- export declare function diffLanguages(ctx: {
13
- version: number;
14
- mainRoles?: Record<string, Role>;
15
- }, main: Record<string, Language>, branch: Record<string, Language>): Change[];
12
+ export declare function diffLanguages(ctx: Pick<ObjectDiffContext, "version">, main: Record<string, Language>, branch: Record<string, Language>): Change[];
@@ -1,5 +1,5 @@
1
1
  import { diffObjects } from "../base.diff.js";
2
- import { diffPrivileges, filterPublicBuiltInDefaults, groupPrivilegesByGrantable, } from "../base.privilege-diff.js";
2
+ import { diffPrivileges, emitObjectPrivilegeChanges, filterPublicBuiltInDefaults, } from "../base.privilege-diff.js";
3
3
  import { hasNonAlterableChanges } from "../utils.js";
4
4
  import { AlterLanguageChangeOwner } from "./changes/language.alter.js";
5
5
  import { CreateCommentOnLanguage, DropCommentOnLanguage, } from "./changes/language.comment.js";
@@ -73,44 +73,12 @@ export function diffLanguages(ctx, main, branch) {
73
73
  const branchPrivilegesFiltered = filterPublicBuiltInDefaults("language", branchLanguage.privileges);
74
74
  // Filter out owner privileges - owner always has ALL privileges implicitly
75
75
  // and shouldn't be compared. Use branch owner as the reference.
76
- const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchLanguage.owner, ctx.mainRoles);
77
- for (const [grantee, result] of privilegeResults) {
78
- // Generate grant changes
79
- if (result.grants.length > 0) {
80
- const grantGroups = groupPrivilegesByGrantable(result.grants);
81
- for (const [grantable, list] of grantGroups) {
82
- void grantable;
83
- changes.push(new GrantLanguagePrivileges({
84
- language: branchLanguage,
85
- grantee,
86
- privileges: list,
87
- version: ctx.version,
88
- }));
89
- }
90
- }
91
- // Generate revoke changes
92
- if (result.revokes.length > 0) {
93
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
94
- for (const [grantable, list] of revokeGroups) {
95
- void grantable;
96
- changes.push(new RevokeLanguagePrivileges({
97
- language: mainLanguage,
98
- grantee,
99
- privileges: list,
100
- version: ctx.version,
101
- }));
102
- }
103
- }
104
- // Generate revoke grant option changes
105
- if (result.revokeGrantOption.length > 0) {
106
- changes.push(new RevokeGrantOptionLanguagePrivileges({
107
- language: mainLanguage,
108
- grantee,
109
- privilegeNames: result.revokeGrantOption,
110
- version: ctx.version,
111
- }));
112
- }
113
- }
76
+ const privilegeResults = diffPrivileges(mainPrivilegesFiltered, branchPrivilegesFiltered, branchLanguage.owner);
77
+ changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchLanguage, mainLanguage, "language", {
78
+ Grant: GrantLanguagePrivileges,
79
+ Revoke: RevokeLanguagePrivileges,
80
+ RevokeGrantOption: RevokeGrantOptionLanguagePrivileges,
81
+ }, ctx.version));
114
82
  }
115
83
  }
116
84
  return changes;