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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/README.md +40 -23
  2. package/dist/cli/app.js +26 -3
  3. package/dist/cli/bin/cli.js +5 -0
  4. package/dist/cli/commands/catalog-export.d.ts +5 -0
  5. package/dist/cli/commands/catalog-export.js +64 -0
  6. package/dist/cli/commands/declarative-apply.d.ts +6 -0
  7. package/dist/cli/commands/declarative-apply.js +288 -0
  8. package/dist/cli/commands/declarative-export.d.ts +5 -0
  9. package/dist/cli/commands/declarative-export.js +245 -0
  10. package/dist/cli/commands/plan.js +19 -6
  11. package/dist/cli/exit-code.d.ts +2 -0
  12. package/dist/cli/exit-code.js +7 -0
  13. package/dist/cli/formatters/tree/tree.js +3 -2
  14. package/dist/cli/utils/apply-display.d.ts +52 -0
  15. package/dist/cli/utils/apply-display.js +183 -0
  16. package/dist/cli/utils/export-display.d.ts +43 -0
  17. package/dist/cli/utils/export-display.js +202 -0
  18. package/dist/cli/utils/resolve-input.d.ts +7 -0
  19. package/dist/cli/utils/resolve-input.js +13 -0
  20. package/dist/core/catalog-export/index.d.ts +11 -0
  21. package/dist/core/catalog-export/index.js +10 -0
  22. package/dist/core/catalog.diff.d.ts +1 -0
  23. package/dist/core/catalog.diff.js +64 -48
  24. package/dist/core/catalog.model.d.ts +14 -1
  25. package/dist/core/catalog.model.js +103 -1
  26. package/dist/core/catalog.snapshot.d.ts +66 -0
  27. package/dist/core/catalog.snapshot.js +206 -0
  28. package/dist/core/declarative-apply/discover-sql.d.ts +18 -0
  29. package/dist/core/declarative-apply/discover-sql.js +86 -0
  30. package/dist/core/declarative-apply/extract-catalog-providers.d.ts +23 -0
  31. package/dist/core/declarative-apply/extract-catalog-providers.js +159 -0
  32. package/dist/core/declarative-apply/index.d.ts +49 -0
  33. package/dist/core/declarative-apply/index.js +134 -0
  34. package/dist/core/declarative-apply/round-apply.d.ts +100 -0
  35. package/dist/core/declarative-apply/round-apply.js +378 -0
  36. package/dist/core/export/file-mapper.d.ts +71 -0
  37. package/dist/core/export/file-mapper.js +474 -0
  38. package/dist/core/export/grouper.d.ts +13 -0
  39. package/dist/core/export/grouper.js +76 -0
  40. package/dist/core/export/index.d.ts +45 -0
  41. package/dist/core/export/index.js +63 -0
  42. package/dist/core/export/types.d.ts +84 -0
  43. package/dist/core/export/types.js +25 -0
  44. package/dist/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  45. package/dist/core/integrations/filter/dsl.d.ts +38 -1
  46. package/dist/core/integrations/filter/dsl.js +20 -2
  47. package/dist/core/integrations/filter/extractors.js +42 -0
  48. package/dist/core/integrations/integration-dsl.d.ts +10 -0
  49. package/dist/core/integrations/supabase.d.ts +8 -0
  50. package/dist/core/integrations/supabase.js +9 -0
  51. package/dist/core/objects/aggregate/aggregate.diff.d.ts +2 -8
  52. package/dist/core/objects/aggregate/aggregate.diff.js +16 -70
  53. package/dist/core/objects/aggregate/aggregate.model.d.ts +8 -8
  54. package/dist/core/objects/aggregate/aggregate.model.js +1 -1
  55. package/dist/core/objects/aggregate/changes/aggregate.create.js +1 -1
  56. package/dist/core/objects/aggregate/changes/aggregate.drop.js +1 -1
  57. package/dist/core/objects/base.privilege-diff.d.ts +38 -13
  58. package/dist/core/objects/base.privilege-diff.js +104 -22
  59. package/dist/core/objects/base.privilege.d.ts +1 -0
  60. package/dist/core/objects/base.privilege.js +9 -2
  61. package/dist/core/objects/collation/collation.diff.d.ts +2 -3
  62. package/dist/core/objects/diff-context.d.ts +15 -0
  63. package/dist/core/objects/diff-context.js +1 -0
  64. package/dist/core/objects/domain/changes/domain.create.js +4 -2
  65. package/dist/core/objects/domain/domain.diff.d.ts +2 -8
  66. package/dist/core/objects/domain/domain.diff.js +16 -77
  67. package/dist/core/objects/domain/domain.model.js +1 -1
  68. package/dist/core/objects/event-trigger/event-trigger.diff.d.ts +2 -3
  69. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.d.ts +2 -8
  70. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.js +13 -77
  71. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +2 -2
  72. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.d.ts +2 -8
  73. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -77
  74. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +1 -1
  75. package/dist/core/objects/foreign-data-wrapper/server/server.diff.d.ts +2 -8
  76. package/dist/core/objects/foreign-data-wrapper/server/server.diff.js +13 -77
  77. package/dist/core/objects/language/language.diff.d.ts +2 -5
  78. package/dist/core/objects/language/language.diff.js +7 -39
  79. package/dist/core/objects/materialized-view/materialized-view.diff.d.ts +2 -8
  80. package/dist/core/objects/materialized-view/materialized-view.diff.js +16 -158
  81. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +3 -3
  82. package/dist/core/objects/materialized-view/materialized-view.model.js +1 -1
  83. package/dist/core/objects/procedure/changes/procedure.alter.js +12 -12
  84. package/dist/core/objects/procedure/procedure.diff.d.ts +2 -8
  85. package/dist/core/objects/procedure/procedure.diff.js +16 -77
  86. package/dist/core/objects/procedure/procedure.model.d.ts +9 -9
  87. package/dist/core/objects/procedure/procedure.model.js +1 -1
  88. package/dist/core/objects/publication/changes/publication.alter.d.ts +0 -9
  89. package/dist/core/objects/publication/changes/publication.alter.js +0 -14
  90. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -2
  91. package/dist/core/objects/publication/publication.diff.d.ts +2 -3
  92. package/dist/core/objects/publication/publication.diff.js +8 -13
  93. package/dist/core/objects/rls-policy/changes/rls-policy.alter.js +3 -3
  94. package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
  95. package/dist/core/objects/role/role.diff.js +22 -1
  96. package/dist/core/objects/role/role.model.d.ts +4 -3
  97. package/dist/core/objects/role/role.model.js +118 -12
  98. package/dist/core/objects/rule/rule.model.d.ts +1 -1
  99. package/dist/core/objects/schema/schema.diff.d.ts +2 -8
  100. package/dist/core/objects/schema/schema.diff.js +16 -77
  101. package/dist/core/objects/schema/schema.model.js +1 -1
  102. package/dist/core/objects/sequence/sequence.diff.d.ts +2 -8
  103. package/dist/core/objects/sequence/sequence.diff.js +16 -79
  104. package/dist/core/objects/sequence/sequence.model.js +1 -1
  105. package/dist/core/objects/subscription/subscription.diff.d.ts +2 -3
  106. package/dist/core/objects/table/changes/table.create.js +3 -0
  107. package/dist/core/objects/table/table.diff.d.ts +2 -8
  108. package/dist/core/objects/table/table.diff.js +26 -157
  109. package/dist/core/objects/table/table.model.d.ts +23 -22
  110. package/dist/core/objects/table/table.model.js +1 -1
  111. package/dist/core/objects/trigger/changes/trigger.create.js +2 -4
  112. package/dist/core/objects/trigger/trigger.model.d.ts +8 -0
  113. package/dist/core/objects/trigger/trigger.model.js +11 -0
  114. package/dist/core/objects/type/composite-type/composite-type.diff.d.ts +2 -8
  115. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -77
  116. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +3 -3
  117. package/dist/core/objects/type/composite-type/composite-type.model.js +2 -1
  118. package/dist/core/objects/type/enum/enum.diff.d.ts +2 -8
  119. package/dist/core/objects/type/enum/enum.diff.js +25 -112
  120. package/dist/core/objects/type/enum/enum.model.js +1 -1
  121. package/dist/core/objects/type/range/changes/range.create.js +6 -3
  122. package/dist/core/objects/type/range/range.diff.d.ts +2 -8
  123. package/dist/core/objects/type/range/range.diff.js +16 -77
  124. package/dist/core/objects/type/range/range.model.js +1 -1
  125. package/dist/core/objects/view/view.diff.d.ts +2 -8
  126. package/dist/core/objects/view/view.diff.js +16 -158
  127. package/dist/core/objects/view/view.model.d.ts +18 -4
  128. package/dist/core/objects/view/view.model.js +3 -13
  129. package/dist/core/plan/apply.js +9 -26
  130. package/dist/core/plan/create.d.ts +19 -6
  131. package/dist/core/plan/create.js +134 -174
  132. package/dist/core/plan/serialize.js +16 -4
  133. package/dist/core/plan/sql-format/fixtures.js +3 -5
  134. package/dist/core/plan/sql-format/keyword-case.js +26 -1
  135. package/dist/core/plan/ssl-config.d.ts +32 -0
  136. package/dist/core/plan/ssl-config.js +115 -0
  137. package/dist/core/plan/types.d.ts +6 -0
  138. package/dist/core/postgres-config.d.ts +14 -0
  139. package/dist/core/postgres-config.js +53 -2
  140. package/dist/core/sort/graph-builder.js +10 -0
  141. package/dist/core/sort/logical-sort.js +31 -23
  142. package/dist/core/test-utils/assert-valid-sql.d.ts +10 -0
  143. package/dist/core/test-utils/assert-valid-sql.js +19 -0
  144. package/dist/index.d.ts +6 -0
  145. package/dist/index.js +6 -1
  146. package/package.json +21 -4
  147. package/src/cli/app.ts +27 -3
  148. package/src/cli/bin/cli.ts +6 -0
  149. package/src/cli/commands/catalog-export.ts +78 -0
  150. package/src/cli/commands/declarative-apply.diagnostics.test.ts +77 -0
  151. package/src/cli/commands/declarative-apply.ts +380 -0
  152. package/src/cli/commands/declarative-export.ts +330 -0
  153. package/src/cli/commands/plan.ts +28 -7
  154. package/src/cli/exit-code.test.ts +19 -0
  155. package/src/cli/exit-code.ts +7 -0
  156. package/src/cli/formatters/tree/tree.ts +3 -2
  157. package/src/cli/utils/apply-display.test.ts +348 -0
  158. package/src/cli/utils/apply-display.ts +238 -0
  159. package/src/cli/utils/export-display.test.ts +103 -0
  160. package/src/cli/utils/export-display.ts +275 -0
  161. package/src/cli/utils/integrations.test.ts +44 -0
  162. package/src/cli/utils/resolve-input.test.ts +38 -0
  163. package/src/cli/utils/resolve-input.ts +17 -0
  164. package/src/core/catalog-export/index.ts +20 -0
  165. package/src/core/catalog.diff.ts +79 -78
  166. package/src/core/catalog.model.test.ts +122 -0
  167. package/src/core/catalog.model.ts +127 -1
  168. package/src/core/catalog.snapshot.test.ts +464 -0
  169. package/src/core/catalog.snapshot.ts +289 -0
  170. package/src/core/declarative-apply/discover-sql.test.ts +103 -0
  171. package/src/core/declarative-apply/discover-sql.ts +107 -0
  172. package/src/core/declarative-apply/extract-catalog-providers.ts +220 -0
  173. package/src/core/declarative-apply/index.test.ts +67 -0
  174. package/src/core/declarative-apply/index.ts +205 -0
  175. package/src/core/declarative-apply/round-apply.test.ts +504 -0
  176. package/src/core/declarative-apply/round-apply.ts +562 -0
  177. package/src/core/expand-replace-dependencies.test.ts +70 -0
  178. package/src/core/export/file-mapper.test.ts +816 -0
  179. package/src/core/export/file-mapper.ts +574 -0
  180. package/src/core/export/grouper.ts +108 -0
  181. package/src/core/export/index.ts +129 -0
  182. package/src/core/export/types.ts +104 -0
  183. package/src/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  184. package/src/core/integrations/filter/dsl.test.ts +211 -0
  185. package/src/core/integrations/filter/dsl.ts +65 -3
  186. package/src/core/integrations/filter/extractors.test.ts +244 -0
  187. package/src/core/integrations/filter/extractors.ts +42 -0
  188. package/src/core/integrations/integration-dsl.ts +10 -0
  189. package/src/core/integrations/serialize/dsl.test.ts +91 -0
  190. package/src/core/integrations/supabase.ts +9 -0
  191. package/src/core/objects/aggregate/aggregate.diff.ts +39 -95
  192. package/src/core/objects/aggregate/aggregate.model.ts +1 -1
  193. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +3 -1
  194. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +5 -2
  195. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +6 -3
  196. package/src/core/objects/aggregate/changes/aggregate.create.ts +1 -1
  197. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +7 -3
  198. package/src/core/objects/aggregate/changes/aggregate.drop.ts +1 -1
  199. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +9 -3
  200. package/src/core/objects/base.privilege-diff.ts +178 -30
  201. package/src/core/objects/base.privilege.ts +9 -2
  202. package/src/core/objects/collation/changes/collation.alter.test.ts +7 -2
  203. package/src/core/objects/collation/changes/collation.create.test.ts +7 -2
  204. package/src/core/objects/collation/changes/collation.drop.test.ts +4 -1
  205. package/src/core/objects/collation/collation.diff.test.ts +9 -12
  206. package/src/core/objects/collation/collation.diff.ts +2 -1
  207. package/src/core/objects/diff-context.ts +16 -0
  208. package/src/core/objects/domain/changes/domain.alter.test.ts +28 -9
  209. package/src/core/objects/domain/changes/domain.create.test.ts +32 -2
  210. package/src/core/objects/domain/changes/domain.create.ts +7 -1
  211. package/src/core/objects/domain/changes/domain.drop.test.ts +4 -1
  212. package/src/core/objects/domain/domain.diff.ts +39 -102
  213. package/src/core/objects/domain/domain.model.ts +1 -1
  214. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +10 -3
  215. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +4 -1
  216. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +4 -1
  217. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +12 -7
  218. package/src/core/objects/event-trigger/event-trigger.diff.ts +2 -1
  219. package/src/core/objects/extension/changes/extension.alter.test.ts +7 -2
  220. package/src/core/objects/extension/changes/extension.create.test.ts +4 -1
  221. package/src/core/objects/extension/changes/extension.drop.test.ts +4 -1
  222. package/src/core/objects/extension/extension.model.test.ts +98 -0
  223. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +16 -5
  224. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +51 -16
  225. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +4 -1
  226. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +111 -4
  227. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +31 -101
  228. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +2 -2
  229. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +46 -15
  230. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +13 -4
  231. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +4 -1
  232. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +39 -102
  233. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +1 -1
  234. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +22 -7
  235. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +19 -6
  236. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +4 -1
  237. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +95 -0
  238. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +31 -101
  239. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +13 -4
  240. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +16 -5
  241. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +10 -3
  242. package/src/core/objects/index/changes/index.alter.test.ts +13 -4
  243. package/src/core/objects/index/changes/index.create.test.ts +4 -1
  244. package/src/core/objects/index/changes/index.drop.test.ts +4 -1
  245. package/src/core/objects/language/changes/language.alter.test.ts +4 -1
  246. package/src/core/objects/language/changes/language.create.test.ts +4 -1
  247. package/src/core/objects/language/changes/language.drop.test.ts +4 -1
  248. package/src/core/objects/language/language.diff.test.ts +86 -4
  249. package/src/core/objects/language/language.diff.ts +17 -49
  250. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +10 -3
  251. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +7 -2
  252. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +4 -1
  253. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +162 -0
  254. package/src/core/objects/materialized-view/materialized-view.diff.ts +41 -191
  255. package/src/core/objects/materialized-view/materialized-view.model.ts +1 -1
  256. package/src/core/objects/procedure/changes/procedure.alter.test.ts +121 -49
  257. package/src/core/objects/procedure/changes/procedure.alter.ts +15 -12
  258. package/src/core/objects/procedure/changes/procedure.create.test.ts +4 -1
  259. package/src/core/objects/procedure/changes/procedure.drop.test.ts +7 -2
  260. package/src/core/objects/procedure/procedure.diff.ts +39 -102
  261. package/src/core/objects/procedure/procedure.model.ts +1 -1
  262. package/src/core/objects/publication/changes/publication.alter.test.ts +15 -21
  263. package/src/core/objects/publication/changes/publication.alter.ts +0 -18
  264. package/src/core/objects/publication/changes/publication.comment.test.ts +5 -2
  265. package/src/core/objects/publication/changes/publication.create.test.ts +5 -2
  266. package/src/core/objects/publication/changes/publication.drop.test.ts +3 -1
  267. package/src/core/objects/publication/changes/publication.types.ts +0 -2
  268. package/src/core/objects/publication/publication.diff.test.ts +24 -19
  269. package/src/core/objects/publication/publication.diff.ts +9 -15
  270. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +31 -14
  271. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +3 -3
  272. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +10 -3
  273. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +4 -1
  274. package/src/core/objects/role/changes/role.alter.test.ts +31 -15
  275. package/src/core/objects/role/changes/role.create.test.ts +6 -2
  276. package/src/core/objects/role/changes/role.drop.test.ts +4 -1
  277. package/src/core/objects/role/role.diff.test.ts +235 -0
  278. package/src/core/objects/role/role.diff.ts +21 -1
  279. package/src/core/objects/role/role.model.ts +122 -14
  280. package/src/core/objects/rule/changes/rule.alter.test.ts +7 -3
  281. package/src/core/objects/rule/changes/rule.comment.test.ts +5 -2
  282. package/src/core/objects/rule/changes/rule.create.test.ts +6 -2
  283. package/src/core/objects/rule/changes/rule.drop.test.ts +3 -1
  284. package/src/core/objects/schema/changes/schema.alter.test.ts +4 -1
  285. package/src/core/objects/schema/changes/schema.create.test.ts +4 -1
  286. package/src/core/objects/schema/changes/schema.drop.test.ts +4 -1
  287. package/src/core/objects/schema/schema.diff.ts +39 -102
  288. package/src/core/objects/schema/schema.model.ts +1 -1
  289. package/src/core/objects/sequence/changes/sequence.alter.test.ts +11 -5
  290. package/src/core/objects/sequence/changes/sequence.create.test.ts +8 -3
  291. package/src/core/objects/sequence/changes/sequence.drop.test.ts +4 -1
  292. package/src/core/objects/sequence/sequence.diff.test.ts +114 -0
  293. package/src/core/objects/sequence/sequence.diff.ts +39 -104
  294. package/src/core/objects/sequence/sequence.model.ts +1 -1
  295. package/src/core/objects/subscription/changes/subscription.alter.test.ts +15 -5
  296. package/src/core/objects/subscription/changes/subscription.comment.test.ts +5 -2
  297. package/src/core/objects/subscription/changes/subscription.create.test.ts +5 -2
  298. package/src/core/objects/subscription/changes/subscription.drop.test.ts +3 -1
  299. package/src/core/objects/subscription/subscription.diff.test.ts +16 -11
  300. package/src/core/objects/subscription/subscription.diff.ts +2 -1
  301. package/src/core/objects/table/changes/table.alter.test.ts +38 -15
  302. package/src/core/objects/table/changes/table.create.test.ts +41 -3
  303. package/src/core/objects/table/changes/table.create.ts +4 -0
  304. package/src/core/objects/table/changes/table.drop.test.ts +3 -1
  305. package/src/core/objects/table/table.diff.test.ts +157 -0
  306. package/src/core/objects/table/table.diff.ts +54 -190
  307. package/src/core/objects/table/table.model.ts +1 -1
  308. package/src/core/objects/trigger/changes/trigger.alter.test.ts +8 -4
  309. package/src/core/objects/trigger/changes/trigger.create.test.ts +5 -1
  310. package/src/core/objects/trigger/changes/trigger.create.ts +7 -4
  311. package/src/core/objects/trigger/changes/trigger.drop.test.ts +5 -1
  312. package/src/core/objects/trigger/trigger.diff.test.ts +1 -0
  313. package/src/core/objects/trigger/trigger.model.ts +12 -0
  314. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +10 -4
  315. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +7 -2
  316. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +4 -1
  317. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +78 -0
  318. package/src/core/objects/type/composite-type/composite-type.diff.ts +39 -101
  319. package/src/core/objects/type/composite-type/composite-type.model.ts +2 -1
  320. package/src/core/objects/type/enum/changes/enum.alter.test.ts +14 -5
  321. package/src/core/objects/type/enum/changes/enum.create.test.ts +4 -1
  322. package/src/core/objects/type/enum/changes/enum.drop.test.ts +4 -1
  323. package/src/core/objects/type/enum/enum.diff.test.ts +181 -0
  324. package/src/core/objects/type/enum/enum.diff.ts +58 -146
  325. package/src/core/objects/type/enum/enum.model.ts +1 -1
  326. package/src/core/objects/type/range/changes/range.alter.test.ts +3 -1
  327. package/src/core/objects/type/range/changes/range.create.test.ts +5 -2
  328. package/src/core/objects/type/range/changes/range.create.ts +6 -2
  329. package/src/core/objects/type/range/changes/range.drop.test.ts +3 -1
  330. package/src/core/objects/type/range/range.diff.test.ts +77 -0
  331. package/src/core/objects/type/range/range.diff.ts +39 -101
  332. package/src/core/objects/type/range/range.model.ts +1 -1
  333. package/src/core/objects/view/changes/view.alter.test.ts +8 -3
  334. package/src/core/objects/view/changes/view.create.test.ts +7 -2
  335. package/src/core/objects/view/changes/view.drop.test.ts +4 -1
  336. package/src/core/objects/view/view.diff.test.ts +82 -0
  337. package/src/core/objects/view/view.diff.ts +41 -191
  338. package/src/core/objects/view/view.model.ts +3 -17
  339. package/src/core/plan/apply.ts +9 -27
  340. package/src/core/plan/create.ts +173 -237
  341. package/src/core/plan/serialize.test.ts +317 -0
  342. package/src/core/plan/serialize.ts +18 -4
  343. package/src/core/plan/sql-format/fixtures.ts +2 -5
  344. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +52 -0
  345. package/src/core/plan/sql-format/format-off.test.ts +14 -17
  346. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +27 -22
  347. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +17 -21
  348. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +25 -20
  349. package/src/core/plan/sql-format/format-pretty-upper.test.ts +23 -20
  350. package/src/core/plan/sql-format/keyword-case.ts +36 -1
  351. package/src/core/plan/ssl-config.ts +172 -0
  352. package/src/core/plan/types.ts +6 -0
  353. package/src/core/postgres-config.ts +71 -2
  354. package/src/core/sort/graph-builder.ts +12 -0
  355. package/src/core/sort/logical-sort.test.ts +371 -0
  356. package/src/core/sort/logical-sort.ts +32 -25
  357. package/src/core/sort/topological-sort.test.ts +275 -0
  358. package/src/core/test-utils/assert-valid-sql.ts +20 -0
  359. package/src/index.ts +26 -2
