@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,185 @@
1
+ import { sql } from "@ts-safeql/sql-tag";
2
+ import type { Pool } from "pg";
3
+ import z from "zod";
4
+ import { BasePgModel } from "../base.model.ts";
5
+ import {
6
+ type PrivilegeProps,
7
+ privilegePropsSchema,
8
+ } from "../base.privilege-diff.ts";
9
+
10
+ const sequencePropsSchema = z.object({
11
+ schema: z.string(),
12
+ name: z.string(),
13
+ data_type: z.string(),
14
+ start_value: z.number(),
15
+ minimum_value: z.bigint(),
16
+ maximum_value: z.bigint(),
17
+ increment: z.number(),
18
+ cycle_option: z.boolean(),
19
+ cache_size: z.number(),
20
+ persistence: z.string(),
21
+ owned_by_schema: z.string().nullable(),
22
+ owned_by_table: z.string().nullable(),
23
+ owned_by_column: z.string().nullable(),
24
+ comment: z.string().nullable(),
25
+ privileges: z.array(privilegePropsSchema),
26
+ owner: z.string(),
27
+ });
28
+
29
+ type SequencePrivilegeProps = PrivilegeProps;
30
+ export type SequenceProps = z.infer<typeof sequencePropsSchema>;
31
+
32
+ export class Sequence extends BasePgModel {
33
+ public readonly schema: SequenceProps["schema"];
34
+ public readonly name: SequenceProps["name"];
35
+ public readonly data_type: SequenceProps["data_type"];
36
+ public readonly start_value: SequenceProps["start_value"];
37
+ public readonly minimum_value: SequenceProps["minimum_value"];
38
+ public readonly maximum_value: SequenceProps["maximum_value"];
39
+ public readonly increment: SequenceProps["increment"];
40
+ public readonly cycle_option: SequenceProps["cycle_option"];
41
+ public readonly cache_size: SequenceProps["cache_size"];
42
+ public readonly persistence: SequenceProps["persistence"];
43
+ public readonly owned_by_schema: SequenceProps["owned_by_schema"];
44
+ public readonly owned_by_table: SequenceProps["owned_by_table"];
45
+ public readonly owned_by_column: SequenceProps["owned_by_column"];
46
+ public readonly comment: SequenceProps["comment"];
47
+ public readonly privileges: SequencePrivilegeProps[];
48
+ public readonly owner: SequenceProps["owner"];
49
+
50
+ constructor(props: SequenceProps) {
51
+ super();
52
+
53
+ // Identity fields
54
+ this.schema = props.schema;
55
+ this.name = props.name;
56
+
57
+ // Data fields
58
+ this.data_type = props.data_type;
59
+ this.start_value = props.start_value;
60
+ this.minimum_value = props.minimum_value;
61
+ this.maximum_value = props.maximum_value;
62
+ this.increment = props.increment;
63
+ this.cycle_option = props.cycle_option;
64
+ this.cache_size = props.cache_size;
65
+ this.persistence = props.persistence;
66
+ this.owned_by_schema = props.owned_by_schema;
67
+ this.owned_by_table = props.owned_by_table;
68
+ this.owned_by_column = props.owned_by_column;
69
+ this.comment = props.comment;
70
+ this.privileges = props.privileges;
71
+ this.owner = props.owner;
72
+ }
73
+
74
+ get stableId(): `sequence:${string}` {
75
+ return `sequence:${this.schema}.${this.name}`;
76
+ }
77
+
78
+ get identityFields() {
79
+ return {
80
+ schema: this.schema,
81
+ name: this.name,
82
+ };
83
+ }
84
+
85
+ get dataFields() {
86
+ return {
87
+ data_type: this.data_type,
88
+ start_value: this.start_value,
89
+ minimum_value: this.minimum_value,
90
+ maximum_value: this.maximum_value,
91
+ increment: this.increment,
92
+ cycle_option: this.cycle_option,
93
+ cache_size: this.cache_size,
94
+ persistence: this.persistence,
95
+ owned_by_schema: this.owned_by_schema,
96
+ owned_by_table: this.owned_by_table,
97
+ owned_by_column: this.owned_by_column,
98
+ comment: this.comment,
99
+ privileges: this.privileges,
100
+ owner: this.owner,
101
+ };
102
+ }
103
+ }
104
+
105
+ export async function extractSequences(pool: Pool): Promise<Sequence[]> {
106
+ const { rows: sequenceRows } = await pool.query<SequenceProps>(sql`
107
+ with extension_sequence_oids as (
108
+ select
109
+ objid
110
+ from
111
+ pg_depend d
112
+ where
113
+ d.refclassid = 'pg_extension'::regclass
114
+ and d.classid = 'pg_class'::regclass
115
+ ),
116
+ extension_table_oids as (
117
+ select
118
+ objid
119
+ from
120
+ pg_depend d
121
+ where
122
+ d.refclassid = 'pg_extension'::regclass
123
+ and d.classid = 'pg_class'::regclass
124
+ and d.deptype = 'e'
125
+ )
126
+ select
127
+ c.relnamespace::regnamespace::text as schema,
128
+ quote_ident(c.relname) as name,
129
+ format_type(s.seqtypid, null) as data_type,
130
+ s.seqstart::int as start_value,
131
+ s.seqmin as minimum_value,
132
+ s.seqmax as maximum_value,
133
+ s.seqincrement::int as increment,
134
+ s.seqcycle as cycle_option,
135
+ s.seqcache::int as cache_size,
136
+ c.relpersistence as persistence,
137
+ quote_ident(t_ns.nspname) as owned_by_schema,
138
+ case when t.relname is not null then quote_ident(t.relname) else null end as owned_by_table,
139
+ case when att.attname is not null then quote_ident(att.attname) else null end as owned_by_column,
140
+ obj_description(c.oid, 'pg_class') as comment,
141
+ coalesce(
142
+ (
143
+ select json_agg(
144
+ json_build_object(
145
+ 'grantee', case when x.grantee = 0 then 'PUBLIC' else x.grantee::regrole::text end,
146
+ 'privilege', x.privilege_type,
147
+ 'grantable', x.is_grantable
148
+ )
149
+ order by x.grantee, x.privilege_type
150
+ )
151
+ from lateral aclexplode(c.relacl) as x(grantor, grantee, privilege_type, is_grantable)
152
+ ), '[]'
153
+ ) as privileges,
154
+ c.relowner::regrole::text as owner
155
+ from
156
+ pg_catalog.pg_class c
157
+ inner join pg_catalog.pg_sequence s on s.seqrelid = c.oid
158
+ left join pg_depend d on d.classid = 'pg_class'::regclass and d.objid = c.oid and d.refclassid = 'pg_class'::regclass and d.deptype = 'a'
159
+ left join pg_class t on t.oid = d.refobjid
160
+ left join pg_namespace t_ns on t.relnamespace = t_ns.oid
161
+ left join pg_attribute att on att.attrelid = t.oid and att.attnum = d.refobjsubid and d.refobjsubid > 0
162
+ left outer join extension_sequence_oids e_seq on c.oid = e_seq.objid
163
+ left outer join extension_table_oids e_table on t.oid = e_table.objid
164
+ where not c.relnamespace::regnamespace::text like any(array['pg\\_%', 'information\\_schema'])
165
+ and e_seq.objid is null
166
+ and (t.oid is null or e_table.objid is null)
167
+ and c.relkind = 'S'
168
+ -- exclude sequences that are tied to an IDENTITY column
169
+ and not exists (
170
+ select 1
171
+ from pg_depend di
172
+ where di.classid = 'pg_class'::regclass
173
+ and di.objid = c.oid
174
+ and di.refclassid = 'pg_class'::regclass
175
+ and di.deptype = 'i'
176
+ )
177
+ order by
178
+ 1, 2
179
+ `);
180
+ // Validate and parse each row using the Zod schema
181
+ const validatedRows = sequenceRows.map((row: unknown) =>
182
+ sequencePropsSchema.parse(row),
183
+ );
184
+ return validatedRows.map((row: SequenceProps) => new Sequence(row));
185
+ }
@@ -0,0 +1,124 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { stableId } from "../../utils.ts";
3
+ import { Subscription } from "../subscription.model.ts";
4
+ import {
5
+ AlterSubscriptionDisable,
6
+ AlterSubscriptionEnable,
7
+ AlterSubscriptionSetConnection,
8
+ AlterSubscriptionSetOptions,
9
+ AlterSubscriptionSetOwner,
10
+ AlterSubscriptionSetPublication,
11
+ } from "./subscription.alter.ts";
12
+
13
+ type SubscriptionProps = ConstructorParameters<typeof Subscription>[0];
14
+
15
+ const base: SubscriptionProps = {
16
+ name: "sub_base",
17
+ raw_name: "sub_base",
18
+ owner: "owner1",
19
+ comment: null,
20
+ enabled: true,
21
+ binary: false,
22
+ streaming: "off",
23
+ two_phase: false,
24
+ disable_on_error: false,
25
+ password_required: true,
26
+ run_as_owner: false,
27
+ failover: false,
28
+ conninfo: "host=example dbname=postgres",
29
+ slot_name: null,
30
+ slot_is_none: false,
31
+ replication_slot_created: true,
32
+ synchronous_commit: "off",
33
+ publications: ["pub_base"],
34
+ origin: "any",
35
+ };
36
+
37
+ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
38
+ new Subscription({
39
+ ...base,
40
+ ...override,
41
+ publications: override.publications
42
+ ? [...override.publications]
43
+ : [...base.publications],
44
+ });
45
+
46
+ describe("subscription.alter", () => {
47
+ test("set connection serializes conninfo literal", () => {
48
+ const subscription = makeSubscription({
49
+ conninfo: "dbname=postgres host=replica",
50
+ });
51
+ const change = new AlterSubscriptionSetConnection({ subscription });
52
+
53
+ expect(change.serialize()).toBe(
54
+ "ALTER SUBSCRIPTION sub_base CONNECTION 'dbname=postgres host=replica'",
55
+ );
56
+ });
57
+
58
+ test("set publication preserves ordering and refresh hint when disabled", () => {
59
+ const enabledSubscription = makeSubscription({
60
+ publications: ["pub_a", "pub_b"],
61
+ enabled: true,
62
+ });
63
+ const enabledChange = new AlterSubscriptionSetPublication({
64
+ subscription: enabledSubscription,
65
+ });
66
+
67
+ expect(enabledChange.serialize()).toBe(
68
+ "ALTER SUBSCRIPTION sub_base SET PUBLICATION pub_a, pub_b",
69
+ );
70
+
71
+ const disabledSubscription = makeSubscription({
72
+ publications: ["pub_b", "pub_a"],
73
+ enabled: false,
74
+ });
75
+ const disabledChange = new AlterSubscriptionSetPublication({
76
+ subscription: disabledSubscription,
77
+ });
78
+
79
+ expect(disabledChange.serialize()).toBe(
80
+ "ALTER SUBSCRIPTION sub_base SET PUBLICATION pub_a, pub_b WITH (refresh = false)",
81
+ );
82
+ });
83
+
84
+ test("toggle enablement serializes ENABLE and DISABLE statements", () => {
85
+ const subscription = makeSubscription();
86
+
87
+ expect(new AlterSubscriptionEnable({ subscription }).serialize()).toBe(
88
+ "ALTER SUBSCRIPTION sub_base ENABLE",
89
+ );
90
+ expect(new AlterSubscriptionDisable({ subscription }).serialize()).toBe(
91
+ "ALTER SUBSCRIPTION sub_base DISABLE",
92
+ );
93
+ });
94
+
95
+ test("set options delegates to option formatter", () => {
96
+ const subscription = makeSubscription({
97
+ slot_name: "custom_slot",
98
+ slot_is_none: false,
99
+ disable_on_error: true,
100
+ origin: "none",
101
+ });
102
+ const change = new AlterSubscriptionSetOptions({
103
+ subscription,
104
+ options: ["slot_name", "disable_on_error", "origin"],
105
+ });
106
+
107
+ expect(change.serialize()).toBe(
108
+ "ALTER SUBSCRIPTION sub_base SET (slot_name = 'custom_slot', disable_on_error = true, origin = 'none')",
109
+ );
110
+ });
111
+
112
+ test("set owner tracks role dependency", () => {
113
+ const subscription = makeSubscription();
114
+ const change = new AlterSubscriptionSetOwner({
115
+ subscription,
116
+ owner: "new_owner",
117
+ });
118
+
119
+ expect(change.requires).toEqual([stableId.role("new_owner")]);
120
+ expect(change.serialize()).toBe(
121
+ "ALTER SUBSCRIPTION sub_base OWNER TO new_owner",
122
+ );
123
+ });
124
+ });
@@ -0,0 +1,110 @@
1
+ import { quoteLiteral } from "../../base.change.ts";
2
+ import { stableId } from "../../utils.ts";
3
+ import type { Subscription } from "../subscription.model.ts";
4
+ import {
5
+ formatSubscriptionOption,
6
+ type SubscriptionSettableOption,
7
+ } from "../utils.ts";
8
+ import { AlterSubscriptionChange } from "./subscription.base.ts";
9
+
10
+ export class AlterSubscriptionSetConnection extends AlterSubscriptionChange {
11
+ public readonly subscription: Subscription;
12
+ public readonly scope = "object" as const;
13
+
14
+ constructor(props: { subscription: Subscription }) {
15
+ super();
16
+ this.subscription = props.subscription;
17
+ }
18
+
19
+ serialize(): string {
20
+ return `ALTER SUBSCRIPTION ${this.subscription.name} CONNECTION ${quoteLiteral(this.subscription.conninfo)}`;
21
+ }
22
+ }
23
+
24
+ export class AlterSubscriptionSetPublication extends AlterSubscriptionChange {
25
+ public readonly subscription: Subscription;
26
+ public readonly scope = "object" as const;
27
+
28
+ constructor(props: { subscription: Subscription }) {
29
+ super();
30
+ this.subscription = props.subscription;
31
+ }
32
+
33
+ serialize(): string {
34
+ const base = `ALTER SUBSCRIPTION ${this.subscription.name} SET PUBLICATION ${this.subscription.publications.join(", ")}`;
35
+ if (!this.subscription.enabled) {
36
+ return `${base} WITH (refresh = false)`;
37
+ }
38
+ return base;
39
+ }
40
+ }
41
+
42
+ export class AlterSubscriptionEnable extends AlterSubscriptionChange {
43
+ public readonly subscription: Subscription;
44
+ public readonly scope = "object" as const;
45
+
46
+ constructor(props: { subscription: Subscription }) {
47
+ super();
48
+ this.subscription = props.subscription;
49
+ }
50
+
51
+ serialize(): string {
52
+ return `ALTER SUBSCRIPTION ${this.subscription.name} ENABLE`;
53
+ }
54
+ }
55
+
56
+ export class AlterSubscriptionDisable extends AlterSubscriptionChange {
57
+ public readonly subscription: Subscription;
58
+ public readonly scope = "object" as const;
59
+
60
+ constructor(props: { subscription: Subscription }) {
61
+ super();
62
+ this.subscription = props.subscription;
63
+ }
64
+
65
+ serialize(): string {
66
+ return `ALTER SUBSCRIPTION ${this.subscription.name} DISABLE`;
67
+ }
68
+ }
69
+
70
+ export class AlterSubscriptionSetOptions extends AlterSubscriptionChange {
71
+ public readonly subscription: Subscription;
72
+ public readonly scope = "object" as const;
73
+ private readonly options: SubscriptionSettableOption[];
74
+
75
+ constructor(props: {
76
+ subscription: Subscription;
77
+ options: SubscriptionSettableOption[];
78
+ }) {
79
+ super();
80
+ this.subscription = props.subscription;
81
+ this.options = props.options;
82
+ }
83
+
84
+ serialize(): string {
85
+ const assignments = this.options.map((option) =>
86
+ formatSubscriptionOption(this.subscription, option),
87
+ );
88
+ return `ALTER SUBSCRIPTION ${this.subscription.name} SET (${assignments.join(", ")})`;
89
+ }
90
+ }
91
+
92
+ export class AlterSubscriptionSetOwner extends AlterSubscriptionChange {
93
+ public readonly subscription: Subscription;
94
+ public readonly scope = "object" as const;
95
+ public readonly owner: string;
96
+
97
+ constructor(props: { subscription: Subscription; owner: string }) {
98
+ super();
99
+ this.subscription = props.subscription;
100
+ this.owner = props.owner;
101
+ }
102
+
103
+ get requires() {
104
+ return [stableId.role(this.owner)];
105
+ }
106
+
107
+ serialize(): string {
108
+ return `ALTER SUBSCRIPTION ${this.subscription.name} OWNER TO ${this.owner}`;
109
+ }
110
+ }
@@ -0,0 +1,20 @@
1
+ import { BaseChange } from "../../base.change.ts";
2
+ import type { Subscription } from "../subscription.model.ts";
3
+
4
+ abstract class BaseSubscriptionChange extends BaseChange {
5
+ abstract readonly subscription: Subscription;
6
+ abstract readonly scope: "object" | "comment";
7
+ readonly objectType = "subscription" as const;
8
+ }
9
+
10
+ export abstract class CreateSubscriptionChange extends BaseSubscriptionChange {
11
+ readonly operation = "create" as const;
12
+ }
13
+
14
+ export abstract class AlterSubscriptionChange extends BaseSubscriptionChange {
15
+ readonly operation = "alter" as const;
16
+ }
17
+
18
+ export abstract class DropSubscriptionChange extends BaseSubscriptionChange {
19
+ readonly operation = "drop" as const;
20
+ }
@@ -0,0 +1,67 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { stableId } from "../../utils.ts";
3
+ import { Subscription } from "../subscription.model.ts";
4
+ import {
5
+ CreateCommentOnSubscription,
6
+ DropCommentOnSubscription,
7
+ } from "./subscription.comment.ts";
8
+
9
+ type SubscriptionProps = ConstructorParameters<typeof Subscription>[0];
10
+
11
+ const base: SubscriptionProps = {
12
+ name: "sub_base",
13
+ raw_name: "sub_base",
14
+ owner: "owner1",
15
+ comment: null,
16
+ enabled: true,
17
+ binary: false,
18
+ streaming: "off",
19
+ two_phase: false,
20
+ disable_on_error: false,
21
+ password_required: true,
22
+ run_as_owner: false,
23
+ failover: false,
24
+ conninfo: "host=example dbname=postgres",
25
+ slot_name: null,
26
+ slot_is_none: false,
27
+ replication_slot_created: true,
28
+ synchronous_commit: "off",
29
+ publications: ["pub_base"],
30
+ origin: "any",
31
+ };
32
+
33
+ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
34
+ new Subscription({
35
+ ...base,
36
+ ...override,
37
+ publications: override.publications
38
+ ? [...override.publications]
39
+ : [...base.publications],
40
+ });
41
+
42
+ describe("subscription.comment", () => {
43
+ test("create comment serializes and declares dependencies", () => {
44
+ const subscription = makeSubscription({
45
+ comment: "subscription's metadata",
46
+ });
47
+ const change = new CreateCommentOnSubscription({ subscription });
48
+
49
+ expect(change.creates).toEqual([stableId.comment(subscription.stableId)]);
50
+ expect(change.requires).toEqual([subscription.stableId]);
51
+ expect(change.serialize()).toBe(
52
+ "COMMENT ON SUBSCRIPTION sub_base IS 'subscription''s metadata'",
53
+ );
54
+ });
55
+
56
+ test("drop comment serializes and tracks drops", () => {
57
+ const subscription = makeSubscription({ comment: "not used" });
58
+ const change = new DropCommentOnSubscription({ subscription });
59
+
60
+ expect(change.drops).toEqual([stableId.comment(subscription.stableId)]);
61
+ expect(change.requires).toEqual([
62
+ stableId.comment(subscription.stableId),
63
+ subscription.stableId,
64
+ ]);
65
+ expect(change.serialize()).toBe("COMMENT ON SUBSCRIPTION sub_base IS NULL");
66
+ });
67
+ });
@@ -0,0 +1,64 @@
1
+ import { quoteLiteral } from "../../base.change.ts";
2
+ import { stableId } from "../../utils.ts";
3
+ import type { Subscription } from "../subscription.model.ts";
4
+ import {
5
+ CreateSubscriptionChange,
6
+ DropSubscriptionChange,
7
+ } from "./subscription.base.ts";
8
+
9
+ export type CommentSubscription =
10
+ | CreateCommentOnSubscription
11
+ | DropCommentOnSubscription;
12
+
13
+ export class CreateCommentOnSubscription extends CreateSubscriptionChange {
14
+ public readonly subscription: Subscription;
15
+ public readonly scope = "comment" as const;
16
+
17
+ constructor(props: { subscription: Subscription }) {
18
+ super();
19
+ this.subscription = props.subscription;
20
+ }
21
+
22
+ get creates() {
23
+ return [stableId.comment(this.subscription.stableId)];
24
+ }
25
+
26
+ get requires() {
27
+ return [this.subscription.stableId];
28
+ }
29
+
30
+ serialize(): string {
31
+ return [
32
+ "COMMENT ON SUBSCRIPTION",
33
+ this.subscription.name,
34
+ "IS",
35
+ // biome-ignore lint/style/noNonNullAssertion: ensures comment provided by caller
36
+ quoteLiteral(this.subscription.comment!),
37
+ ].join(" ");
38
+ }
39
+ }
40
+
41
+ export class DropCommentOnSubscription extends DropSubscriptionChange {
42
+ public readonly subscription: Subscription;
43
+ public readonly scope = "comment" as const;
44
+
45
+ constructor(props: { subscription: Subscription }) {
46
+ super();
47
+ this.subscription = props.subscription;
48
+ }
49
+
50
+ get drops() {
51
+ return [stableId.comment(this.subscription.stableId)];
52
+ }
53
+
54
+ get requires() {
55
+ return [
56
+ stableId.comment(this.subscription.stableId),
57
+ this.subscription.stableId,
58
+ ];
59
+ }
60
+
61
+ serialize(): string {
62
+ return `COMMENT ON SUBSCRIPTION ${this.subscription.name} IS NULL`;
63
+ }
64
+ }
@@ -0,0 +1,77 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { stableId } from "../../utils.ts";
3
+ import { Subscription } from "../subscription.model.ts";
4
+ import { CreateSubscription } from "./subscription.create.ts";
5
+
6
+ type SubscriptionProps = ConstructorParameters<typeof Subscription>[0];
7
+
8
+ const base: SubscriptionProps = {
9
+ name: "sub_base",
10
+ raw_name: "sub_base",
11
+ owner: "owner1",
12
+ comment: null,
13
+ enabled: true,
14
+ binary: false,
15
+ streaming: "off",
16
+ two_phase: false,
17
+ disable_on_error: false,
18
+ password_required: true,
19
+ run_as_owner: false,
20
+ failover: false,
21
+ conninfo: "host=example dbname=postgres",
22
+ slot_name: null,
23
+ slot_is_none: false,
24
+ replication_slot_created: true,
25
+ synchronous_commit: "off",
26
+ publications: ["pub_base"],
27
+ origin: "any",
28
+ };
29
+
30
+ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
31
+ new Subscription({
32
+ ...base,
33
+ ...override,
34
+ publications: override.publications
35
+ ? [...override.publications]
36
+ : [...base.publications],
37
+ });
38
+
39
+ describe("subscription.create", () => {
40
+ test("serialize minimal subscription", () => {
41
+ const subscription = makeSubscription();
42
+ const change = new CreateSubscription({ subscription });
43
+
44
+ expect(change.creates).toEqual([subscription.stableId]);
45
+ expect(change.requires).toEqual([stableId.role(subscription.owner)]);
46
+ expect(change.serialize()).toBe(
47
+ "CREATE SUBSCRIPTION sub_base CONNECTION 'host=example dbname=postgres' PUBLICATION pub_base",
48
+ );
49
+ });
50
+
51
+ test("serialize subscription with extended options", () => {
52
+ const subscription = makeSubscription({
53
+ enabled: false,
54
+ binary: true,
55
+ streaming: "parallel",
56
+ two_phase: true,
57
+ disable_on_error: true,
58
+ password_required: false,
59
+ run_as_owner: true,
60
+ failover: true,
61
+ conninfo: "dbname=postgres application_name=sub_base",
62
+ slot_name: "custom_slot",
63
+ slot_is_none: false,
64
+ replication_slot_created: false,
65
+ synchronous_commit: "local",
66
+ publications: ["pub_b", "pub_a"],
67
+ origin: "none",
68
+ });
69
+
70
+ const change = new CreateSubscription({ subscription });
71
+
72
+ expect(change.requires).toEqual([stableId.role(subscription.owner)]);
73
+ expect(change.serialize()).toBe(
74
+ "CREATE SUBSCRIPTION sub_base CONNECTION 'dbname=postgres application_name=sub_base' PUBLICATION pub_a, pub_b WITH (enabled = false, slot_name = 'custom_slot', binary = true, streaming = 'parallel', synchronous_commit = 'local', two_phase = true, disable_on_error = true, password_required = false, run_as_owner = true, origin = 'none', failover = true, create_slot = false, connect = false)",
75
+ );
76
+ });
77
+ });