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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/README.md +40 -23
  2. package/dist/cli/app.js +26 -3
  3. package/dist/cli/bin/cli.js +5 -0
  4. package/dist/cli/commands/catalog-export.d.ts +5 -0
  5. package/dist/cli/commands/catalog-export.js +64 -0
  6. package/dist/cli/commands/declarative-apply.d.ts +6 -0
  7. package/dist/cli/commands/declarative-apply.js +288 -0
  8. package/dist/cli/commands/declarative-export.d.ts +5 -0
  9. package/dist/cli/commands/declarative-export.js +245 -0
  10. package/dist/cli/commands/plan.js +19 -6
  11. package/dist/cli/exit-code.d.ts +2 -0
  12. package/dist/cli/exit-code.js +7 -0
  13. package/dist/cli/formatters/tree/tree.js +3 -2
  14. package/dist/cli/utils/apply-display.d.ts +52 -0
  15. package/dist/cli/utils/apply-display.js +183 -0
  16. package/dist/cli/utils/export-display.d.ts +43 -0
  17. package/dist/cli/utils/export-display.js +202 -0
  18. package/dist/cli/utils/resolve-input.d.ts +7 -0
  19. package/dist/cli/utils/resolve-input.js +13 -0
  20. package/dist/core/catalog-export/index.d.ts +11 -0
  21. package/dist/core/catalog-export/index.js +10 -0
  22. package/dist/core/catalog.diff.d.ts +1 -0
  23. package/dist/core/catalog.diff.js +64 -48
  24. package/dist/core/catalog.model.d.ts +14 -1
  25. package/dist/core/catalog.model.js +103 -1
  26. package/dist/core/catalog.snapshot.d.ts +66 -0
  27. package/dist/core/catalog.snapshot.js +206 -0
  28. package/dist/core/declarative-apply/discover-sql.d.ts +18 -0
  29. package/dist/core/declarative-apply/discover-sql.js +86 -0
  30. package/dist/core/declarative-apply/extract-catalog-providers.d.ts +23 -0
  31. package/dist/core/declarative-apply/extract-catalog-providers.js +159 -0
  32. package/dist/core/declarative-apply/index.d.ts +49 -0
  33. package/dist/core/declarative-apply/index.js +134 -0
  34. package/dist/core/declarative-apply/round-apply.d.ts +100 -0
  35. package/dist/core/declarative-apply/round-apply.js +378 -0
  36. package/dist/core/export/file-mapper.d.ts +71 -0
  37. package/dist/core/export/file-mapper.js +474 -0
  38. package/dist/core/export/grouper.d.ts +13 -0
  39. package/dist/core/export/grouper.js +76 -0
  40. package/dist/core/export/index.d.ts +45 -0
  41. package/dist/core/export/index.js +63 -0
  42. package/dist/core/export/types.d.ts +84 -0
  43. package/dist/core/export/types.js +25 -0
  44. package/dist/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  45. package/dist/core/integrations/filter/dsl.d.ts +38 -1
  46. package/dist/core/integrations/filter/dsl.js +20 -2
  47. package/dist/core/integrations/filter/extractors.js +42 -0
  48. package/dist/core/integrations/integration-dsl.d.ts +10 -0
  49. package/dist/core/integrations/supabase.d.ts +8 -0
  50. package/dist/core/integrations/supabase.js +9 -0
  51. package/dist/core/objects/aggregate/aggregate.diff.d.ts +2 -8
  52. package/dist/core/objects/aggregate/aggregate.diff.js +16 -70
  53. package/dist/core/objects/aggregate/aggregate.model.d.ts +8 -8
  54. package/dist/core/objects/aggregate/aggregate.model.js +1 -1
  55. package/dist/core/objects/aggregate/changes/aggregate.create.js +1 -1
  56. package/dist/core/objects/aggregate/changes/aggregate.drop.js +1 -1
  57. package/dist/core/objects/base.privilege-diff.d.ts +38 -13
  58. package/dist/core/objects/base.privilege-diff.js +104 -22
  59. package/dist/core/objects/base.privilege.d.ts +1 -0
  60. package/dist/core/objects/base.privilege.js +9 -2
  61. package/dist/core/objects/collation/collation.diff.d.ts +2 -3
  62. package/dist/core/objects/diff-context.d.ts +15 -0
  63. package/dist/core/objects/diff-context.js +1 -0
  64. package/dist/core/objects/domain/changes/domain.create.js +4 -2
  65. package/dist/core/objects/domain/domain.diff.d.ts +2 -8
  66. package/dist/core/objects/domain/domain.diff.js +16 -77
  67. package/dist/core/objects/domain/domain.model.js +1 -1
  68. package/dist/core/objects/event-trigger/event-trigger.diff.d.ts +2 -3
  69. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.d.ts +2 -8
  70. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.js +13 -77
  71. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +2 -2
  72. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.d.ts +2 -8
  73. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -77
  74. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +1 -1
  75. package/dist/core/objects/foreign-data-wrapper/server/server.diff.d.ts +2 -8
  76. package/dist/core/objects/foreign-data-wrapper/server/server.diff.js +13 -77
  77. package/dist/core/objects/language/language.diff.d.ts +2 -5
  78. package/dist/core/objects/language/language.diff.js +7 -39
  79. package/dist/core/objects/materialized-view/materialized-view.diff.d.ts +2 -8
  80. package/dist/core/objects/materialized-view/materialized-view.diff.js +16 -158
  81. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +3 -3
  82. package/dist/core/objects/materialized-view/materialized-view.model.js +1 -1
  83. package/dist/core/objects/procedure/changes/procedure.alter.js +12 -12
  84. package/dist/core/objects/procedure/procedure.diff.d.ts +2 -8
  85. package/dist/core/objects/procedure/procedure.diff.js +16 -77
  86. package/dist/core/objects/procedure/procedure.model.d.ts +9 -9
  87. package/dist/core/objects/procedure/procedure.model.js +1 -1
  88. package/dist/core/objects/publication/changes/publication.alter.d.ts +0 -9
  89. package/dist/core/objects/publication/changes/publication.alter.js +0 -14
  90. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -2
  91. package/dist/core/objects/publication/publication.diff.d.ts +2 -3
  92. package/dist/core/objects/publication/publication.diff.js +8 -13
  93. package/dist/core/objects/rls-policy/changes/rls-policy.alter.js +3 -3
  94. package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
  95. package/dist/core/objects/role/role.diff.js +22 -1
  96. package/dist/core/objects/role/role.model.d.ts +4 -3
  97. package/dist/core/objects/role/role.model.js +118 -12
  98. package/dist/core/objects/rule/rule.model.d.ts +1 -1
  99. package/dist/core/objects/schema/schema.diff.d.ts +2 -8
  100. package/dist/core/objects/schema/schema.diff.js +16 -77
  101. package/dist/core/objects/schema/schema.model.js +1 -1
  102. package/dist/core/objects/sequence/sequence.diff.d.ts +2 -8
  103. package/dist/core/objects/sequence/sequence.diff.js +16 -79
  104. package/dist/core/objects/sequence/sequence.model.js +1 -1
  105. package/dist/core/objects/subscription/subscription.diff.d.ts +2 -3
  106. package/dist/core/objects/table/changes/table.create.js +3 -0
  107. package/dist/core/objects/table/table.diff.d.ts +2 -8
  108. package/dist/core/objects/table/table.diff.js +26 -157
  109. package/dist/core/objects/table/table.model.d.ts +23 -22
  110. package/dist/core/objects/table/table.model.js +1 -1
  111. package/dist/core/objects/trigger/changes/trigger.create.js +2 -4
  112. package/dist/core/objects/trigger/trigger.model.d.ts +8 -0
  113. package/dist/core/objects/trigger/trigger.model.js +11 -0
  114. package/dist/core/objects/type/composite-type/composite-type.diff.d.ts +2 -8
  115. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -77
  116. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +3 -3
  117. package/dist/core/objects/type/composite-type/composite-type.model.js +2 -1
  118. package/dist/core/objects/type/enum/enum.diff.d.ts +2 -8
  119. package/dist/core/objects/type/enum/enum.diff.js +25 -112
  120. package/dist/core/objects/type/enum/enum.model.js +1 -1
  121. package/dist/core/objects/type/range/changes/range.create.js +6 -3
  122. package/dist/core/objects/type/range/range.diff.d.ts +2 -8
  123. package/dist/core/objects/type/range/range.diff.js +16 -77
  124. package/dist/core/objects/type/range/range.model.js +1 -1
  125. package/dist/core/objects/view/view.diff.d.ts +2 -8
  126. package/dist/core/objects/view/view.diff.js +16 -158
  127. package/dist/core/objects/view/view.model.d.ts +18 -4
  128. package/dist/core/objects/view/view.model.js +3 -13
  129. package/dist/core/plan/apply.js +9 -26
  130. package/dist/core/plan/create.d.ts +19 -6
  131. package/dist/core/plan/create.js +134 -174
  132. package/dist/core/plan/serialize.js +16 -4
  133. package/dist/core/plan/sql-format/fixtures.js +3 -5
  134. package/dist/core/plan/sql-format/keyword-case.js +26 -1
  135. package/dist/core/plan/ssl-config.d.ts +32 -0
  136. package/dist/core/plan/ssl-config.js +115 -0
  137. package/dist/core/plan/types.d.ts +6 -0
  138. package/dist/core/postgres-config.d.ts +14 -0
  139. package/dist/core/postgres-config.js +53 -2
  140. package/dist/core/sort/graph-builder.js +10 -0
  141. package/dist/core/sort/logical-sort.js +31 -23
  142. package/dist/core/test-utils/assert-valid-sql.d.ts +10 -0
  143. package/dist/core/test-utils/assert-valid-sql.js +19 -0
  144. package/dist/index.d.ts +6 -0
  145. package/dist/index.js +6 -1
  146. package/package.json +21 -4
  147. package/src/cli/app.ts +27 -3
  148. package/src/cli/bin/cli.ts +6 -0
  149. package/src/cli/commands/catalog-export.ts +78 -0
  150. package/src/cli/commands/declarative-apply.diagnostics.test.ts +77 -0
  151. package/src/cli/commands/declarative-apply.ts +380 -0
  152. package/src/cli/commands/declarative-export.ts +330 -0
  153. package/src/cli/commands/plan.ts +28 -7
  154. package/src/cli/exit-code.test.ts +19 -0
  155. package/src/cli/exit-code.ts +7 -0
  156. package/src/cli/formatters/tree/tree.ts +3 -2
  157. package/src/cli/utils/apply-display.test.ts +348 -0
  158. package/src/cli/utils/apply-display.ts +238 -0
  159. package/src/cli/utils/export-display.test.ts +103 -0
  160. package/src/cli/utils/export-display.ts +275 -0
  161. package/src/cli/utils/integrations.test.ts +44 -0
  162. package/src/cli/utils/resolve-input.test.ts +38 -0
  163. package/src/cli/utils/resolve-input.ts +17 -0
  164. package/src/core/catalog-export/index.ts +20 -0
  165. package/src/core/catalog.diff.ts +79 -78
  166. package/src/core/catalog.model.test.ts +122 -0
  167. package/src/core/catalog.model.ts +127 -1
  168. package/src/core/catalog.snapshot.test.ts +464 -0
  169. package/src/core/catalog.snapshot.ts +289 -0
  170. package/src/core/declarative-apply/discover-sql.test.ts +103 -0
  171. package/src/core/declarative-apply/discover-sql.ts +107 -0
  172. package/src/core/declarative-apply/extract-catalog-providers.ts +220 -0
  173. package/src/core/declarative-apply/index.test.ts +67 -0
  174. package/src/core/declarative-apply/index.ts +205 -0
  175. package/src/core/declarative-apply/round-apply.test.ts +504 -0
  176. package/src/core/declarative-apply/round-apply.ts +562 -0
  177. package/src/core/expand-replace-dependencies.test.ts +70 -0
  178. package/src/core/export/file-mapper.test.ts +816 -0
  179. package/src/core/export/file-mapper.ts +574 -0
  180. package/src/core/export/grouper.ts +108 -0
  181. package/src/core/export/index.ts +129 -0
  182. package/src/core/export/types.ts +104 -0
  183. package/src/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  184. package/src/core/integrations/filter/dsl.test.ts +211 -0
  185. package/src/core/integrations/filter/dsl.ts +65 -3
  186. package/src/core/integrations/filter/extractors.test.ts +244 -0
  187. package/src/core/integrations/filter/extractors.ts +42 -0
  188. package/src/core/integrations/integration-dsl.ts +10 -0
  189. package/src/core/integrations/serialize/dsl.test.ts +91 -0
  190. package/src/core/integrations/supabase.ts +9 -0
  191. package/src/core/objects/aggregate/aggregate.diff.ts +39 -95
  192. package/src/core/objects/aggregate/aggregate.model.ts +1 -1
  193. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +3 -1
  194. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +5 -2
  195. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +6 -3
  196. package/src/core/objects/aggregate/changes/aggregate.create.ts +1 -1
  197. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +7 -3
  198. package/src/core/objects/aggregate/changes/aggregate.drop.ts +1 -1
  199. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +9 -3
  200. package/src/core/objects/base.privilege-diff.ts +178 -30
  201. package/src/core/objects/base.privilege.ts +9 -2
  202. package/src/core/objects/collation/changes/collation.alter.test.ts +7 -2
  203. package/src/core/objects/collation/changes/collation.create.test.ts +7 -2
  204. package/src/core/objects/collation/changes/collation.drop.test.ts +4 -1
  205. package/src/core/objects/collation/collation.diff.test.ts +9 -12
  206. package/src/core/objects/collation/collation.diff.ts +2 -1
  207. package/src/core/objects/diff-context.ts +16 -0
  208. package/src/core/objects/domain/changes/domain.alter.test.ts +28 -9
  209. package/src/core/objects/domain/changes/domain.create.test.ts +32 -2
  210. package/src/core/objects/domain/changes/domain.create.ts +7 -1
  211. package/src/core/objects/domain/changes/domain.drop.test.ts +4 -1
  212. package/src/core/objects/domain/domain.diff.ts +39 -102
  213. package/src/core/objects/domain/domain.model.ts +1 -1
  214. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +10 -3
  215. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +4 -1
  216. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +4 -1
  217. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +12 -7
  218. package/src/core/objects/event-trigger/event-trigger.diff.ts +2 -1
  219. package/src/core/objects/extension/changes/extension.alter.test.ts +7 -2
  220. package/src/core/objects/extension/changes/extension.create.test.ts +4 -1
  221. package/src/core/objects/extension/changes/extension.drop.test.ts +4 -1
  222. package/src/core/objects/extension/extension.model.test.ts +98 -0
  223. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +16 -5
  224. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +51 -16
  225. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +4 -1
  226. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +111 -4
  227. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +31 -101
  228. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +2 -2
  229. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +46 -15
  230. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +13 -4
  231. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +4 -1
  232. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +39 -102
  233. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +1 -1
  234. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +22 -7
  235. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +19 -6
  236. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +4 -1
  237. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +95 -0
  238. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +31 -101
  239. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +13 -4
  240. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +16 -5
  241. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +10 -3
  242. package/src/core/objects/index/changes/index.alter.test.ts +13 -4
  243. package/src/core/objects/index/changes/index.create.test.ts +4 -1
  244. package/src/core/objects/index/changes/index.drop.test.ts +4 -1
  245. package/src/core/objects/language/changes/language.alter.test.ts +4 -1
  246. package/src/core/objects/language/changes/language.create.test.ts +4 -1
  247. package/src/core/objects/language/changes/language.drop.test.ts +4 -1
  248. package/src/core/objects/language/language.diff.test.ts +86 -4
  249. package/src/core/objects/language/language.diff.ts +17 -49
  250. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +10 -3
  251. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +7 -2
  252. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +4 -1
  253. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +162 -0
  254. package/src/core/objects/materialized-view/materialized-view.diff.ts +41 -191
  255. package/src/core/objects/materialized-view/materialized-view.model.ts +1 -1
  256. package/src/core/objects/procedure/changes/procedure.alter.test.ts +121 -49
  257. package/src/core/objects/procedure/changes/procedure.alter.ts +15 -12
  258. package/src/core/objects/procedure/changes/procedure.create.test.ts +4 -1
  259. package/src/core/objects/procedure/changes/procedure.drop.test.ts +7 -2
  260. package/src/core/objects/procedure/procedure.diff.ts +39 -102
  261. package/src/core/objects/procedure/procedure.model.ts +1 -1
  262. package/src/core/objects/publication/changes/publication.alter.test.ts +15 -21
  263. package/src/core/objects/publication/changes/publication.alter.ts +0 -18
  264. package/src/core/objects/publication/changes/publication.comment.test.ts +5 -2
  265. package/src/core/objects/publication/changes/publication.create.test.ts +5 -2
  266. package/src/core/objects/publication/changes/publication.drop.test.ts +3 -1
  267. package/src/core/objects/publication/changes/publication.types.ts +0 -2
  268. package/src/core/objects/publication/publication.diff.test.ts +24 -19
  269. package/src/core/objects/publication/publication.diff.ts +9 -15
  270. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +31 -14
  271. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +3 -3
  272. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +10 -3
  273. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +4 -1
  274. package/src/core/objects/role/changes/role.alter.test.ts +31 -15
  275. package/src/core/objects/role/changes/role.create.test.ts +6 -2
  276. package/src/core/objects/role/changes/role.drop.test.ts +4 -1
  277. package/src/core/objects/role/role.diff.test.ts +235 -0
  278. package/src/core/objects/role/role.diff.ts +21 -1
  279. package/src/core/objects/role/role.model.ts +122 -14
  280. package/src/core/objects/rule/changes/rule.alter.test.ts +7 -3
  281. package/src/core/objects/rule/changes/rule.comment.test.ts +5 -2
  282. package/src/core/objects/rule/changes/rule.create.test.ts +6 -2
  283. package/src/core/objects/rule/changes/rule.drop.test.ts +3 -1
  284. package/src/core/objects/schema/changes/schema.alter.test.ts +4 -1
  285. package/src/core/objects/schema/changes/schema.create.test.ts +4 -1
  286. package/src/core/objects/schema/changes/schema.drop.test.ts +4 -1
  287. package/src/core/objects/schema/schema.diff.ts +39 -102
  288. package/src/core/objects/schema/schema.model.ts +1 -1
  289. package/src/core/objects/sequence/changes/sequence.alter.test.ts +11 -5
  290. package/src/core/objects/sequence/changes/sequence.create.test.ts +8 -3
  291. package/src/core/objects/sequence/changes/sequence.drop.test.ts +4 -1
  292. package/src/core/objects/sequence/sequence.diff.test.ts +114 -0
  293. package/src/core/objects/sequence/sequence.diff.ts +39 -104
  294. package/src/core/objects/sequence/sequence.model.ts +1 -1
  295. package/src/core/objects/subscription/changes/subscription.alter.test.ts +15 -5
  296. package/src/core/objects/subscription/changes/subscription.comment.test.ts +5 -2
  297. package/src/core/objects/subscription/changes/subscription.create.test.ts +5 -2
  298. package/src/core/objects/subscription/changes/subscription.drop.test.ts +3 -1
  299. package/src/core/objects/subscription/subscription.diff.test.ts +16 -11
  300. package/src/core/objects/subscription/subscription.diff.ts +2 -1
  301. package/src/core/objects/table/changes/table.alter.test.ts +38 -15
  302. package/src/core/objects/table/changes/table.create.test.ts +41 -3
  303. package/src/core/objects/table/changes/table.create.ts +4 -0
  304. package/src/core/objects/table/changes/table.drop.test.ts +3 -1
  305. package/src/core/objects/table/table.diff.test.ts +157 -0
  306. package/src/core/objects/table/table.diff.ts +54 -190
  307. package/src/core/objects/table/table.model.ts +1 -1
  308. package/src/core/objects/trigger/changes/trigger.alter.test.ts +8 -4
  309. package/src/core/objects/trigger/changes/trigger.create.test.ts +5 -1
  310. package/src/core/objects/trigger/changes/trigger.create.ts +7 -4
  311. package/src/core/objects/trigger/changes/trigger.drop.test.ts +5 -1
  312. package/src/core/objects/trigger/trigger.diff.test.ts +1 -0
  313. package/src/core/objects/trigger/trigger.model.ts +12 -0
  314. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +10 -4
  315. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +7 -2
  316. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +4 -1
  317. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +78 -0
  318. package/src/core/objects/type/composite-type/composite-type.diff.ts +39 -101
  319. package/src/core/objects/type/composite-type/composite-type.model.ts +2 -1
  320. package/src/core/objects/type/enum/changes/enum.alter.test.ts +14 -5
  321. package/src/core/objects/type/enum/changes/enum.create.test.ts +4 -1
  322. package/src/core/objects/type/enum/changes/enum.drop.test.ts +4 -1
  323. package/src/core/objects/type/enum/enum.diff.test.ts +181 -0
  324. package/src/core/objects/type/enum/enum.diff.ts +58 -146
  325. package/src/core/objects/type/enum/enum.model.ts +1 -1
  326. package/src/core/objects/type/range/changes/range.alter.test.ts +3 -1
  327. package/src/core/objects/type/range/changes/range.create.test.ts +5 -2
  328. package/src/core/objects/type/range/changes/range.create.ts +6 -2
  329. package/src/core/objects/type/range/changes/range.drop.test.ts +3 -1
  330. package/src/core/objects/type/range/range.diff.test.ts +77 -0
  331. package/src/core/objects/type/range/range.diff.ts +39 -101
  332. package/src/core/objects/type/range/range.model.ts +1 -1
  333. package/src/core/objects/view/changes/view.alter.test.ts +8 -3
  334. package/src/core/objects/view/changes/view.create.test.ts +7 -2
  335. package/src/core/objects/view/changes/view.drop.test.ts +4 -1
  336. package/src/core/objects/view/view.diff.test.ts +82 -0
  337. package/src/core/objects/view/view.diff.ts +41 -191
  338. package/src/core/objects/view/view.model.ts +3 -17
  339. package/src/core/plan/apply.ts +9 -27
  340. package/src/core/plan/create.ts +173 -237
  341. package/src/core/plan/serialize.test.ts +317 -0
  342. package/src/core/plan/serialize.ts +18 -4
  343. package/src/core/plan/sql-format/fixtures.ts +2 -5
  344. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +52 -0
  345. package/src/core/plan/sql-format/format-off.test.ts +14 -17
  346. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +27 -22
  347. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +17 -21
  348. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +25 -20
  349. package/src/core/plan/sql-format/format-pretty-upper.test.ts +23 -20
  350. package/src/core/plan/sql-format/keyword-case.ts +36 -1
  351. package/src/core/plan/ssl-config.ts +172 -0
  352. package/src/core/plan/types.ts +6 -0
  353. package/src/core/postgres-config.ts +71 -2
  354. package/src/core/sort/graph-builder.ts +12 -0
  355. package/src/core/sort/logical-sort.test.ts +371 -0
  356. package/src/core/sort/logical-sort.ts +32 -25
  357. package/src/core/sort/topological-sort.test.ts +275 -0
  358. package/src/core/test-utils/assert-valid-sql.ts +20 -0
  359. package/src/index.ts +26 -2
