@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
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Schema } from "../schema.model.ts";
3
4
  import { CreateSchema } from "./schema.create.ts";
4
5
 
5
6
  describe("schema", () => {
6
- test("create", () => {
7
+ test("create", async () => {
7
8
  const schema = new Schema({
8
9
  name: "test_schema",
9
10
  owner: "test",
@@ -15,6 +16,8 @@ describe("schema", () => {
15
16
  schema,
16
17
  });
17
18
 
19
+ await assertValidSql(change.serialize());
20
+
18
21
  expect(change.serialize()).toBe(
19
22
  "CREATE SCHEMA test_schema AUTHORIZATION test",
20
23
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Schema } from "../schema.model.ts";
3
4
  import { DropSchema } from "./schema.drop.ts";
4
5
 
5
6
  describe("schema", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const schema = new Schema({
8
9
  name: "test_schema",
9
10
  owner: "test",
@@ -15,6 +16,8 @@ describe("schema", () => {
15
16
  schema,
16
17
  });
17
18
 
19
+ await assertValidSql(change.serialize());
20
+
18
21
  expect(change.serialize()).toBe("DROP SCHEMA test_schema");
19
22
  });
20
23
  });
@@ -1,10 +1,9 @@
1
- import type { DefaultPrivilegeState } from "../base.default-privileges.ts";
2
1
  import { diffObjects } from "../base.diff.ts";
3
2
  import {
4
3
  diffPrivileges,
5
- groupPrivilegesByGrantable,
4
+ emitObjectPrivilegeChanges,
6
5
  } from "../base.privilege-diff.ts";
7
- import type { Role } from "../role/role.model.ts";
6
+ import type { ObjectDiffContext } from "../diff-context.ts";
8
7
  import { AlterSchemaChangeOwner } from "./changes/schema.alter.ts";
9
8
  import {
10
9
  CreateCommentOnSchema,
@@ -29,12 +28,10 @@ import type { Schema } from "./schema.model.ts";
29
28
  * @returns A list of changes to apply to main to make it match branch.
30
29
  */
31
30
  export function diffSchemas(
32
- ctx: {
33
- version: number;
34
- currentUser: string;
35
- defaultPrivilegeState: DefaultPrivilegeState;
36
- mainRoles: Record<string, Role>;
37
- },
31
+ ctx: Pick<
32
+ ObjectDiffContext,
33
+ "version" | "currentUser" | "defaultPrivilegeState"
34
+ >,
38
35
  main: Record<string, Schema>,
39
36
  branch: Record<string, Schema>,
40
37
  ): SchemaChange[] {
@@ -60,61 +57,33 @@ export function diffSchemas(
60
57
  "schema",
61
58
  "",
62
59
  );
60
+ const creatorFilteredDefaults =
61
+ sc.owner !== ctx.currentUser
62
+ ? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
63
+ : effectiveDefaults;
63
64
  const desiredPrivileges = sc.privileges;
64
65
  // Filter out owner privileges - owner always has ALL privileges implicitly
65
66
  // and shouldn't be compared. Use the schema owner as the reference.
66
67
  const privilegeResults = diffPrivileges(
67
- effectiveDefaults,
68
+ creatorFilteredDefaults,
68
69
  desiredPrivileges,
69
70
  sc.owner,
70
- ctx.mainRoles,
71
71
  );
72
72
 
73
- // Generate grant changes
74
- for (const [grantee, result] of privilegeResults) {
75
- if (result.grants.length > 0) {
76
- const grantGroups = groupPrivilegesByGrantable(result.grants);
77
- for (const [grantable, list] of grantGroups) {
78
- void grantable;
79
- changes.push(
80
- new GrantSchemaPrivileges({
81
- schema: sc,
82
- grantee,
83
- privileges: list,
84
- version: ctx.version,
85
- }),
86
- );
87
- }
88
- }
89
-
90
- // Generate revoke changes
91
- if (result.revokes.length > 0) {
92
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
93
- for (const [grantable, list] of revokeGroups) {
94
- void grantable;
95
- changes.push(
96
- new RevokeSchemaPrivileges({
97
- schema: sc,
98
- grantee,
99
- privileges: list,
100
- version: ctx.version,
101
- }),
102
- );
103
- }
104
- }
105
-
106
- // Generate revoke grant option changes
107
- if (result.revokeGrantOption.length > 0) {
108
- changes.push(
109
- new RevokeGrantOptionSchemaPrivileges({
110
- schema: sc,
111
- grantee,
112
- privilegeNames: result.revokeGrantOption,
113
- version: ctx.version,
114
- }),
115
- );
116
- }
117
- }
73
+ changes.push(
74
+ ...(emitObjectPrivilegeChanges(
75
+ privilegeResults,
76
+ sc,
77
+ sc,
78
+ "schema",
79
+ {
80
+ Grant: GrantSchemaPrivileges,
81
+ Revoke: RevokeSchemaPrivileges,
82
+ RevokeGrantOption: RevokeGrantOptionSchemaPrivileges,
83
+ },
84
+ ctx.version,
85
+ ) as SchemaChange[]),
86
+ );
118
87
  }
119
88
 
120
89
  for (const schemaId of dropped) {
@@ -151,54 +120,22 @@ export function diffSchemas(
151
120
  mainSchema.privileges,
152
121
  branchSchema.privileges,
153
122
  branchSchema.owner,
154
- ctx.mainRoles,
155
123
  );
156
124
 
157
- for (const [grantee, result] of privilegeResults) {
158
- // Generate grant changes
159
- if (result.grants.length > 0) {
160
- const grantGroups = groupPrivilegesByGrantable(result.grants);
161
- for (const [grantable, list] of grantGroups) {
162
- void grantable;
163
- changes.push(
164
- new GrantSchemaPrivileges({
165
- schema: branchSchema,
166
- grantee,
167
- privileges: list,
168
- version: ctx.version,
169
- }),
170
- );
171
- }
172
- }
173
-
174
- // Generate revoke changes
175
- if (result.revokes.length > 0) {
176
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
177
- for (const [grantable, list] of revokeGroups) {
178
- void grantable;
179
- changes.push(
180
- new RevokeSchemaPrivileges({
181
- schema: mainSchema,
182
- grantee,
183
- privileges: list,
184
- version: ctx.version,
185
- }),
186
- );
187
- }
188
- }
189
-
190
- // Generate revoke grant option changes
191
- if (result.revokeGrantOption.length > 0) {
192
- changes.push(
193
- new RevokeGrantOptionSchemaPrivileges({
194
- schema: mainSchema,
195
- grantee,
196
- privilegeNames: result.revokeGrantOption,
197
- version: ctx.version,
198
- }),
199
- );
200
- }
201
- }
125
+ changes.push(
126
+ ...(emitObjectPrivilegeChanges(
127
+ privilegeResults,
128
+ branchSchema,
129
+ mainSchema,
130
+ "schema",
131
+ {
132
+ Grant: GrantSchemaPrivileges,
133
+ Revoke: RevokeSchemaPrivileges,
134
+ RevokeGrantOption: RevokeGrantOptionSchemaPrivileges,
135
+ },
136
+ ctx.version,
137
+ ) as SchemaChange[]),
138
+ );
202
139
 
203
140
  // Note: Schema renaming would also use ALTER SCHEMA ... RENAME TO ...
204
141
  // But since our Schema model uses 'schema' as the identity field,
@@ -86,7 +86,7 @@ export async function extractSchemas(pool: Pool): Promise<Schema[]> {
86
86
  )
87
87
  order by x.grantee, x.privilege_type
88
88
  )
89
- from lateral aclexplode(nspacl) as x(grantor, grantee, privilege_type, is_grantable)
89
+ from lateral aclexplode(COALESCE(nspacl, acldefault('n', nspowner))) as x(grantor, grantee, privilege_type, is_grantable)
90
90
  ), '[]'
91
91
  ) as privileges
92
92
  from
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Sequence, type SequenceProps } from "../sequence.model.ts";
3
4
  import {
4
5
  AlterSequenceSetOptions,
@@ -7,7 +8,7 @@ import {
7
8
 
8
9
  describe.concurrent("sequence", () => {
9
10
  describe("alter", () => {
10
- test("set owned by table column", () => {
11
+ test("set owned by table column", async () => {
11
12
  const props: Omit<
12
13
  SequenceProps,
13
14
  "owned_by_schema" | "owned_by_table" | "owned_by_column"
@@ -38,12 +39,14 @@ describe.concurrent("sequence", () => {
38
39
  ownedBy: { schema: "public", table: "t", column: "id" },
39
40
  });
40
41
 
42
+ await assertValidSql(change.serialize());
43
+
41
44
  expect(change.serialize()).toBe(
42
45
  "ALTER SEQUENCE public.test_sequence OWNED BY public.t.id",
43
46
  );
44
47
  });
45
48
 
46
- test("owned by none", () => {
49
+ test("owned by none", async () => {
47
50
  const sequence = new Sequence({
48
51
  schema: "public",
49
52
  name: "s",
@@ -63,14 +66,15 @@ describe.concurrent("sequence", () => {
63
66
  owner: "test",
64
67
  });
65
68
  const change = new AlterSequenceSetOwnedBy({ sequence, ownedBy: null });
69
+ await assertValidSql(change.serialize());
66
70
  expect(change.serialize()).toBe("ALTER SEQUENCE public.s OWNED BY NONE");
67
71
  });
68
72
 
69
- test("drop + create sequence (handled in diff)", () => {
73
+ test("drop + create sequence (handled in diff)", async () => {
70
74
  expect(1).toBe(1);
71
75
  });
72
76
 
73
- test("alter options: increment, min/max, start, cache, cycle", () => {
77
+ test("alter options: increment, min/max, start, cache, cycle", async () => {
74
78
  const sequence = new Sequence({
75
79
  schema: "public",
76
80
  name: "s",
@@ -105,12 +109,13 @@ describe.concurrent("sequence", () => {
105
109
  "CYCLE",
106
110
  ],
107
111
  });
112
+ await assertValidSql(change.serialize());
108
113
  expect(change.serialize()).toBe(
109
114
  "ALTER SEQUENCE public.s INCREMENT BY 2 MINVALUE 5 MAXVALUE 100 START WITH 10 CACHE 3 CYCLE",
110
115
  );
111
116
  });
112
117
 
113
- test("alter options: reset to defaults uses NO MINVALUE/NO MAXVALUE", () => {
118
+ test("alter options: reset to defaults uses NO MINVALUE/NO MAXVALUE", async () => {
114
119
  const sequence = new Sequence({
115
120
  schema: "public",
116
121
  name: "s",
@@ -143,6 +148,7 @@ describe.concurrent("sequence", () => {
143
148
  "NO CYCLE",
144
149
  ],
145
150
  });
151
+ await assertValidSql(change.serialize());
146
152
  expect(change.serialize()).toBe(
147
153
  "ALTER SEQUENCE public.s INCREMENT BY 1 NO MINVALUE NO MAXVALUE START WITH 1 CACHE 1 NO CYCLE",
148
154
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Sequence } from "../sequence.model.ts";
3
4
  import { CreateSequence } from "./sequence.create.ts";
4
5
 
5
6
  describe("sequence", () => {
6
- test("create minimal (all defaults elided)", () => {
7
+ test("create minimal (all defaults elided)", async () => {
7
8
  const sequence = new Sequence({
8
9
  schema: "public",
9
10
  name: "s_min",
@@ -24,10 +25,11 @@ describe("sequence", () => {
24
25
  });
25
26
 
26
27
  const change = new CreateSequence({ sequence });
28
+ await assertValidSql(change.serialize());
27
29
  expect(change.serialize()).toBe("CREATE SEQUENCE public.s_min");
28
30
  });
29
31
 
30
- test("create", () => {
32
+ test("create", async () => {
31
33
  const sequence = new Sequence({
32
34
  schema: "public",
33
35
  name: "test_sequence",
@@ -51,12 +53,14 @@ describe("sequence", () => {
51
53
  sequence,
52
54
  });
53
55
 
56
+ await assertValidSql(change.serialize());
57
+
54
58
  expect(change.serialize()).toBe(
55
59
  "CREATE SEQUENCE public.test_sequence AS integer",
56
60
  );
57
61
  });
58
62
 
59
- test("create with all options", () => {
63
+ test("create with all options", async () => {
60
64
  const sequence = new Sequence({
61
65
  schema: "public",
62
66
  name: "s_all",
@@ -77,6 +81,7 @@ describe("sequence", () => {
77
81
  });
78
82
 
79
83
  const change = new CreateSequence({ sequence });
84
+ await assertValidSql(change.serialize());
80
85
  expect(change.serialize()).toBe(
81
86
  "CREATE SEQUENCE public.s_all AS integer INCREMENT BY 2 MINVALUE 5 MAXVALUE 100 START WITH 10 CACHE 3 CYCLE",
82
87
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Sequence } from "../sequence.model.ts";
3
4
  import { DropSequence } from "./sequence.drop.ts";
4
5
 
5
6
  describe("sequence", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const sequence = new Sequence({
8
9
  schema: "public",
9
10
  name: "test_sequence",
@@ -27,6 +28,8 @@ describe("sequence", () => {
27
28
  sequence,
28
29
  });
29
30
 
31
+ await assertValidSql(change.serialize());
32
+
30
33
  expect(change.serialize()).toBe("DROP SEQUENCE public.test_sequence");
31
34
  });
32
35
  });
@@ -5,8 +5,17 @@ import {
5
5
  AlterSequenceSetOptions,
6
6
  AlterSequenceSetOwnedBy,
7
7
  } from "./changes/sequence.alter.ts";
8
+ import {
9
+ CreateCommentOnSequence,
10
+ DropCommentOnSequence,
11
+ } from "./changes/sequence.comment.ts";
8
12
  import { CreateSequence } from "./changes/sequence.create.ts";
9
13
  import { DropSequence } from "./changes/sequence.drop.ts";
14
+ import {
15
+ GrantSequencePrivileges,
16
+ RevokeGrantOptionSequencePrivileges,
17
+ RevokeSequencePrivileges,
18
+ } from "./changes/sequence.privilege.ts";
10
19
  import { diffSequences } from "./sequence.diff.ts";
11
20
  import { Sequence, type SequenceProps } from "./sequence.model.ts";
12
21
 
@@ -138,4 +147,109 @@ describe.concurrent("sequence.diff", () => {
138
147
  expect(changes).toHaveLength(1);
139
148
  expect(changes[0]).toBeInstanceOf(DropSequence);
140
149
  });
150
+
151
+ test("create with comment emits CreateCommentOnSequence", () => {
152
+ const s = new Sequence({ ...base, comment: "my seq" });
153
+ const changes = diffSequences(testContext, {}, { [s.stableId]: s });
154
+ expect(changes[0]).toBeInstanceOf(CreateSequence);
155
+ expect(changes.some((c) => c instanceof CreateCommentOnSequence)).toBe(
156
+ true,
157
+ );
158
+ });
159
+
160
+ test("create with owned-by emits AlterSequenceSetOwnedBy", () => {
161
+ const s = new Sequence({
162
+ ...base,
163
+ owned_by_schema: "public",
164
+ owned_by_table: "t",
165
+ owned_by_column: "id",
166
+ });
167
+ const changes = diffSequences(testContext, {}, { [s.stableId]: s });
168
+ expect(changes[0]).toBeInstanceOf(CreateSequence);
169
+ expect(changes.some((c) => c instanceof AlterSequenceSetOwnedBy)).toBe(
170
+ true,
171
+ );
172
+ });
173
+
174
+ test("create with privileges emits grant, revoke, and revoke grant option", () => {
175
+ const dpState = new DefaultPrivilegeState({});
176
+ dpState.applyGrant("postgres", "S", null, "role_revoke_me", [
177
+ { privilege: "USAGE", grantable: false },
178
+ ]);
179
+ dpState.applyGrant("postgres", "S", null, "role_downgrade", [
180
+ { privilege: "USAGE", grantable: true },
181
+ ]);
182
+ const ctx = { ...testContext, defaultPrivilegeState: dpState };
183
+ const s = new Sequence({
184
+ ...base,
185
+ privileges: [
186
+ { grantee: "role_grant_me", privilege: "USAGE", grantable: false },
187
+ { grantee: "role_downgrade", privilege: "USAGE", grantable: false },
188
+ ],
189
+ });
190
+ const changes = diffSequences(ctx, {}, { [s.stableId]: s });
191
+ expect(changes[0]).toBeInstanceOf(CreateSequence);
192
+ expect(changes.some((c) => c instanceof GrantSequencePrivileges)).toBe(
193
+ true,
194
+ );
195
+ expect(changes.some((c) => c instanceof RevokeSequencePrivileges)).toBe(
196
+ true,
197
+ );
198
+ expect(
199
+ changes.some((c) => c instanceof RevokeGrantOptionSequencePrivileges),
200
+ ).toBe(true);
201
+ });
202
+
203
+ test("alter comment emits create and drop comment", () => {
204
+ const main = new Sequence(base);
205
+ const withComment = new Sequence({ ...base, comment: "my seq" });
206
+
207
+ const addComment = diffSequences(
208
+ testContext,
209
+ { [main.stableId]: main },
210
+ { [withComment.stableId]: withComment },
211
+ );
212
+ expect(addComment[0]).toBeInstanceOf(CreateCommentOnSequence);
213
+
214
+ const dropComment = diffSequences(
215
+ testContext,
216
+ { [withComment.stableId]: withComment },
217
+ { [main.stableId]: main },
218
+ );
219
+ expect(dropComment[0]).toBeInstanceOf(DropCommentOnSequence);
220
+ });
221
+
222
+ test("alter privileges emits grant, revoke, and revoke grant option", () => {
223
+ const main = new Sequence({
224
+ ...base,
225
+ privileges: [
226
+ { grantee: "role_a", privilege: "USAGE", grantable: false },
227
+ { grantee: "role_b", privilege: "USAGE", grantable: true },
228
+ { grantee: "role_removed", privilege: "USAGE", grantable: false },
229
+ ],
230
+ });
231
+ const branch = new Sequence({
232
+ ...base,
233
+ privileges: [
234
+ { grantee: "role_a", privilege: "USAGE", grantable: true },
235
+ { grantee: "role_b", privilege: "USAGE", grantable: false },
236
+ { grantee: "role_new", privilege: "USAGE", grantable: false },
237
+ ],
238
+ });
239
+
240
+ const changes = diffSequences(
241
+ testContext,
242
+ { [main.stableId]: main },
243
+ { [branch.stableId]: branch },
244
+ );
245
+ expect(changes.some((c) => c instanceof GrantSequencePrivileges)).toBe(
246
+ true,
247
+ );
248
+ expect(changes.some((c) => c instanceof RevokeSequencePrivileges)).toBe(
249
+ true,
250
+ );
251
+ expect(
252
+ changes.some((c) => c instanceof RevokeGrantOptionSequencePrivileges),
253
+ ).toBe(true);
254
+ });
141
255
  });
@@ -1,10 +1,9 @@
1
- import type { DefaultPrivilegeState } from "../base.default-privileges.ts";
2
1
  import { diffObjects } from "../base.diff.ts";
3
2
  import {
4
3
  diffPrivileges,
5
- groupPrivilegesByGrantable,
4
+ emitObjectPrivilegeChanges,
6
5
  } from "../base.privilege-diff.ts";
7
- import type { Role } from "../role/role.model.ts";
6
+ import type { ObjectDiffContext } from "../diff-context.ts";
8
7
  import type { Table } from "../table/table.model.ts";
9
8
  import { hasNonAlterableChanges } from "../utils.ts";
10
9
  import {
@@ -35,12 +34,10 @@ import type { Sequence } from "./sequence.model.ts";
35
34
  * @returns A list of changes to apply to main to make it match branch.
36
35
  */
37
36
  export function diffSequences(
38
- ctx: {
39
- version: number;
40
- currentUser: string;
41
- defaultPrivilegeState: DefaultPrivilegeState;
42
- mainRoles: Record<string, Role>;
43
- },
37
+ ctx: Pick<
38
+ ObjectDiffContext,
39
+ "version" | "currentUser" | "defaultPrivilegeState"
40
+ >,
44
41
  main: Record<string, Sequence>,
45
42
  branch: Record<string, Sequence>,
46
43
  branchTables: Record<string, Table> = {},
@@ -83,62 +80,33 @@ export function diffSequences(
83
80
  "sequence",
84
81
  createdSeq.schema ?? "",
85
82
  );
83
+ const creatorFilteredDefaults =
84
+ createdSeq.owner !== ctx.currentUser
85
+ ? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
86
+ : effectiveDefaults;
86
87
  const desiredPrivileges = createdSeq.privileges;
87
88
  // Filter out owner privileges - owner always has ALL privileges implicitly
88
89
  // and shouldn't be compared. Use the sequence owner as the reference.
89
- // Superuser privileges are filtered inside diffPrivileges.
90
90
  const privilegeResults = diffPrivileges(
91
- effectiveDefaults,
91
+ creatorFilteredDefaults,
92
92
  desiredPrivileges,
93
93
  createdSeq.owner,
94
- ctx.mainRoles,
95
94
  );
96
95
 
97
- // Generate grant changes
98
- for (const [grantee, result] of privilegeResults) {
99
- if (result.grants.length > 0) {
100
- const grantGroups = groupPrivilegesByGrantable(result.grants);
101
- for (const [grantable, list] of grantGroups) {
102
- void grantable;
103
- changes.push(
104
- new GrantSequencePrivileges({
105
- sequence: createdSeq,
106
- grantee,
107
- privileges: list,
108
- version: ctx.version,
109
- }),
110
- );
111
- }
112
- }
113
-
114
- // Generate revoke changes
115
- if (result.revokes.length > 0) {
116
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
117
- for (const [grantable, list] of revokeGroups) {
118
- void grantable;
119
- changes.push(
120
- new RevokeSequencePrivileges({
121
- sequence: createdSeq,
122
- grantee,
123
- privileges: list,
124
- version: ctx.version,
125
- }),
126
- );
127
- }
128
- }
129
-
130
- // Generate revoke grant option changes
131
- if (result.revokeGrantOption.length > 0) {
132
- changes.push(
133
- new RevokeGrantOptionSequencePrivileges({
134
- sequence: createdSeq,
135
- grantee,
136
- privilegeNames: result.revokeGrantOption,
137
- version: ctx.version,
138
- }),
139
- );
140
- }
141
- }
96
+ changes.push(
97
+ ...(emitObjectPrivilegeChanges(
98
+ privilegeResults,
99
+ createdSeq,
100
+ createdSeq,
101
+ "sequence",
102
+ {
103
+ Grant: GrantSequencePrivileges,
104
+ Revoke: RevokeSequencePrivileges,
105
+ RevokeGrantOption: RevokeGrantOptionSequencePrivileges,
106
+ },
107
+ ctx.version,
108
+ ) as SequenceChange[]),
109
+ );
142
110
  }
143
111
 
144
112
  for (const sequenceId of dropped) {
@@ -295,59 +263,26 @@ export function diffSequences(
295
263
  // PRIVILEGES
296
264
  // Filter out owner privileges - owner always has ALL privileges implicitly
297
265
  // and shouldn't be compared. Use branch owner as the reference.
298
- // Superuser privileges are filtered inside diffPrivileges.
299
266
  const privilegeResults = diffPrivileges(
300
267
  mainSequence.privileges,
301
268
  branchSequence.privileges,
302
269
  branchSequence.owner,
303
- ctx.mainRoles,
304
270
  );
305
271
 
306
- for (const [grantee, result] of privilegeResults) {
307
- // Generate grant changes
308
- if (result.grants.length > 0) {
309
- const grantGroups = groupPrivilegesByGrantable(result.grants);
310
- for (const [grantable, list] of grantGroups) {
311
- void grantable;
312
- changes.push(
313
- new GrantSequencePrivileges({
314
- sequence: branchSequence,
315
- grantee,
316
- privileges: list,
317
- version: ctx.version,
318
- }),
319
- );
320
- }
321
- }
322
-
323
- // Generate revoke changes
324
- if (result.revokes.length > 0) {
325
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
326
- for (const [grantable, list] of revokeGroups) {
327
- void grantable;
328
- changes.push(
329
- new RevokeSequencePrivileges({
330
- sequence: mainSequence,
331
- grantee,
332
- privileges: list,
333
- version: ctx.version,
334
- }),
335
- );
336
- }
337
- }
338
-
339
- // Generate revoke grant option changes
340
- if (result.revokeGrantOption.length > 0) {
341
- changes.push(
342
- new RevokeGrantOptionSequencePrivileges({
343
- sequence: mainSequence,
344
- grantee,
345
- privilegeNames: result.revokeGrantOption,
346
- version: ctx.version,
347
- }),
348
- );
349
- }
350
- }
272
+ changes.push(
273
+ ...(emitObjectPrivilegeChanges(
274
+ privilegeResults,
275
+ branchSequence,
276
+ mainSequence,
277
+ "sequence",
278
+ {
279
+ Grant: GrantSequencePrivileges,
280
+ Revoke: RevokeSequencePrivileges,
281
+ RevokeGrantOption: RevokeGrantOptionSequencePrivileges,
282
+ },
283
+ ctx.version,
284
+ ) as SequenceChange[]),
285
+ );
351
286
 
352
287
  // Note: Sequence renaming would also use ALTER SEQUENCE ... RENAME TO ...
353
288
  // But since our Sequence model uses 'name' as the identity field,