@@ -0,0 +1,464 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { Catalog, createEmptyCatalog } from "./catalog.model.ts";
3
+ import {
4
+ deserializeCatalog,
5
+ serializeCatalog,
6
+ stringifyCatalogSnapshot,
7
+ } from "./catalog.snapshot.ts";
8
+ import { Aggregate } from "./objects/aggregate/aggregate.model.ts";
9
+ import { Procedure } from "./objects/procedure/procedure.model.ts";
10
+ import { RlsPolicy } from "./objects/rls-policy/rls-policy.model.ts";
11
+ import { Role } from "./objects/role/role.model.ts";
12
+ import { Schema } from "./objects/schema/schema.model.ts";
13
+ import { Sequence } from "./objects/sequence/sequence.model.ts";
14
+ import { Table } from "./objects/table/table.model.ts";
15
+
16
+ function emptyCatalogProps() {
17
+ return {
18
+ aggregates: {},
19
+ collations: {},
20
+ compositeTypes: {},
21
+ domains: {},
22
+ enums: {},
23
+ extensions: {},
24
+ procedures: {},
25
+ indexes: {},
26
+ materializedViews: {},
27
+ subscriptions: {},
28
+ publications: {},
29
+ rlsPolicies: {},
30
+ roles: {},
31
+ schemas: {},
32
+ sequences: {},
33
+ tables: {},
34
+ triggers: {},
35
+ eventTriggers: {},
36
+ rules: {},
37
+ ranges: {},
38
+ views: {},
39
+ foreignDataWrappers: {},
40
+ servers: {},
41
+ userMappings: {},
42
+ foreignTables: {},
43
+ depends: [],
44
+ indexableObjects: {},
45
+ version: 160000,
46
+ currentUser: "postgres",
47
+ };
48
+ }
49
+
50
+ describe("catalog snapshot serde", () => {
51
+ test("round-trip on empty catalog", async () => {
52
+ const original = await createEmptyCatalog(160000, "postgres");
53
+ const snapshot = serializeCatalog(original);
54
+ const json = stringifyCatalogSnapshot(snapshot);
55
+ const deserialized = deserializeCatalog(JSON.parse(json));
56
+
57
+ expect(deserialized.version).toBe(original.version);
58
+ expect(deserialized.currentUser).toBe(original.currentUser);
59
+ expect(Object.keys(deserialized.schemas)).toEqual(
60
+ Object.keys(original.schemas),
61
+ );
62
+
63
+ const origSchema = original.schemas["schema:public"];
64
+ const deserSchema = deserialized.schemas["schema:public"];
65
+ expect(deserSchema.name).toBe(origSchema.name);
66
+ expect(deserSchema.owner).toBe(origSchema.owner);
67
+ expect(deserSchema.comment).toBe(origSchema.comment);
68
+ expect(deserSchema.privileges).toEqual(origSchema.privileges);
69
+ });
70
+
71
+ test("round-trip preserves Sequence BigInt fields", () => {
72
+ const seq = new Sequence({
73
+ schema: "public",
74
+ name: "my_seq",
75
+ data_type: "bigint",
76
+ start_value: 1,
77
+ minimum_value: BigInt("-9223372036854775808"),
78
+ maximum_value: BigInt("9223372036854775807"),
79
+ increment: 1,
80
+ cycle_option: false,
81
+ cache_size: 1,
82
+ persistence: "p",
83
+ owned_by_schema: null,
84
+ owned_by_table: null,
85
+ owned_by_column: null,
86
+ comment: null,
87
+ privileges: [],
88
+ owner: "postgres",
89
+ });
90
+
91
+ const catalog = new Catalog({
92
+ ...emptyCatalogProps(),
93
+ sequences: { [seq.stableId]: seq },
94
+ });
95
+
96
+ const snapshot = serializeCatalog(catalog);
97
+ const json = stringifyCatalogSnapshot(snapshot);
98
+ const deserialized = deserializeCatalog(JSON.parse(json));
99
+
100
+ const deserSeq = deserialized.sequences[seq.stableId];
101
+ expect(deserSeq).toBeDefined();
102
+ expect(deserSeq.minimum_value).toBe(BigInt("-9223372036854775808"));
103
+ expect(deserSeq.maximum_value).toBe(BigInt("9223372036854775807"));
104
+ expect(typeof deserSeq.minimum_value).toBe("bigint");
105
+ expect(typeof deserSeq.maximum_value).toBe("bigint");
106
+ });
107
+
108
+ test("round-trip preserves Aggregate identity_arguments mapping", () => {
109
+ const agg = new Aggregate({
110
+ schema: "public",
111
+ name: "my_agg",
112
+ identity_arguments: " integer, text ",
113
+ kind: "a",
114
+ aggkind: "n",
115
+ num_direct_args: 0,
116
+ return_type: "integer",
117
+ return_type_schema: null,
118
+ parallel_safety: "u",
119
+ is_strict: false,
120
+ transition_function: "my_sfunc",
121
+ state_data_type: "integer",
122
+ state_data_type_schema: null,
123
+ state_data_space: 0,
124
+ final_function: null,
125
+ final_function_extra_args: false,
126
+ final_function_modify: null,
127
+ combine_function: null,
128
+ serial_function: null,
129
+ deserial_function: null,
130
+ initial_condition: "0",
131
+ moving_transition_function: null,
132
+ moving_inverse_function: null,
133
+ moving_state_data_type: null,
134
+ moving_state_data_type_schema: null,
135
+ moving_state_data_space: null,
136
+ moving_final_function: null,
137
+ moving_final_function_extra_args: false,
138
+ moving_final_function_modify: null,
139
+ moving_initial_condition: null,
140
+ sort_operator: null,
141
+ argument_count: 2,
142
+ argument_default_count: 0,
143
+ argument_names: null,
144
+ argument_types: ["integer", "text"],
145
+ all_argument_types: null,
146
+ argument_modes: null,
147
+ argument_defaults: null,
148
+ owner: "postgres",
149
+ comment: null,
150
+ privileges: [],
151
+ });
152
+
153
+ const catalog = new Catalog({
154
+ ...emptyCatalogProps(),
155
+ aggregates: { [agg.stableId]: agg },
156
+ });
157
+
158
+ const snapshot = serializeCatalog(catalog);
159
+ const json = stringifyCatalogSnapshot(snapshot);
160
+ const deserialized = deserializeCatalog(JSON.parse(json));
161
+
162
+ const deserAgg = deserialized.aggregates[agg.stableId];
163
+ expect(deserAgg).toBeDefined();
164
+ expect(deserAgg.identityArguments).toBe("integer, text");
165
+ });
166
+
167
+ test("round-trip preserves depends array", () => {
168
+ const table = new Table({
169
+ schema: "public",
170
+ name: "my_table",
171
+ owner: "postgres",
172
+ comment: null,
173
+ privileges: [],
174
+ columns: [],
175
+ constraints: [],
176
+ persistence: "p",
177
+ row_security: false,
178
+ force_row_security: false,
179
+ has_indexes: false,
180
+ has_rules: false,
181
+ has_triggers: false,
182
+ has_subclasses: false,
183
+ is_populated: true,
184
+ replica_identity: "d",
185
+ is_partition: false,
186
+ options: null,
187
+ partition_bound: null,
188
+ partition_by: null,
189
+ parent_schema: null,
190
+ parent_name: null,
191
+ });
192
+
193
+ const publicSchema = new Schema({
194
+ name: "public",
195
+ owner: "pg_database_owner",
196
+ comment: "standard public schema",
197
+ privileges: [],
198
+ });
199
+
200
+ const depends = [
201
+ {
202
+ dependent_stable_id: table.stableId,
203
+ referenced_stable_id: publicSchema.stableId,
204
+ deptype: "n" as const,
205
+ },
206
+ ];
207
+
208
+ const catalog = new Catalog({
209
+ ...emptyCatalogProps(),
210
+ schemas: { [publicSchema.stableId]: publicSchema },
211
+ tables: { [table.stableId]: table },
212
+ indexableObjects: { [table.stableId]: table },
213
+ depends,
214
+ });
215
+
216
+ const snapshot = serializeCatalog(catalog);
217
+ const json = stringifyCatalogSnapshot(snapshot);
218
+ const deserialized = deserializeCatalog(JSON.parse(json));
219
+
220
+ expect(deserialized.depends).toEqual(depends);
221
+ });
222
+
223
+ test("round-trip preserves indexableObjects from tables and materialized views", () => {
224
+ const table = new Table({
225
+ schema: "public",
226
+ name: "tbl",
227
+ owner: "postgres",
228
+ comment: null,
229
+ privileges: [],
230
+ columns: [],
231
+ constraints: [],
232
+ persistence: "p",
233
+ row_security: false,
234
+ force_row_security: false,
235
+ has_indexes: false,
236
+ has_rules: false,
237
+ has_triggers: false,
238
+ has_subclasses: false,
239
+ is_populated: true,
240
+ replica_identity: "d",
241
+ is_partition: false,
242
+ options: null,
243
+ partition_bound: null,
244
+ partition_by: null,
245
+ parent_schema: null,
246
+ parent_name: null,
247
+ });
248
+
249
+ const catalog = new Catalog({
250
+ ...emptyCatalogProps(),
251
+ tables: { [table.stableId]: table },
252
+ indexableObjects: { [table.stableId]: table },
253
+ });
254
+
255
+ const snapshot = serializeCatalog(catalog);
256
+ const json = stringifyCatalogSnapshot(snapshot);
257
+ const deserialized = deserializeCatalog(JSON.parse(json));
258
+
259
+ expect(Object.keys(deserialized.indexableObjects)).toEqual([
260
+ table.stableId,
261
+ ]);
262
+ });
263
+
264
+ test("deserializeCatalog rejects invalid data", () => {
265
+ expect(() => deserializeCatalog({})).toThrow();
266
+ expect(() => deserializeCatalog("not json")).toThrow();
267
+ expect(() => deserializeCatalog(null)).toThrow();
268
+ expect(() =>
269
+ deserializeCatalog({ version: "not-a-number", currentUser: "x" }),
270
+ ).toThrow();
271
+ });
272
+
273
+ test("deserializeCatalog rejects missing required fields", () => {
274
+ expect(() =>
275
+ deserializeCatalog({
276
+ version: 1,
277
+ currentUser: "x",
278
+ }),
279
+ ).toThrow();
280
+ });
281
+
282
+ test("createPlan accepts Catalog directly as source", async () => {
283
+ const { createPlan } = await import("./plan/create.ts");
284
+
285
+ const source = await createEmptyCatalog(160000, "postgres");
286
+ const target = await createEmptyCatalog(160000, "postgres");
287
+
288
+ const result = await createPlan(source, target);
289
+ expect(result).toBeNull();
290
+ });
291
+
292
+ test("createPlan with null source produces plan when target has objects", async () => {
293
+ const { createPlan } = await import("./plan/create.ts");
294
+
295
+ const publicSchema = new Schema({
296
+ name: "public",
297
+ owner: "pg_database_owner",
298
+ comment: "standard public schema",
299
+ privileges: [],
300
+ });
301
+
302
+ const mySchema = new Schema({
303
+ name: "myschema",
304
+ owner: "postgres",
305
+ comment: null,
306
+ privileges: [],
307
+ });
308
+
309
+ const target = new Catalog({
310
+ ...emptyCatalogProps(),
311
+ schemas: {
312
+ [publicSchema.stableId]: publicSchema,
313
+ [mySchema.stableId]: mySchema,
314
+ },
315
+ });
316
+
317
+ const result = await createPlan(null, target);
318
+ expect(result).not.toBeNull();
319
+ expect(result?.plan.statements.length).toBeGreaterThan(0);
320
+ });
321
+
322
+ test("createPlan with filter DSL without cascade keeps dependents of excluded changes", async () => {
323
+ const { createPlan } = await import("./plan/create.ts");
324
+
325
+ const authSchema = new Schema({
326
+ name: "auth",
327
+ owner: "postgres",
328
+ comment: null,
329
+ privileges: [],
330
+ });
331
+ const publicSchema = new Schema({
332
+ name: "public",
333
+ owner: "postgres",
334
+ comment: null,
335
+ privileges: [],
336
+ });
337
+ const postgresRole = new Role({
338
+ name: "postgres",
339
+ is_superuser: true,
340
+ can_inherit: true,
341
+ can_create_roles: true,
342
+ can_create_databases: true,
343
+ can_login: true,
344
+ can_replicate: true,
345
+ connection_limit: null,
346
+ can_bypass_rls: true,
347
+ config: null,
348
+ comment: null,
349
+ members: [],
350
+ default_privileges: [],
351
+ });
352
+ const authUidProc = new Procedure({
353
+ schema: "auth",
354
+ name: "uid",
355
+ kind: "f",
356
+ return_type: "uuid",
357
+ return_type_schema: "pg_catalog",
358
+ language: "sql",
359
+ security_definer: false,
360
+ volatility: "s",
361
+ parallel_safety: "s",
362
+ is_strict: true,
363
+ leakproof: false,
364
+ returns_set: false,
365
+ argument_count: 0,
366
+ argument_default_count: 0,
367
+ argument_names: null,
368
+ argument_types: null,
369
+ all_argument_types: null,
370
+ argument_modes: null,
371
+ argument_defaults: null,
372
+ source_code: null,
373
+ definition: "CREATE FUNCTION auth.uid() RETURNS uuid ...",
374
+ binary_path: null,
375
+ sql_body: null,
376
+ config: null,
377
+ owner: "postgres",
378
+ execution_cost: 0,
379
+ result_rows: 0,
380
+ comment: null,
381
+ privileges: [],
382
+ });
383
+ const accountsTable = new Table({
384
+ schema: "public",
385
+ name: "accounts",
386
+ owner: "postgres",
387
+ comment: null,
388
+ privileges: [],
389
+ columns: [],
390
+ constraints: [],
391
+ persistence: "p",
392
+ row_security: true,
393
+ force_row_security: false,
394
+ has_indexes: false,
395
+ has_rules: false,
396
+ has_triggers: false,
397
+ has_subclasses: false,
398
+ is_populated: true,
399
+ replica_identity: "d",
400
+ is_partition: false,
401
+ options: null,
402
+ partition_bound: null,
403
+ partition_by: null,
404
+ parent_schema: null,
405
+ parent_name: null,
406
+ });
407
+ const accountsPolicy = new RlsPolicy({
408
+ schema: "public",
409
+ name: "accounts_select_policy",
410
+ table_name: "accounts",
411
+ command: "r",
412
+ permissive: true,
413
+ roles: ["authenticated"],
414
+ using_expression: "auth.uid() = user_id",
415
+ with_check_expression: null,
416
+ owner: "postgres",
417
+ comment: null,
418
+ });
419
+
420
+ const target = new Catalog({
421
+ ...emptyCatalogProps(),
422
+ roles: { [postgresRole.stableId]: postgresRole },
423
+ schemas: {
424
+ [authSchema.stableId]: authSchema,
425
+ [publicSchema.stableId]: publicSchema,
426
+ },
427
+ procedures: { [authUidProc.stableId]: authUidProc },
428
+ tables: { [accountsTable.stableId]: accountsTable },
429
+ rlsPolicies: { [accountsPolicy.stableId]: accountsPolicy },
430
+ indexableObjects: { [accountsTable.stableId]: accountsTable },
431
+ depends: [
432
+ {
433
+ dependent_stable_id: accountsPolicy.stableId,
434
+ referenced_stable_id: authUidProc.stableId,
435
+ deptype: "n",
436
+ },
437
+ ],
438
+ });
439
+
440
+ // Filter out auth schema (no cascade): procedure is excluded but policy stays
441
+ const resultNoCascade = await createPlan(null, target, {
442
+ filter: { not: { schema: ["auth"] } },
443
+ });
444
+ expect(resultNoCascade).not.toBeNull();
445
+ if (resultNoCascade) {
446
+ const policyChangesNoCascade = resultNoCascade.sortedChanges.filter(
447
+ (c) => c.objectType === "rls_policy",
448
+ );
449
+ expect(policyChangesNoCascade.length).toBe(1);
450
+ }
451
+
452
+ // Filter out auth schema with cascade: true: policy is also excluded (depends on auth.uid())
453
+ const resultCascade = await createPlan(null, target, {
454
+ filter: { not: { schema: ["auth"] }, cascade: true },
455
+ });
456
+ expect(resultCascade).not.toBeNull();
457
+ if (resultCascade) {
458
+ const policyChangesCascade = resultCascade.sortedChanges.filter(
459
+ (c) => c.objectType === "rls_policy",
460
+ );
461
+ expect(policyChangesCascade.length).toBe(0);
462
+ }
463
+ });
464
+ });