@@ -0,0 +1,371 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import type { Change } from "../change.types.ts";
3
+ import { logicalSort } from "./logical-sort.ts";
4
+
5
+ function mockChange(
6
+ overrides: Partial<{
7
+ objectType: string;
8
+ operation: string;
9
+ scope: string;
10
+ creates: string[];
11
+ drops: string[];
12
+ requires: string[];
13
+ schema: string | null;
14
+ className: string;
15
+ inSchema: string | null;
16
+ objtype: string;
17
+ grantee: string;
18
+ eventTrigger: { function_schema: string };
19
+ }>,
20
+ ): Change {
21
+ const {
22
+ objectType = "table",
23
+ operation = "create",
24
+ scope = "object",
25
+ creates = [],
26
+ drops = [],
27
+ requires = [],
28
+ schema = "public",
29
+ className = "MockChange",
30
+ inSchema,
31
+ objtype,
32
+ grantee,
33
+ eventTrigger,
34
+ } = overrides;
35
+
36
+ const change: Record<string, unknown> = {
37
+ objectType,
38
+ operation,
39
+ scope,
40
+ creates,
41
+ drops,
42
+ requires,
43
+ };
44
+
45
+ if (objectType === "table") {
46
+ change.table = { schema, name: "t" };
47
+ } else if (objectType === "schema") {
48
+ change.schema = { name: schema ?? "public" };
49
+ } else if (objectType === "role") {
50
+ change.role = { name: "postgres" };
51
+ } else if (objectType === "index") {
52
+ change.index = { schema, name: "idx" };
53
+ }
54
+
55
+ if (inSchema !== undefined) {
56
+ change.inSchema = inSchema;
57
+ }
58
+ if (objtype !== undefined) {
59
+ change.objtype = objtype;
60
+ }
61
+ if (grantee !== undefined) {
62
+ change.grantee = grantee;
63
+ }
64
+ if (eventTrigger !== undefined) {
65
+ change.eventTrigger = eventTrigger;
66
+ }
67
+
68
+ Object.defineProperty(change, "constructor", { value: { name: className } });
69
+ return change as unknown as Change;
70
+ }
71
+
72
+ describe("logicalSort", () => {
73
+ test("returns empty array for empty input", () => {
74
+ expect(logicalSort([])).toEqual([]);
75
+ });
76
+
77
+ test("single change passes through", () => {
78
+ const c = mockChange({ creates: ["table:public.t"] });
79
+ expect(logicalSort([c])).toEqual([c]);
80
+ });
81
+
82
+ describe("comment/privilege on constraint", () => {
83
+ test("CREATE comment on constraint groups with table", () => {
84
+ const tableCreate = mockChange({
85
+ creates: ["table:public.t"],
86
+ });
87
+ const commentOnConstraint = mockChange({
88
+ scope: "comment",
89
+ operation: "create",
90
+ creates: ["comment:constraint:public.t.pk"],
91
+ requires: ["constraint:public.t.pk_name"],
92
+ });
93
+
94
+ const result = logicalSort([commentOnConstraint, tableCreate]);
95
+ expect(result).toHaveLength(2);
96
+ expect(result).toContain(tableCreate);
97
+ expect(result).toContain(commentOnConstraint);
98
+ });
99
+
100
+ test("DROP comment on constraint groups with table", () => {
101
+ const tableDrop = mockChange({
102
+ operation: "drop",
103
+ drops: ["table:public.t"],
104
+ });
105
+ const commentDrop = mockChange({
106
+ scope: "comment",
107
+ operation: "drop",
108
+ creates: [],
109
+ requires: ["constraint:public.t.pk_name"],
110
+ });
111
+
112
+ const result = logicalSort([commentDrop, tableDrop]);
113
+ expect(result).toHaveLength(2);
114
+ });
115
+ });
116
+
117
+ describe("comment/privilege on column", () => {
118
+ test("CREATE comment on column groups with table", () => {
119
+ const tableCreate = mockChange({
120
+ creates: ["table:public.t"],
121
+ });
122
+ const commentOnColumn = mockChange({
123
+ scope: "comment",
124
+ operation: "create",
125
+ creates: ["comment:column:public.t.col"],
126
+ requires: ["column:public.t.col"],
127
+ });
128
+
129
+ const result = logicalSort([commentOnColumn, tableCreate]);
130
+ expect(result).toHaveLength(2);
131
+ });
132
+
133
+ test("DROP comment on column extracts table grouping key", () => {
134
+ const commentDrop = mockChange({
135
+ scope: "comment",
136
+ operation: "drop",
137
+ creates: [],
138
+ requires: ["column:public.t.col"],
139
+ });
140
+ const tableCreate = mockChange({
141
+ creates: ["table:public.t"],
142
+ });
143
+
144
+ const result = logicalSort([commentDrop, tableCreate]);
145
+ expect(result).toHaveLength(2);
146
+ });
147
+ });
148
+
149
+ describe("CREATE/DROP constraint", () => {
150
+ test("CREATE constraint groups with parent table", () => {
151
+ const tableCreate = mockChange({
152
+ creates: ["table:public.t"],
153
+ });
154
+ const constraintCreate = mockChange({
155
+ operation: "create",
156
+ creates: ["constraint:public.t.pk_name"],
157
+ requires: ["table:public.t"],
158
+ });
159
+
160
+ const result = logicalSort([constraintCreate, tableCreate]);
161
+ expect(result).toHaveLength(2);
162
+ });
163
+
164
+ test("DROP constraint groups with parent table", () => {
165
+ const constraintDrop = mockChange({
166
+ operation: "drop",
167
+ drops: ["constraint:public.t.pk_name"],
168
+ requires: ["table:public.t"],
169
+ });
170
+
171
+ const result = logicalSort([constraintDrop]);
172
+ expect(result).toHaveLength(1);
173
+ });
174
+ });
175
+
176
+ describe("default_privilege scope", () => {
177
+ test("groups by role + schema combination", () => {
178
+ const defPriv = mockChange({
179
+ scope: "default_privilege",
180
+ operation: "create",
181
+ creates: ["defacl:public.tables"],
182
+ requires: ["role:postgres", "schema:public"],
183
+ inSchema: "public",
184
+ });
185
+
186
+ const result = logicalSort([defPriv]);
187
+ expect(result).toHaveLength(1);
188
+ expect(result[0]).toBe(defPriv);
189
+ });
190
+
191
+ test("groups by role only when no schema", () => {
192
+ const defPriv = mockChange({
193
+ scope: "default_privilege",
194
+ operation: "create",
195
+ creates: ["defacl:tables"],
196
+ requires: ["role:postgres"],
197
+ inSchema: null,
198
+ });
199
+
200
+ const result = logicalSort([defPriv]);
201
+ expect(result).toHaveLength(1);
202
+ });
203
+ });
204
+
205
+ describe("ALTER with constraints and columns", () => {
206
+ test("ALTER with constraint creates groups with table", () => {
207
+ const alterConstraint = mockChange({
208
+ operation: "alter",
209
+ creates: ["constraint:public.t.fk"],
210
+ requires: ["table:public.t"],
211
+ });
212
+
213
+ const result = logicalSort([alterConstraint]);
214
+ expect(result).toHaveLength(1);
215
+ });
216
+
217
+ test("ALTER with column creates groups with table", () => {
218
+ const alterColumn = mockChange({
219
+ operation: "alter",
220
+ creates: ["column:public.t.new_col"],
221
+ requires: ["table:public.t"],
222
+ });
223
+
224
+ const result = logicalSort([alterColumn]);
225
+ expect(result).toHaveLength(1);
226
+ });
227
+
228
+ test("ALTER with constraint drops groups with table", () => {
229
+ const alterDropConstraint = mockChange({
230
+ operation: "alter",
231
+ drops: ["constraint:public.t.fk"],
232
+ requires: ["table:public.t"],
233
+ });
234
+
235
+ const result = logicalSort([alterDropConstraint]);
236
+ expect(result).toHaveLength(1);
237
+ });
238
+
239
+ test("ALTER with constraint in requires groups with table", () => {
240
+ const alterValidateConstraint = mockChange({
241
+ operation: "alter",
242
+ requires: ["constraint:public.t.pk"],
243
+ });
244
+
245
+ const result = logicalSort([alterValidateConstraint]);
246
+ expect(result).toHaveLength(1);
247
+ });
248
+ });
249
+
250
+ describe("phase ordering", () => {
251
+ test("DROP changes come before CREATE changes", () => {
252
+ const createChange = mockChange({
253
+ operation: "create",
254
+ creates: ["table:public.a"],
255
+ });
256
+ const dropChange = mockChange({
257
+ operation: "drop",
258
+ drops: ["table:public.b"],
259
+ });
260
+
261
+ const result = logicalSort([createChange, dropChange]);
262
+ expect(result[0]).toBe(dropChange);
263
+ expect(result[1]).toBe(createChange);
264
+ });
265
+ });
266
+
267
+ describe("grouping related changes together", () => {
268
+ test("table create + constraint comment sort adjacent", () => {
269
+ const tableCreate = mockChange({
270
+ creates: ["table:public.t"],
271
+ });
272
+ const otherTable = mockChange({
273
+ creates: ["table:public.z"],
274
+ });
275
+ const commentOnConstraint = mockChange({
276
+ scope: "comment",
277
+ operation: "create",
278
+ creates: ["comment:constraint:public.t.pk"],
279
+ requires: ["constraint:public.t.pk_name"],
280
+ });
281
+
282
+ const result = logicalSort([
283
+ otherTable,
284
+ commentOnConstraint,
285
+ tableCreate,
286
+ ]);
287
+ expect(result).toHaveLength(3);
288
+ const tIdx = result.indexOf(tableCreate);
289
+ const cIdx = result.indexOf(commentOnConstraint);
290
+ const zIdx = result.indexOf(otherTable);
291
+ expect(Math.abs(tIdx - cIdx)).toBe(1);
292
+ expect(zIdx).not.toBe(tIdx + 1);
293
+ });
294
+
295
+ test("default_privilege sorts after schemas and roles", () => {
296
+ const schemaCreate = mockChange({
297
+ objectType: "schema",
298
+ operation: "create",
299
+ creates: ["schema:public"],
300
+ schema: "public",
301
+ });
302
+ const roleCreate = mockChange({
303
+ objectType: "role",
304
+ operation: "create",
305
+ creates: ["role:postgres"],
306
+ schema: null,
307
+ });
308
+ const defPriv = mockChange({
309
+ scope: "default_privilege",
310
+ operation: "create",
311
+ creates: ["defacl:public.tables"],
312
+ requires: ["role:postgres", "schema:public"],
313
+ inSchema: "public",
314
+ });
315
+
316
+ const result = logicalSort([defPriv, schemaCreate, roleCreate]);
317
+ expect(result).toHaveLength(3);
318
+ expect(result.indexOf(defPriv)).toBeGreaterThan(
319
+ result.indexOf(schemaCreate),
320
+ );
321
+ });
322
+
323
+ test("default_privilege orders deterministically by objtype then grantee", () => {
324
+ const baseRequires = ["role:postgres", "schema:public"];
325
+ const defPrivTablesAnon = mockChange({
326
+ scope: "default_privilege",
327
+ operation: "create",
328
+ creates: ["defacl:postgres:r:schema:public:grantee:anon"],
329
+ requires: baseRequires,
330
+ inSchema: "public",
331
+ objtype: "r",
332
+ grantee: "anon",
333
+ });
334
+ const defPrivTablesAuthenticated = mockChange({
335
+ scope: "default_privilege",
336
+ operation: "create",
337
+ creates: ["defacl:postgres:r:schema:public:grantee:authenticated"],
338
+ requires: baseRequires,
339
+ inSchema: "public",
340
+ objtype: "r",
341
+ grantee: "authenticated",
342
+ });
343
+ const defPrivSequencesAnon = mockChange({
344
+ scope: "default_privilege",
345
+ operation: "create",
346
+ creates: ["defacl:postgres:S:schema:public:grantee:anon"],
347
+ requires: baseRequires,
348
+ inSchema: "public",
349
+ objtype: "S",
350
+ grantee: "anon",
351
+ });
352
+ const input = [
353
+ defPrivTablesAuthenticated,
354
+ defPrivSequencesAnon,
355
+ defPrivTablesAnon,
356
+ ];
357
+ const result = logicalSort(input);
358
+ expect(result).toHaveLength(3);
359
+ // Result ordered by canonical objtype (n,r,S,f,T) then grantee: r before S, anon before authenticated within r
360
+ const getKey = (c: Change) =>
361
+ `${(c as { objtype: string }).objtype}:${(c as { grantee: string }).grantee}`;
362
+ expect(getKey(result[0])).toBe("r:anon");
363
+ expect(getKey(result[1])).toBe("r:authenticated");
364
+ expect(getKey(result[2])).toBe("S:anon");
365
+ // Determinism: shuffling input must yield the same order
366
+ const shuffled = [...input].sort(() => Math.random() - 0.5);
367
+ const result2 = logicalSort(shuffled);
368
+ expect(result2.map(getKey)).toEqual(result.map(getKey));
369
+ });
370
+ });
371
+ });
@@ -156,6 +156,25 @@ function getMainStableId(change: Change): string | null {
156
156
  return null;
157
157
  }
