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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/README.md +22 -0
  2. package/dist/cli/bin/cli.js +0 -0
  3. package/dist/cli/commands/plan.js +21 -0
  4. package/dist/cli/utils.d.ts +2 -0
  5. package/dist/cli/utils.js +1 -1
  6. package/dist/core/objects/table/table.model.d.ts +4 -2
  7. package/dist/core/objects/table/table.model.js +3 -0
  8. package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
  9. package/dist/core/objects/trigger/changes/trigger.create.js +2 -1
  10. package/dist/core/objects/trigger/trigger.model.d.ts +1 -0
  11. package/dist/core/objects/trigger/trigger.model.js +3 -0
  12. package/dist/core/plan/apply.js +3 -3
  13. package/dist/core/plan/create.js +34 -15
  14. package/dist/core/plan/sql-format/constants.d.ts +2 -0
  15. package/dist/core/plan/sql-format/constants.js +11 -0
  16. package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
  17. package/dist/core/plan/sql-format/fixtures.js +2449 -0
  18. package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
  19. package/dist/core/plan/sql-format/format-utils.js +274 -0
  20. package/dist/core/plan/sql-format/formatters.d.ts +20 -0
  21. package/dist/core/plan/sql-format/formatters.js +737 -0
  22. package/dist/core/plan/sql-format/index.d.ts +2 -0
  23. package/dist/core/plan/sql-format/index.js +98 -0
  24. package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
  25. package/dist/core/plan/sql-format/keyword-case.js +868 -0
  26. package/dist/core/plan/sql-format/protect.d.ts +3 -0
  27. package/dist/core/plan/sql-format/protect.js +269 -0
  28. package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
  29. package/dist/core/plan/sql-format/sql-scanner.js +202 -0
  30. package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
  31. package/dist/core/plan/sql-format/tokenizer.js +118 -0
  32. package/dist/core/plan/sql-format/types.d.ts +28 -0
  33. package/dist/core/plan/sql-format/types.js +1 -0
  34. package/dist/core/plan/sql-format/wrap.d.ts +2 -0
  35. package/dist/core/plan/sql-format/wrap.js +165 -0
  36. package/dist/core/plan/sql-format.d.ts +2 -0
  37. package/dist/core/plan/sql-format.js +1 -0
  38. package/dist/core/plan/statements.d.ts +2 -1
  39. package/dist/core/plan/statements.js +6 -2
  40. package/dist/core/postgres-config.d.ts +15 -0
  41. package/dist/core/postgres-config.js +30 -0
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.js +1 -0
  44. package/package.json +37 -22
  45. package/src/cli/app.ts +28 -0
  46. package/src/cli/bin/cli.ts +9 -0
  47. package/src/cli/commands/apply.ts +101 -0
  48. package/src/cli/commands/plan.ts +195 -0
  49. package/src/cli/commands/sync.ts +185 -0
  50. package/src/cli/formatters/index.ts +5 -0
  51. package/src/cli/formatters/tree/tree-builder.ts +380 -0
  52. package/src/cli/formatters/tree/tree-renderer.ts +372 -0
  53. package/src/cli/formatters/tree/tree.ts +237 -0
  54. package/src/cli/utils/integrations.ts +42 -0
  55. package/src/cli/utils.ts +231 -0
  56. package/src/core/catalog.diff.ts +246 -0
  57. package/src/core/catalog.model.ts +384 -0
  58. package/src/core/change.types.ts +44 -0
  59. package/src/core/context.ts +26 -0
  60. package/src/core/depend.ts +1870 -0
  61. package/src/core/expand-replace-dependencies.ts +380 -0
  62. package/src/core/fingerprint.ts +204 -0
  63. package/src/core/integrations/filter/dsl.ts +204 -0
  64. package/src/core/integrations/filter/extractors.ts +145 -0
  65. package/src/core/integrations/filter/filter.types.ts +3 -0
  66. package/src/core/integrations/integration-dsl.ts +24 -0
  67. package/src/core/integrations/integration.types.ts +7 -0
  68. package/src/core/integrations/serialize/dsl.ts +77 -0
  69. package/src/core/integrations/serialize/serialize.types.ts +3 -0
  70. package/src/core/integrations/supabase.ts +121 -0
  71. package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
  72. package/src/core/objects/aggregate/aggregate.diff.ts +278 -0
  73. package/src/core/objects/aggregate/aggregate.model.ts +317 -0
  74. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +64 -0
  75. package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
  76. package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
  77. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +86 -0
  78. package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
  79. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +101 -0
  80. package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
  81. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +78 -0
  82. package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
  83. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +130 -0
  84. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
  85. package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
  86. package/src/core/objects/base.change.ts +62 -0
  87. package/src/core/objects/base.default-privileges.ts +204 -0
  88. package/src/core/objects/base.diff.ts +20 -0
  89. package/src/core/objects/base.model.ts +82 -0
  90. package/src/core/objects/base.privilege-diff.ts +299 -0
  91. package/src/core/objects/base.privilege.ts +184 -0
  92. package/src/core/objects/collation/changes/collation.alter.test.ts +63 -0
  93. package/src/core/objects/collation/changes/collation.alter.ts +79 -0
  94. package/src/core/objects/collation/changes/collation.base.ts +20 -0
  95. package/src/core/objects/collation/changes/collation.comment.ts +68 -0
  96. package/src/core/objects/collation/changes/collation.create.test.ts +51 -0
  97. package/src/core/objects/collation/changes/collation.create.ts +106 -0
  98. package/src/core/objects/collation/changes/collation.drop.test.ts +28 -0
  99. package/src/core/objects/collation/changes/collation.drop.ts +37 -0
  100. package/src/core/objects/collation/changes/collation.types.ts +10 -0
  101. package/src/core/objects/collation/collation.diff.test.ts +100 -0
  102. package/src/core/objects/collation/collation.diff.ts +126 -0
  103. package/src/core/objects/collation/collation.model.ts +224 -0
  104. package/src/core/objects/domain/changes/domain.alter.test.ts +316 -0
  105. package/src/core/objects/domain/changes/domain.alter.ts +286 -0
  106. package/src/core/objects/domain/changes/domain.base.ts +20 -0
  107. package/src/core/objects/domain/changes/domain.comment.ts +59 -0
  108. package/src/core/objects/domain/changes/domain.create.test.ts +65 -0
  109. package/src/core/objects/domain/changes/domain.create.ts +118 -0
  110. package/src/core/objects/domain/changes/domain.drop.test.ts +30 -0
  111. package/src/core/objects/domain/changes/domain.drop.ts +34 -0
  112. package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
  113. package/src/core/objects/domain/changes/domain.types.ts +12 -0
  114. package/src/core/objects/domain/domain.diff.test.ts +284 -0
  115. package/src/core/objects/domain/domain.diff.ts +358 -0
  116. package/src/core/objects/domain/domain.model.ts +190 -0
  117. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +50 -0
  118. package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
  119. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
  120. package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
  121. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +24 -0
  122. package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
  123. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +22 -0
  124. package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
  125. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
  126. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +126 -0
  127. package/src/core/objects/event-trigger/event-trigger.diff.ts +126 -0
  128. package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
  129. package/src/core/objects/extension/changes/extension.alter.test.ts +58 -0
  130. package/src/core/objects/extension/changes/extension.alter.ts +78 -0
  131. package/src/core/objects/extension/changes/extension.base.ts +20 -0
  132. package/src/core/objects/extension/changes/extension.comment.ts +64 -0
  133. package/src/core/objects/extension/changes/extension.create.test.ts +25 -0
  134. package/src/core/objects/extension/changes/extension.create.ts +63 -0
  135. package/src/core/objects/extension/changes/extension.drop.test.ts +23 -0
  136. package/src/core/objects/extension/changes/extension.drop.ts +34 -0
  137. package/src/core/objects/extension/changes/extension.types.ts +10 -0
  138. package/src/core/objects/extension/extension.diff.test.ts +42 -0
  139. package/src/core/objects/extension/extension.diff.ts +90 -0
  140. package/src/core/objects/extension/extension.model.ts +280 -0
  141. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +125 -0
  142. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
  143. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
  144. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
  145. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +125 -0
  146. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
  147. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +23 -0
  148. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
  149. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
  150. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
  151. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +179 -0
  152. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +341 -0
  153. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
  154. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
  155. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +309 -0
  156. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
  157. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
  158. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
  159. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +201 -0
  160. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
  161. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +43 -0
  162. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
  163. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
  164. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
  165. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
  166. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +406 -0
  167. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
  168. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +168 -0
  169. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
  170. package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
  171. package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
  172. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +131 -0
  173. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
  174. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +24 -0
  175. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
  176. package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
  177. package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
  178. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +167 -0
  179. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +317 -0
  180. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
  181. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +82 -0
  182. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
  183. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
  184. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +85 -0
  185. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
  186. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +53 -0
  187. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
  188. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
  189. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
  190. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
  191. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
  192. package/src/core/objects/index/changes/index.alter.test.ts +200 -0
  193. package/src/core/objects/index/changes/index.alter.ts +144 -0
  194. package/src/core/objects/index/changes/index.base.ts +20 -0
  195. package/src/core/objects/index/changes/index.comment.ts +63 -0
  196. package/src/core/objects/index/changes/index.create.test.ts +66 -0
  197. package/src/core/objects/index/changes/index.create.ts +68 -0
  198. package/src/core/objects/index/changes/index.drop.test.ts +44 -0
  199. package/src/core/objects/index/changes/index.drop.ts +34 -0
  200. package/src/core/objects/index/changes/index.types.ts +6 -0
  201. package/src/core/objects/index/changes/utils.ts +16 -0
  202. package/src/core/objects/index/index.diff.test.ts +153 -0
  203. package/src/core/objects/index/index.diff.ts +243 -0
  204. package/src/core/objects/index/index.model.ts +370 -0
  205. package/src/core/objects/language/changes/language.alter.test.ts +33 -0
  206. package/src/core/objects/language/changes/language.alter.ts +53 -0
  207. package/src/core/objects/language/changes/language.base.ts +20 -0
  208. package/src/core/objects/language/changes/language.comment.ts +58 -0
  209. package/src/core/objects/language/changes/language.create.test.ts +27 -0
  210. package/src/core/objects/language/changes/language.create.ts +104 -0
  211. package/src/core/objects/language/changes/language.drop.test.ts +25 -0
  212. package/src/core/objects/language/changes/language.drop.ts +39 -0
  213. package/src/core/objects/language/changes/language.privilege.ts +172 -0
  214. package/src/core/objects/language/changes/language.types.ts +12 -0
  215. package/src/core/objects/language/language.diff.test.ts +53 -0
  216. package/src/core/objects/language/language.diff.ts +176 -0
  217. package/src/core/objects/language/language.model.ts +150 -0
  218. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +123 -0
  219. package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
  220. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
  221. package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
  222. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +64 -0
  223. package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
  224. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +34 -0
  225. package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
  226. package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
  227. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
  228. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +102 -0
  229. package/src/core/objects/materialized-view/materialized-view.diff.ts +451 -0
  230. package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
  231. package/src/core/objects/procedure/changes/procedure.alter.test.ts +1005 -0
  232. package/src/core/objects/procedure/changes/procedure.alter.ts +287 -0
  233. package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
  234. package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
  235. package/src/core/objects/procedure/changes/procedure.create.test.ts +48 -0
  236. package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
  237. package/src/core/objects/procedure/changes/procedure.drop.test.ts +85 -0
  238. package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
  239. package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
  240. package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
  241. package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
  242. package/src/core/objects/procedure/procedure.diff.ts +404 -0
  243. package/src/core/objects/procedure/procedure.model.ts +264 -0
  244. package/src/core/objects/procedure/utils.ts +58 -0
  245. package/src/core/objects/publication/changes/publication.alter.test.ts +223 -0
  246. package/src/core/objects/publication/changes/publication.alter.ts +243 -0
  247. package/src/core/objects/publication/changes/publication.base.ts +20 -0
  248. package/src/core/objects/publication/changes/publication.comment.test.ts +70 -0
  249. package/src/core/objects/publication/changes/publication.comment.ts +64 -0
  250. package/src/core/objects/publication/changes/publication.create.test.ts +87 -0
  251. package/src/core/objects/publication/changes/publication.create.ts +82 -0
  252. package/src/core/objects/publication/changes/publication.drop.test.ts +46 -0
  253. package/src/core/objects/publication/changes/publication.drop.ts +29 -0
  254. package/src/core/objects/publication/changes/publication.types.ts +26 -0
  255. package/src/core/objects/publication/publication.diff.test.ts +292 -0
  256. package/src/core/objects/publication/publication.diff.ts +253 -0
  257. package/src/core/objects/publication/publication.model.ts +206 -0
  258. package/src/core/objects/publication/utils.ts +55 -0
  259. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +250 -0
  260. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
  261. package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
  262. package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
  263. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +74 -0
  264. package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
  265. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +28 -0
  266. package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
  267. package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
  268. package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
  269. package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
  270. package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
  271. package/src/core/objects/role/changes/role.alter.test.ts +346 -0
  272. package/src/core/objects/role/changes/role.alter.ts +110 -0
  273. package/src/core/objects/role/changes/role.base.ts +24 -0
  274. package/src/core/objects/role/changes/role.comment.ts +55 -0
  275. package/src/core/objects/role/changes/role.create.test.ts +52 -0
  276. package/src/core/objects/role/changes/role.create.ts +102 -0
  277. package/src/core/objects/role/changes/role.drop.test.ts +29 -0
  278. package/src/core/objects/role/changes/role.drop.ts +34 -0
  279. package/src/core/objects/role/changes/role.privilege.ts +376 -0
  280. package/src/core/objects/role/changes/role.types.ts +12 -0
  281. package/src/core/objects/role/role.diff.test.ts +44 -0
  282. package/src/core/objects/role/role.diff.ts +479 -0
  283. package/src/core/objects/role/role.model.ts +344 -0
  284. package/src/core/objects/rule/changes/rule.alter.test.ts +78 -0
  285. package/src/core/objects/rule/changes/rule.alter.ts +72 -0
  286. package/src/core/objects/rule/changes/rule.base.ts +20 -0
  287. package/src/core/objects/rule/changes/rule.comment.test.ts +55 -0
  288. package/src/core/objects/rule/changes/rule.comment.ts +62 -0
  289. package/src/core/objects/rule/changes/rule.create.test.ts +59 -0
  290. package/src/core/objects/rule/changes/rule.create.ts +42 -0
  291. package/src/core/objects/rule/changes/rule.drop.test.ts +38 -0
  292. package/src/core/objects/rule/changes/rule.drop.ts +29 -0
  293. package/src/core/objects/rule/changes/rule.types.ts +12 -0
  294. package/src/core/objects/rule/rule.diff.test.ts +132 -0
  295. package/src/core/objects/rule/rule.diff.ts +79 -0
  296. package/src/core/objects/rule/rule.model.ts +173 -0
  297. package/src/core/objects/schema/changes/schema.alter.test.ts +28 -0
  298. package/src/core/objects/schema/changes/schema.alter.ts +45 -0
  299. package/src/core/objects/schema/changes/schema.base.ts +20 -0
  300. package/src/core/objects/schema/changes/schema.comment.ts +56 -0
  301. package/src/core/objects/schema/changes/schema.create.test.ts +22 -0
  302. package/src/core/objects/schema/changes/schema.create.ts +47 -0
  303. package/src/core/objects/schema/changes/schema.drop.test.ts +20 -0
  304. package/src/core/objects/schema/changes/schema.drop.ts +34 -0
  305. package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
  306. package/src/core/objects/schema/changes/schema.types.ts +12 -0
  307. package/src/core/objects/schema/schema.diff.test.ts +42 -0
  308. package/src/core/objects/schema/schema.diff.ts +209 -0
  309. package/src/core/objects/schema/schema.model.ts +107 -0
  310. package/src/core/objects/sequence/changes/sequence.alter.test.ts +151 -0
  311. package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
  312. package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
  313. package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
  314. package/src/core/objects/sequence/changes/sequence.create.test.ts +84 -0
  315. package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
  316. package/src/core/objects/sequence/changes/sequence.drop.test.ts +32 -0
  317. package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
  318. package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
  319. package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
  320. package/src/core/objects/sequence/sequence.diff.test.ts +141 -0
  321. package/src/core/objects/sequence/sequence.diff.ts +359 -0
  322. package/src/core/objects/sequence/sequence.model.ts +185 -0
  323. package/src/core/objects/subscription/changes/subscription.alter.test.ts +124 -0
  324. package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
  325. package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
  326. package/src/core/objects/subscription/changes/subscription.comment.test.ts +67 -0
  327. package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
  328. package/src/core/objects/subscription/changes/subscription.create.test.ts +77 -0
  329. package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
  330. package/src/core/objects/subscription/changes/subscription.drop.test.ts +46 -0
  331. package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
  332. package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
  333. package/src/core/objects/subscription/subscription.diff.test.ts +232 -0
  334. package/src/core/objects/subscription/subscription.diff.ts +241 -0
  335. package/src/core/objects/subscription/subscription.model.ts +190 -0
  336. package/src/core/objects/subscription/utils.ts +156 -0
  337. package/src/core/objects/table/changes/table.alter.test.ts +823 -0
  338. package/src/core/objects/table/changes/table.alter.ts +806 -0
  339. package/src/core/objects/table/changes/table.base.ts +20 -0
  340. package/src/core/objects/table/changes/table.comment.ts +266 -0
  341. package/src/core/objects/table/changes/table.create.test.ts +150 -0
  342. package/src/core/objects/table/changes/table.create.ts +188 -0
  343. package/src/core/objects/table/changes/table.drop.test.ts +34 -0
  344. package/src/core/objects/table/changes/table.drop.ts +45 -0
  345. package/src/core/objects/table/changes/table.privilege.ts +200 -0
  346. package/src/core/objects/table/changes/table.types.ts +12 -0
  347. package/src/core/objects/table/table.diff.test.ts +711 -0
  348. package/src/core/objects/table/table.diff.ts +953 -0
  349. package/src/core/objects/table/table.model.ts +460 -0
  350. package/src/core/objects/trigger/changes/trigger.alter.test.ts +46 -0
  351. package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
  352. package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
  353. package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
  354. package/src/core/objects/trigger/changes/trigger.create.test.ts +43 -0
  355. package/src/core/objects/trigger/changes/trigger.create.ts +85 -0
  356. package/src/core/objects/trigger/changes/trigger.drop.test.ts +43 -0
  357. package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
  358. package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
  359. package/src/core/objects/trigger/trigger.diff.test.ts +83 -0
  360. package/src/core/objects/trigger/trigger.diff.ts +116 -0
  361. package/src/core/objects/trigger/trigger.model.ts +252 -0
  362. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +202 -0
  363. package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
  364. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
  365. package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
  366. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +101 -0
  367. package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
  368. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +33 -0
  369. package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
  370. package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
  371. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
  372. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +191 -0
  373. package/src/core/objects/type/composite-type/composite-type.diff.ts +372 -0
  374. package/src/core/objects/type/composite-type/composite-type.model.ts +252 -0
  375. package/src/core/objects/type/enum/changes/enum.alter.test.ts +104 -0
  376. package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
  377. package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
  378. package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
  379. package/src/core/objects/type/enum/changes/enum.create.test.ts +28 -0
  380. package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
  381. package/src/core/objects/type/enum/changes/enum.drop.test.ts +25 -0
  382. package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
  383. package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
  384. package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
  385. package/src/core/objects/type/enum/enum.diff.test.ts +191 -0
  386. package/src/core/objects/type/enum/enum.diff.ts +396 -0
  387. package/src/core/objects/type/enum/enum.model.ts +194 -0
  388. package/src/core/objects/type/range/changes/range.alter.test.ts +27 -0
  389. package/src/core/objects/type/range/changes/range.alter.ts +51 -0
  390. package/src/core/objects/type/range/changes/range.base.ts +20 -0
  391. package/src/core/objects/type/range/changes/range.comment.ts +64 -0
  392. package/src/core/objects/type/range/changes/range.create.test.ts +51 -0
  393. package/src/core/objects/type/range/changes/range.create.ts +151 -0
  394. package/src/core/objects/type/range/changes/range.drop.test.ts +26 -0
  395. package/src/core/objects/type/range/changes/range.drop.ts +34 -0
  396. package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
  397. package/src/core/objects/type/range/changes/range.types.ts +12 -0
  398. package/src/core/objects/type/range/range.diff.test.ts +70 -0
  399. package/src/core/objects/type/range/range.diff.ts +259 -0
  400. package/src/core/objects/type/range/range.model.ts +187 -0
  401. package/src/core/objects/type/type.types.ts +5 -0
  402. package/src/core/objects/utils.ts +171 -0
  403. package/src/core/objects/view/changes/view.alter.test.ts +110 -0
  404. package/src/core/objects/view/changes/view.alter.ts +112 -0
  405. package/src/core/objects/view/changes/view.base.ts +20 -0
  406. package/src/core/objects/view/changes/view.comment.ts +59 -0
  407. package/src/core/objects/view/changes/view.create.test.ts +65 -0
  408. package/src/core/objects/view/changes/view.create.ts +73 -0
  409. package/src/core/objects/view/changes/view.drop.test.ts +34 -0
  410. package/src/core/objects/view/changes/view.drop.ts +40 -0
  411. package/src/core/objects/view/changes/view.privilege.ts +200 -0
  412. package/src/core/objects/view/changes/view.types.ts +12 -0
  413. package/src/core/objects/view/view.diff.test.ts +91 -0
  414. package/src/core/objects/view/view.diff.ts +365 -0
  415. package/src/core/objects/view/view.model.ts +276 -0
  416. package/src/core/plan/apply.ts +190 -0
  417. package/src/core/plan/create.ts +432 -0
  418. package/src/core/plan/hierarchy.ts +574 -0
  419. package/src/core/plan/index.ts +29 -0
  420. package/src/core/plan/io.ts +20 -0
  421. package/src/core/plan/risk.ts +48 -0
  422. package/src/core/plan/serialize.ts +195 -0
  423. package/src/core/plan/sql-format/constants.ts +13 -0
  424. package/src/core/plan/sql-format/fixtures.ts +2806 -0
  425. package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
  426. package/src/core/plan/sql-format/format-functions.test.ts +127 -0
  427. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +67 -0
  428. package/src/core/plan/sql-format/format-off.test.ts +809 -0
  429. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1056 -0
  430. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1283 -0
  431. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1052 -0
  432. package/src/core/plan/sql-format/format-pretty-upper.test.ts +1045 -0
  433. package/src/core/plan/sql-format/format-stress.test.ts +616 -0
  434. package/src/core/plan/sql-format/format-utils.test.ts +91 -0
  435. package/src/core/plan/sql-format/format-utils.ts +391 -0
  436. package/src/core/plan/sql-format/formatters.ts +921 -0
  437. package/src/core/plan/sql-format/index.ts +149 -0
  438. package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
  439. package/src/core/plan/sql-format/keyword-case.ts +1085 -0
  440. package/src/core/plan/sql-format/protect.test.ts +127 -0
  441. package/src/core/plan/sql-format/protect.ts +337 -0
  442. package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
  443. package/src/core/plan/sql-format/sql-scanner.ts +252 -0
  444. package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
  445. package/src/core/plan/sql-format/tokenizer.ts +152 -0
  446. package/src/core/plan/sql-format/types.ts +31 -0
  447. package/src/core/plan/sql-format/wrap.test.ts +119 -0
  448. package/src/core/plan/sql-format/wrap.ts +196 -0
  449. package/src/core/plan/sql-format.ts +2 -0
  450. package/src/core/plan/statements.ts +22 -0
  451. package/src/core/plan/types.ts +165 -0
  452. package/src/core/postgres-config.ts +169 -0
  453. package/src/core/sort/custom-constraints.ts +161 -0
  454. package/src/core/sort/debug-visualization.ts +239 -0
  455. package/src/core/sort/dependency-filter.ts +224 -0
  456. package/src/core/sort/graph-builder.ts +223 -0
  457. package/src/core/sort/graph-utils.ts +51 -0
  458. package/src/core/sort/logical-sort.ts +590 -0
  459. package/src/core/sort/sort-changes.ts +234 -0
  460. package/src/core/sort/topological-sort.ts +184 -0
  461. package/src/core/sort/types.ts +112 -0
  462. package/src/core/sort/utils.ts +69 -0
  463. package/src/index.ts +14 -0