158
158
 
159
+ // For default_privilege operations: group by role + schema combination (before CREATE so we group and use tiebreaker)
160
+ if (change.scope === "default_privilege") {
161
+ if (change.requires.length > 0) {
162
+ let grantingRole: string | null = null;
163
+ let schemaId: string | null = null;
164
+ for (const id of change.requires) {
165
+ if (id.startsWith("role:")) {
166
+ grantingRole = id;
167
+ } else if (id.startsWith("schema:")) {
168
+ schemaId = id;
169
+ }
170
+ }
171
+ if (schemaId && grantingRole) {
172
+ return `${grantingRole}:${schemaId}`;
173
+ }
174
+ return grantingRole ?? null;
175
+ }
176
+ }
177
+
159
178
  // For CREATE operations: check if creating a constraint (sub-entity of table)
160
179
  if (change.operation === "create" && change.creates.length > 0) {
161
180
  // Iterate through creates to find the first non-metadata stable ID
@@ -195,31 +214,6 @@ function getMainStableId(change: Change): string | null {
195
214
  return change.drops[0] ?? null;
196
215
  }
197
216
 
198
- // For default_privilege operations: group by role + schema combination
199
- // This groups all "FOR ROLE X IN SCHEMA Y" statements together
200
- if (change.scope === "default_privilege") {
201
- if (change.requires.length > 0) {
202
- // Iterate through requires to find role and schema
203
- let grantingRole: string | null = null;
204
- let schemaId: string | null = null;
205
-
206
- for (const id of change.requires) {
207
- if (id.startsWith("role:")) {
208
- grantingRole = id;
209
- } else if (id.startsWith("schema:")) {
210
- schemaId = id;
211
- }
212
- }
213
-
214
- if (schemaId && grantingRole) {
215
- // Create composite key: "role:postgres:schema:public"
216
- return `${grantingRole}:${schemaId}`;
217
- }
218
- // If no schema, just group by role
219
- return grantingRole ?? null;
220
- }
221
- }
222
-
223
217
  // For ALTER operations: check if creating/dropping a constraint
224
218
  // Skip this for privilege/comment/default_privilege scopes (handled above)
225
219
  if (change.operation === "alter") {
@@ -582,6 +576,19 @@ function sortPhase(changes: Change[], phase: Phase): Change[] {
582
576
  return operationOrderA - operationOrderB;
583
577
  }
584
578
 
579
+ // 6b. For default_privilege: deterministic tiebreaker by objtype then grantee (canonical order for objtype)
580
+ if (scopeA === "default_privilege" && scopeB === "default_privilege") {
581
+ const defPrivA = changeA as { objtype: string; grantee: string };
582
+ const defPrivB = changeB as { objtype: string; grantee: string };
583
+ const objtypeOrder = (code: string) =>
584
+ ({ n: 0, r: 1, S: 2, f: 3, T: 4 })[code] ?? 99;
585
+ const objtypeCompare =
586
+ objtypeOrder(defPrivA.objtype) - objtypeOrder(defPrivB.objtype);
587
+ if (objtypeCompare !== 0) return objtypeCompare;
588
+ const granteeCompare = defPrivA.grantee.localeCompare(defPrivB.grantee);
589
+ if (granteeCompare !== 0) return granteeCompare;
590
+ }
591
+
585
592
  // 7. Preserve original order (stability)
586
593
  return a.originalIndex - b.originalIndex;
587
594
  });