@@ -0,0 +1,146 @@
1
+ import {
2
+ formatObjectPrivilegeList,
3
+ getObjectKindPrefix,
4
+ } from "../../base.privilege.ts";
5
+ import { stableId } from "../../utils.ts";
6
+ import type { Aggregate } from "../aggregate.model.ts";
7
+ import { AlterAggregateChange } from "./aggregate.base.ts";
8
+
9
+ export type AggregatePrivilege =
10
+ | GrantAggregatePrivileges
11
+ | RevokeAggregatePrivileges
12
+ | RevokeGrantOptionAggregatePrivileges;
13
+
14
+ export class GrantAggregatePrivileges extends AlterAggregateChange {
15
+ public readonly aggregate: Aggregate;
16
+ public readonly grantee: string;
17
+ public readonly privileges: { privilege: string; grantable: boolean }[];
18
+ public readonly version: number | undefined;
19
+ public readonly scope = "privilege" as const;
20
+
21
+ constructor(props: {
22
+ aggregate: Aggregate;
23
+ grantee: string;
24
+ privileges: { privilege: string; grantable: boolean }[];
25
+ version?: number;
26
+ }) {
27
+ super();
28
+ this.aggregate = props.aggregate;
29
+ this.grantee = props.grantee;
30
+ this.privileges = props.privileges;
31
+ this.version = props.version;
32
+ }
33
+
34
+ get creates() {
35
+ return [stableId.acl(this.aggregate.stableId, this.grantee)];
36
+ }
37
+
38
+ get requires() {
39
+ return [this.aggregate.stableId, stableId.role(this.grantee)];
40
+ }
41
+
42
+ serialize(): string {
43
+ const hasGrantable = this.privileges.some((p) => p.grantable);
44
+ const hasBase = this.privileges.some((p) => !p.grantable);
45
+ if (hasGrantable && hasBase) {
46
+ throw new Error(
47
+ "GrantAggregatePrivileges expects privileges with uniform grantable flag",
48
+ );
49
+ }
50
+ const withGrant = hasGrantable ? " WITH GRANT OPTION" : "";
51
+ const kindPrefix = getObjectKindPrefix("FUNCTION");
52
+ const list = this.privileges.map((p) => p.privilege);
53
+ const privSql = formatObjectPrivilegeList("FUNCTION", list, this.version);
54
+ const aggregateName = `${this.aggregate.schema}.${this.aggregate.name}`;
55
+ const signature = this.aggregate.identityArguments;
56
+ const qualified = `${aggregateName}(${signature})`;
57
+ return `GRANT ${privSql} ${kindPrefix} ${qualified} TO ${this.grantee}${withGrant}`;
58
+ }
59
+ }
60
+
61
+ export class RevokeAggregatePrivileges extends AlterAggregateChange {
62
+ public readonly aggregate: Aggregate;
63
+ public readonly grantee: string;
64
+ public readonly privileges: { privilege: string; grantable: boolean }[];
65
+ public readonly version: number | undefined;
66
+ public readonly scope = "privilege" as const;
67
+
68
+ constructor(props: {
69
+ aggregate: Aggregate;
70
+ grantee: string;
71
+ privileges: { privilege: string; grantable: boolean }[];
72
+ version?: number;
73
+ }) {
74
+ super();
75
+ this.aggregate = props.aggregate;
76
+ this.grantee = props.grantee;
77
+ this.privileges = props.privileges;
78
+ this.version = props.version;
79
+ }
80
+
81
+ get drops() {
82
+ // Return ACL ID for dependency tracking, even though this is an ALTER operation
83
+ // Phase assignment now uses operation type, so this won't affect phase placement
84
+ return [stableId.acl(this.aggregate.stableId, this.grantee)];
85
+ }
86
+
87
+ get requires() {
88
+ return [
89
+ stableId.acl(this.aggregate.stableId, this.grantee),
90
+ this.aggregate.stableId,
91
+ stableId.role(this.grantee),
92
+ ];
93
+ }
94
+
95
+ serialize(): string {
96
+ const kindPrefix = getObjectKindPrefix("FUNCTION");
97
+ const list = this.privileges.map((p) => p.privilege);
98
+ const privSql = formatObjectPrivilegeList("FUNCTION", list, this.version);
99
+ const aggregateName = `${this.aggregate.schema}.${this.aggregate.name}`;
100
+ const signature = this.aggregate.identityArguments;
101
+ const qualified = `${aggregateName}(${signature})`;
102
+ return `REVOKE ${privSql} ${kindPrefix} ${qualified} FROM ${this.grantee}`;
103
+ }
104
+ }
105
+
106
+ export class RevokeGrantOptionAggregatePrivileges extends AlterAggregateChange {
107
+ public readonly aggregate: Aggregate;
108
+ public readonly grantee: string;
109
+ public readonly privilegeNames: string[];
110
+ public readonly version: number | undefined;
111
+ public readonly scope = "privilege" as const;
112
+
113
+ constructor(props: {
114
+ aggregate: Aggregate;
115
+ grantee: string;
116
+ privilegeNames: string[];
117
+ version?: number;
118
+ }) {
119
+ super();
120
+ this.aggregate = props.aggregate;
121
+ this.grantee = props.grantee;
122
+ this.privilegeNames = [...new Set(props.privilegeNames)].sort();
123
+ this.version = props.version;
124
+ }
125
+
126
+ get requires() {
127
+ return [
128
+ stableId.acl(this.aggregate.stableId, this.grantee),
129
+ this.aggregate.stableId,
130
+ stableId.role(this.grantee),
131
+ ];
132
+ }
133
+
134
+ serialize(): string {
135
+ const kindPrefix = getObjectKindPrefix("FUNCTION");
136
+ const privSql = formatObjectPrivilegeList(
137
+ "FUNCTION",
138
+ this.privilegeNames,
139
+ this.version,
140
+ );
141
+ const aggregateName = `${this.aggregate.schema}.${this.aggregate.name}`;
142
+ const signature = this.aggregate.identityArguments;
143
+ const qualified = `${aggregateName}(${signature})`;
144
+ return `REVOKE GRANT OPTION FOR ${privSql} ${kindPrefix} ${qualified} FROM ${this.grantee}`;
145
+ }
146
+ }
@@ -0,0 +1,12 @@
1
+ import type { AlterAggregate } from "./aggregate.alter.ts";
2
+ import type { CommentAggregate } from "./aggregate.comment.ts";
3
+ import type { CreateAggregate } from "./aggregate.create.ts";
4
+ import type { DropAggregate } from "./aggregate.drop.ts";
5
+ import type { AggregatePrivilege } from "./aggregate.privilege.ts";
6
+
7
+ export type AggregateChange =
8
+ | AlterAggregate
9
+ | CommentAggregate
10
+ | CreateAggregate
11
+ | DropAggregate
12
+ | AggregatePrivilege;
@@ -0,0 +1,62 @@
1
+ type ChangeOperation = "create" | "alter" | "drop";
2
+
3
+ export abstract class BaseChange {
4
+ /**
5
+ * The operation of the change.
6
+ */
7
+ abstract readonly operation: ChangeOperation;
8
+ /**
9
+ * The type of the object targeted by the change.
10
+ */
11
+ abstract readonly objectType: string;
12
+ /**
13
+ * The scope of the change.
14
+ */
15
+ abstract readonly scope: string;
16
+
17
+ /**
18
+ * A unique identifier for the change.
19
+ */
20
+ get changeId(): string {
21
+ return `${this.operation}:${this.scope}:${this.objectType}:${this.serialize()}`;
22
+ }
23
+
24
+ /**
25
+ * Stable identifiers this change creates.
26
+ *
27
+ * Defaults to an empty array. Override in subclasses that create objects.
28
+ */
29
+ get creates(): string[] {
30
+ return [];
31
+ }
32
+
33
+ /**
34
+ * Stable identifiers this change drops.
35
+ *
36
+ * Defaults to an empty array. Override in subclasses that remove objects.
37
+ */
38
+ get drops(): string[] {
39
+ return [];
40
+ }
41
+
42
+ /**
43
+ * Stable identifiers this change requires to exist beforehand.
44
+ *
45
+ * Defaults to an empty array. Override in subclasses that have prerequisites.
46
+ */
47
+ get requires(): string[] {
48
+ return [];
49
+ }
50
+
51
+ /**
52
+ * Serialize the change into a single SQL statement.
53
+ */
54
+ abstract serialize(options?: Record<string, unknown>): string;
55
+ }
56
+
57
+ /**
58
+ * Port of string literal quoting: doubles single quotes inside and wraps with single quotes
59
+ */
60
+ export function quoteLiteral(value: string): string {
61
+ return `'${value.replace(/'/g, "''")}'`;
62
+ }
@@ -0,0 +1,204 @@
1
+ import type { PrivilegeProps } from "./base.privilege-diff.ts";
2
+ import type { Role } from "./role/role.model.ts";
3
+
4
+ /**
5
+ * Maps object type names to PostgreSQL default privilege objtype codes.
6
+ * Used to look up default privileges for different object types.
7
+ */
8
+ function objectTypeToObjtype(objectType: string): string | null {
9
+ switch (objectType) {
10
+ case "table":
11
+ return "r"; // Relations (tables)
12
+ case "view":
13
+ return "r"; // Views are also relations
14
+ case "materialized_view":
15
+ return "r"; // Materialized views are also relations
16
+ case "sequence":
17
+ return "S"; // Sequences
18
+ case "procedure":
19
+ case "function":
20
+ case "aggregate":
21
+ return "f"; // Functions/routines
22
+ case "type":
23
+ case "domain":
24
+ case "enum":
25
+ case "range":
26
+ case "composite_type":
27
+ return "T"; // Types
28
+ case "schema":
29
+ return "n"; // Schemas
30
+ default:
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Tracks the effective state of default privileges as changes are processed.
37
+ * This allows us to compute what default privileges would be in effect at any point
38
+ * in the migration script, accounting for ALTER DEFAULT PRIVILEGES statements.
39
+ */
40
+ export class DefaultPrivilegeState {
41
+ private state: Map<
42
+ string,
43
+ Map<string, Map<string | null, Map<string, Set<string>>>>
44
+ > = new Map(); // role -> objtype -> schema -> grantee -> privileges
45
+
46
+ constructor(initialRoles: Record<string, Role>) {
47
+ // Initialize state from roles' default_privileges
48
+ for (const [_roleId, role] of Object.entries(initialRoles)) {
49
+ const roleName = role.name;
50
+ if (!this.state.has(roleName)) {
51
+ this.state.set(roleName, new Map());
52
+ }
53
+ // biome-ignore lint/style/noNonNullAssertion: roleName is guaranteed to be in the state
54
+ const roleState = this.state.get(roleName)!;
55
+
56
+ for (const defPriv of role.default_privileges) {
57
+ if (!roleState.has(defPriv.objtype)) {
58
+ roleState.set(defPriv.objtype, new Map());
59
+ }
60
+ // biome-ignore lint/style/noNonNullAssertion: objtype is guaranteed to be in the state
61
+ const objtypeState = roleState.get(defPriv.objtype)!;
62
+
63
+ const schemaKey = defPriv.in_schema ?? null;
64
+ if (!objtypeState.has(schemaKey)) {
65
+ objtypeState.set(schemaKey, new Map());
66
+ }
67
+ // biome-ignore lint/style/noNonNullAssertion: schemaKey is guaranteed to be in the state
68
+ const schemaState = objtypeState.get(schemaKey)!;
69
+
70
+ if (!schemaState.has(defPriv.grantee)) {
71
+ schemaState.set(defPriv.grantee, new Set());
72
+ }
73
+ // biome-ignore lint/style/noNonNullAssertion: grantee is guaranteed to be in the state
74
+ const privileges = schemaState.get(defPriv.grantee)!;
75
+
76
+ for (const priv of defPriv.privileges) {
77
+ const key = `${priv.privilege}:${priv.grantable}`;
78
+ privileges.add(key);
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Apply a GrantRoleDefaultPrivileges change to the state.
86
+ */
87
+ applyGrant(
88
+ roleName: string,
89
+ objtype: string,
90
+ inSchema: string | null,
91
+ grantee: string,
92
+ privileges: { privilege: string; grantable: boolean }[],
93
+ ): void {
94
+ if (!this.state.has(roleName)) {
95
+ this.state.set(roleName, new Map());
96
+ }
97
+ // biome-ignore lint/style/noNonNullAssertion: roleName is guaranteed to be in the state
98
+ const roleState = this.state.get(roleName)!;
99
+
100
+ if (!roleState.has(objtype)) {
101
+ roleState.set(objtype, new Map());
102
+ }
103
+ // biome-ignore lint/style/noNonNullAssertion: objtype is guaranteed to be in the state
104
+ const objtypeState = roleState.get(objtype)!;
105
+
106
+ const schemaKey = inSchema ?? null;
107
+ if (!objtypeState.has(schemaKey)) {
108
+ objtypeState.set(schemaKey, new Map());
109
+ }
110
+ // biome-ignore lint/style/noNonNullAssertion: schemaKey is guaranteed to be in the state
111
+ const schemaState = objtypeState.get(schemaKey)!;
112
+
113
+ if (!schemaState.has(grantee)) {
114
+ schemaState.set(grantee, new Set());
115
+ }
116
+ // biome-ignore lint/style/noNonNullAssertion: grantee is guaranteed to be in the state
117
+ const privilegesSet = schemaState.get(grantee)!;
118
+
119
+ for (const priv of privileges) {
120
+ const key = `${priv.privilege}:${priv.grantable}`;
121
+ privilegesSet.add(key);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Apply a RevokeRoleDefaultPrivileges change to the state.
127
+ */
128
+ applyRevoke(
129
+ roleName: string,
130
+ objtype: string,
131
+ inSchema: string | null,
132
+ grantee: string,
133
+ privileges: { privilege: string; grantable: boolean }[],
134
+ ): void {
135
+ const roleState = this.state.get(roleName);
136
+ if (!roleState) return;
137
+
138
+ const objtypeState = roleState.get(objtype);
139
+ if (!objtypeState) return;
140
+
141
+ const schemaKey = inSchema ?? null;
142
+ const schemaState = objtypeState.get(schemaKey);
143
+ if (!schemaState) return;
144
+
145
+ const privilegesSet = schemaState.get(grantee);
146
+ if (!privilegesSet) return;
147
+
148
+ for (const priv of privileges) {
149
+ const key = `${priv.privilege}:${priv.grantable}`;
150
+ privilegesSet.delete(key);
151
+ // Also remove base privilege if grantable was revoked
152
+ if (priv.grantable) {
153
+ const baseKey = `${priv.privilege}:false`;
154
+ privilegesSet.delete(baseKey);
155
+ }
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Get effective default privileges for a given object creation.
161
+ */
162
+ getEffectiveDefaults(
163
+ currentUser: string,
164
+ objectType: string,
165
+ objectSchema: string,
166
+ ): PrivilegeProps[] {
167
+ const objtype = objectTypeToObjtype(objectType);
168
+ if (!objtype) return [];
169
+
170
+ const roleState = this.state.get(currentUser);
171
+ if (!roleState) return [];
172
+
173
+ const objtypeState = roleState.get(objtype);
174
+ if (!objtypeState) return [];
175
+
176
+ const defaultPrivs: PrivilegeProps[] = [];
177
+
178
+ // Check schema-specific first, then global (null schema)
179
+ const schemasToCheck = [objectSchema, null];
180
+ for (const schemaKey of schemasToCheck) {
181
+ const schemaState = objtypeState.get(schemaKey);
182
+ if (!schemaState) continue;
183
+
184
+ for (const [grantee, privilegesSet] of schemaState.entries()) {
185
+ for (const privKey of privilegesSet) {
186
+ const [privilege, grantableStr] = privKey.split(":");
187
+ const grantable = grantableStr === "true";
188
+ defaultPrivs.push({
189
+ grantee,
190
+ privilege,
191
+ grantable,
192
+ columns: null,
193
+ });
194
+ }
195
+ }
196
+ // Schema-specific takes precedence, so break after first match
197
+ if (schemaKey === objectSchema && schemaState.size > 0) {
198
+ break;
199
+ }
200
+ }
201
+
202
+ return defaultPrivs;
203
+ }
204
+ }
@@ -0,0 +1,20 @@
1
+ import type { BasePgModel } from "./base.model.ts";
2
+
3
+ export function diffObjects<T extends BasePgModel>(
4
+ main: Record<string, T>,
5
+ branch: Record<string, T>,
6
+ ) {
7
+ const mainIds = new Set(Object.keys(main));
8
+ const branchIds = new Set(Object.keys(branch));
9
+
10
+ const created = [...branchIds.difference(mainIds)];
11
+ const dropped = [...mainIds.difference(branchIds)];
12
+ const altered = [...mainIds.intersection(branchIds)].filter((id) => {
13
+ const mainModel = main[id];
14
+ const branchModel = branch[id];
15
+
16
+ return !mainModel.equals(branchModel);
17
+ });
18
+
19
+ return { created, dropped, altered };
20
+ }
@@ -0,0 +1,82 @@
1
+ import z from "zod";
2
+ import { deepEqual } from "./utils.ts";
3
+
4
+ export const columnPropsSchema = z.object({
5
+ name: z.string(),
6
+ position: z.number(),
7
+ data_type: z.string(),
8
+ data_type_str: z.string(),
9
+ is_custom_type: z.boolean(),
10
+ custom_type_type: z.string().nullable(),
11
+ custom_type_category: z.string().nullable(),
12
+ custom_type_schema: z.string().nullable(),
13
+ custom_type_name: z.string().nullable(),
14
+ not_null: z.boolean(),
15
+ is_identity: z.boolean(),
16
+ is_identity_always: z.boolean(),
17
+ is_generated: z.boolean(),
18
+ collation: z.string().nullable(),
19
+ default: z.string().nullable(),
20
+ comment: z.string().nullable(),
21
+ });
22
+
23
+ export type ColumnProps = z.infer<typeof columnPropsSchema>;
24
+
25
+ export function normalizeColumns(columns: ColumnProps[]) {
26
+ return columns
27
+ .map((column) => {
28
+ const { position: _position, ...rest } = column;
29
+ return rest;
30
+ })
31
+ .sort((a, b) => a.name.localeCompare(b.name));
32
+ }
33
+
34
+ /**
35
+ * Interface for table-like objects that have columns (tables, views, materialized views).
36
+ * In PostgreSQL, these are relations with relkind in ('r', 'p', 'v', 'm').
37
+ */
38
+ export interface TableLikeObject {
39
+ readonly columns: ColumnProps[];
40
+ }
41
+
42
+ export abstract class BasePgModel {
43
+ /**
44
+ * Database-portable stable identifier for dependency resolution.
45
+ * This identifier remains constant across database dumps/restores and
46
+ * is used for cross-database dependency resolution.
47
+ */
48
+ abstract get stableId(): string;
49
+
50
+ /**
51
+ * Get all identity fields and their values.
52
+ * Subclasses should override this to return the identity fields.
53
+ */
54
+ abstract get identityFields(): Record<string, unknown>;
55
+
56
+ /**
57
+ * Get all data fields and their values.
58
+ * Subclasses should override this to return the data fields.
59
+ */
60
+ abstract get dataFields(): Record<string, unknown>;
61
+
62
+ /**
63
+ * Compare this object with another BasePgModel for equality based on stableId and dataFields.
64
+ */
65
+ equals(other: BasePgModel): boolean {
66
+ return (
67
+ this.stableId === other.stableId &&
68
+ deepEqual(this.dataFields, other.dataFields)
69
+ );
70
+ }
71
+
72
+ /**
73
+ * Stable representation used for equality/fingerprints.
74
+ * Subclasses can override to normalize unstable fields.
75
+ */
76
+ stableSnapshot() {
77
+ return {
78
+ identity: this.identityFields,
79
+ data: this.dataFields,
80
+ };
81
+ }
82
+ }