@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,211 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import type { Change } from "../../change.types.ts";
3
+ import { compileFilterDSL, evaluatePattern } from "./dsl.ts";
4
+
5
+ const tableCreate = {
6
+ objectType: "table",
7
+ operation: "create",
8
+ scope: "object",
9
+ table: { schema: "public", name: "t" },
10
+ requires: ["schema:public"],
11
+ } as unknown as Change;
12
+
13
+ const viewAlter = {
14
+ objectType: "view",
15
+ operation: "alter",
16
+ scope: "comment",
17
+ view: { schema: "private", name: "v" },
18
+ requires: ["schema:private", "type:auth.users"],
19
+ } as unknown as Change;
20
+
21
+ const roleDrop = {
22
+ objectType: "role",
23
+ operation: "drop",
24
+ scope: "object",
25
+ role: { name: "admin" },
26
+ requires: [],
27
+ } as unknown as Change;
28
+
29
+ describe("evaluatePattern", () => {
30
+ describe("core properties", () => {
31
+ test("type match", () => {
32
+ expect(evaluatePattern({ type: "table" }, tableCreate)).toBe(true);
33
+ });
34
+
35
+ test("type mismatch", () => {
36
+ expect(evaluatePattern({ type: "view" }, tableCreate)).toBe(false);
37
+ });
38
+
39
+ test("operation match", () => {
40
+ expect(evaluatePattern({ operation: "create" }, tableCreate)).toBe(true);
41
+ });
42
+
43
+ test("operation mismatch", () => {
44
+ expect(evaluatePattern({ operation: "drop" }, tableCreate)).toBe(false);
45
+ });
46
+
47
+ test("scope match", () => {
48
+ expect(evaluatePattern({ scope: "object" }, tableCreate)).toBe(true);
49
+ });
50
+
51
+ test("scope mismatch", () => {
52
+ expect(evaluatePattern({ scope: "comment" }, tableCreate)).toBe(false);
53
+ });
54
+
55
+ test("multiple core properties AND together", () => {
56
+ expect(
57
+ evaluatePattern({ type: "table", operation: "create" }, tableCreate),
58
+ ).toBe(true);
59
+ expect(
60
+ evaluatePattern({ type: "table", operation: "drop" }, tableCreate),
61
+ ).toBe(false);
62
+ });
63
+
64
+ test("empty pattern matches everything", () => {
65
+ expect(evaluatePattern({}, tableCreate)).toBe(true);
66
+ expect(evaluatePattern({}, roleDrop)).toBe(true);
67
+ });
68
+ });
69
+
70
+ describe("composition patterns", () => {
71
+ test("not negates a pattern", () => {
72
+ expect(evaluatePattern({ not: { type: "table" } }, tableCreate)).toBe(
73
+ false,
74
+ );
75
+ expect(evaluatePattern({ not: { type: "view" } }, tableCreate)).toBe(
76
+ true,
77
+ );
78
+ });
79
+
80
+ test("and requires all to match", () => {
81
+ expect(
82
+ evaluatePattern(
83
+ { and: [{ type: "table" }, { operation: "create" }] },
84
+ tableCreate,
85
+ ),
86
+ ).toBe(true);
87
+ expect(
88
+ evaluatePattern(
89
+ { and: [{ type: "table" }, { operation: "drop" }] },
90
+ tableCreate,
91
+ ),
92
+ ).toBe(false);
93
+ });
94
+
95
+ test("or requires any to match", () => {
96
+ expect(
97
+ evaluatePattern(
98
+ { or: [{ type: "table" }, { type: "view" }] },
99
+ tableCreate,
100
+ ),
101
+ ).toBe(true);
102
+ expect(
103
+ evaluatePattern(
104
+ { or: [{ type: "role" }, { type: "view" }] },
105
+ tableCreate,
106
+ ),
107
+ ).toBe(false);
108
+ });
109
+
110
+ test("nested composition", () => {
111
+ expect(
112
+ evaluatePattern(
113
+ { not: { or: [{ type: "role" }, { type: "view" }] } },
114
+ tableCreate,
115
+ ),
116
+ ).toBe(true);
117
+ });
118
+ });
119
+
120
+ describe("requiresMatching", () => {
121
+ test("prefix match on requires array", () => {
122
+ expect(
123
+ evaluatePattern({ requiresMatching: ["schema:public"] }, tableCreate),
124
+ ).toBe(true);
125
+ expect(
126
+ evaluatePattern({ requiresMatching: ["schema:"] }, tableCreate),
127
+ ).toBe(true);
128
+ });
129
+
130
+ test("no match when prefix absent", () => {
131
+ expect(
132
+ evaluatePattern({ requiresMatching: ["type:auth."] }, tableCreate),
133
+ ).toBe(false);
134
+ });
135
+
136
+ test("matches when any prefix matches any requires entry", () => {
137
+ expect(
138
+ evaluatePattern({ requiresMatching: ["type:auth."] }, viewAlter),
139
+ ).toBe(true);
140
+ });
141
+
142
+ test("no match when requires is empty", () => {
143
+ expect(evaluatePattern({ requiresMatching: ["schema:"] }, roleDrop)).toBe(
144
+ false,
145
+ );
146
+ });
147
+ });
148
+
149
+ describe("extracted properties", () => {
150
+ test("schema as string exact match", () => {
151
+ expect(evaluatePattern({ schema: "public" }, tableCreate)).toBe(true);
152
+ expect(evaluatePattern({ schema: "private" }, tableCreate)).toBe(false);
153
+ });
154
+
155
+ test("schema as array checks inclusion", () => {
156
+ expect(
157
+ evaluatePattern({ schema: ["public", "private"] }, tableCreate),
158
+ ).toBe(true);
159
+ expect(
160
+ evaluatePattern({ schema: ["private", "auth"] }, tableCreate),
161
+ ).toBe(false);
162
+ });
163
+
164
+ test("null extracted value returns false", () => {
165
+ expect(evaluatePattern({ schema: "public" }, roleDrop)).toBe(false);
166
+ });
167
+
168
+ test("unknown property key is ignored", () => {
169
+ const pattern = { unknownKey: "value" } as Record<string, unknown>;
170
+ expect(
171
+ evaluatePattern(
172
+ pattern as Parameters<typeof evaluatePattern>[0],
173
+ tableCreate,
174
+ ),
175
+ ).toBe(true);
176
+ });
177
+
178
+ test("cascade property is ignored and does not affect match", () => {
179
+ expect(
180
+ evaluatePattern({ type: "table", cascade: true }, tableCreate),
181
+ ).toBe(true);
182
+ expect(
183
+ evaluatePattern({ type: "table", cascade: false }, tableCreate),
184
+ ).toBe(true);
185
+ expect(
186
+ evaluatePattern(
187
+ { not: { schema: "auth" }, cascade: true },
188
+ tableCreate,
189
+ ),
190
+ ).toBe(true);
191
+ });
192
+ });
193
+ });
194
+
195
+ describe("compileFilterDSL", () => {
196
+ test("returns a function that evaluates the pattern", () => {
197
+ const filter = compileFilterDSL({ type: "table" });
198
+ expect(typeof filter).toBe("function");
199
+ expect(filter(tableCreate)).toBe(true);
200
+ expect(filter(roleDrop)).toBe(false);
201
+ });
202
+
203
+ test("works with composition patterns", () => {
204
+ const filter = compileFilterDSL({
205
+ or: [{ type: "table" }, { type: "role" }],
206
+ });
207
+ expect(filter(tableCreate)).toBe(true);
208
+ expect(filter(roleDrop)).toBe(true);
209
+ expect(filter(viewAlter)).toBe(false);
210
+ });
211
+ });
@@ -23,6 +23,30 @@ type ExtractedProperties = {
23
23
  schema?: string | string[];
24
24
  owner?: string | string[];
25
25
  member?: string | string[];
26
+ grantee?: string | string[];
27
+ publication?: string | string[];
28
+ extension?: string | string[];
29
+ procedureLanguage?: string | string[];
30
+ eventTriggerName?: string | string[];
31
+ procedureBinaryPath?: string | string[];
32
+ triggerFunctionSchema?: string | string[];
33
+ };
34
+
35
+ /**
36
+ * Special properties that use custom matching logic (not extractor-based).
37
+ */
38
+ type SpecialProperties = {
39
+ /**
40
+ * Prefix match on `change.requires`.
41
+ * Matches when any element of `change.requires` starts with any of the given prefixes.
42
+ * Useful for excluding changes that depend on specific schemas/types.
43
+ *
44
+ * @example Filter out changes that require auth or extensions types:
45
+ * ```ts
46
+ * { not: { requiresMatching: ["type:auth.", "type:extensions."] } }
47
+ * ```
48
+ */
49
+ requiresMatching?: string[];
26
50
  };
27
51
 
28
52
  /**
@@ -30,7 +54,13 @@ type ExtractedProperties = {
30
54
  * Multiple properties are combined with AND (all must match).
31
55
  */
32
56
  type PropertyPattern = CoreProperties &
33
- ExtractedProperties & {
57
+ ExtractedProperties &
58
+ SpecialProperties & {
59
+ /**
60
+ * When true, exclusions from this filter cascade to dependents (requires/pg_depend).
61
+ * Default false for DSL filters (opt-in).
62
+ */
63
+ cascade?: boolean;
34
64
  // Composition operators are NOT allowed in property patterns
35
65
  and?: never;
36
66
  or?: never;
@@ -44,30 +74,39 @@ type PropertyPattern = CoreProperties &
44
74
  type CompositionPattern =
45
75
  | ({
46
76
  and: FilterPattern[];
77
+ cascade?: boolean;
47
78
  or?: never;
48
79
  not?: never;
49
80
  } & {
50
81
  [K in keyof CoreProperties]?: never;
51
82
  } & {
52
83
  [K in keyof ExtractedProperties]?: never;
84
+ } & {
85
+ [K in keyof SpecialProperties]?: never;
53
86
  })
54
87
  | ({
55
88
  or: FilterPattern[];
89
+ cascade?: boolean;
56
90
  and?: never;
57
91
  not?: never;
58
92
  } & {
59
93
  [K in keyof CoreProperties]?: never;
60
94
  } & {
61
95
  [K in keyof ExtractedProperties]?: never;
96
+ } & {
97
+ [K in keyof SpecialProperties]?: never;
62
98
  })
63
99
  | ({
64
100
  not: FilterPattern;
101
+ cascade?: boolean;
65
102
  and?: never;
66
103
  or?: never;
67
104
  } & {
68
105
  [K in keyof CoreProperties]?: never;
69
106
  } & {
70
107
  [K in keyof ExtractedProperties]?: never;
108
+ } & {
109
+ [K in keyof SpecialProperties]?: never;
71
110
  });
72
111
 
73
112
  /**
@@ -135,10 +174,33 @@ export function evaluatePattern(
135
174
  }
136
175
  }
137
176
 
177
+ // Match requiresMatching (special property - prefix match on change.requires)
178
+ if (pattern.requiresMatching) {
179
+ const requires = change.requires ?? [];
180
+ const prefixes = pattern.requiresMatching;
181
+ const hasMatch = requires.some((r) =>
182
+ prefixes.some((p) => r.startsWith(p)),
183
+ );
184
+ if (!hasMatch) {
185
+ return false;
186
+ }
187
+ }
188
+
138
189
  // Match extracted properties
139
190
  for (const [key, value] of Object.entries(pattern)) {
140
- // Skip composition operators and core properties
141
- if (["and", "or", "not", "type", "operation", "scope"].includes(key)) {
191
+ // Skip composition operators, core properties, special properties, and cascade
192
+ if (
193
+ [
194
+ "and",
195
+ "or",
196
+ "not",
197
+ "type",
198
+ "operation",
199
+ "scope",
200
+ "requiresMatching",
201
+ "cascade",
202
+ ].includes(key)
203
+ ) {
142
204
  continue;
143
205
  }
144
206
 
@@ -0,0 +1,244 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import type { Change } from "../../change.types.ts";
3
+ import { getSchema, PROPERTY_EXTRACTORS } from "./extractors.ts";
4
+
5
+ describe("getSchema", () => {
6
+ test("returns schema for table", () => {
7
+ const change = {
8
+ objectType: "table",
9
+ table: { schema: "public" },
10
+ } as unknown as Change;
11
+ expect(getSchema(change)).toBe("public");
12
+ });
13
+
14
+ test("returns schema for view", () => {
15
+ const change = {
16
+ objectType: "view",
17
+ view: { schema: "app" },
18
+ } as unknown as Change;
19
+ expect(getSchema(change)).toBe("app");
20
+ });
21
+
22
+ test("returns schema for enum", () => {
23
+ const change = {
24
+ objectType: "enum",
25
+ enum: { schema: "types" },
26
+ } as unknown as Change;
27
+ expect(getSchema(change)).toBe("types");
28
+ });
29
+
30
+ test("returns schema.name for schema type", () => {
31
+ const change = {
32
+ objectType: "schema",
33
+ schema: { name: "auth" },
34
+ } as unknown as Change;
35
+ expect(getSchema(change)).toBe("auth");
36
+ });
37
+
38
+ test("returns null for role", () => {
39
+ const change = {
40
+ objectType: "role",
41
+ role: { name: "admin" },
42
+ } as unknown as Change;
43
+ expect(getSchema(change)).toBeNull();
44
+ });
45
+
46
+ test("returns null for publication", () => {
47
+ const change = {
48
+ objectType: "publication",
49
+ publication: { name: "pub1" },
50
+ } as unknown as Change;
51
+ expect(getSchema(change)).toBeNull();
52
+ });
53
+
54
+ test("returns null for language", () => {
55
+ const change = {
56
+ objectType: "language",
57
+ language: { name: "plpgsql" },
58
+ } as unknown as Change;
59
+ expect(getSchema(change)).toBeNull();
60
+ });
61
+ });
62
+
63
+ describe("owner extractor", () => {
64
+ const getOwner = PROPERTY_EXTRACTORS.owner;
65
+
66
+ test("returns owner for table", () => {
67
+ const change = {
68
+ objectType: "table",
69
+ table: { owner: "postgres" },
70
+ } as unknown as Change;
71
+ expect(getOwner(change)).toBe("postgres");
72
+ });
73
+
74
+ test("returns owner for schema", () => {
75
+ const change = {
76
+ objectType: "schema",
77
+ schema: { owner: "admin" },
78
+ } as unknown as Change;
79
+ expect(getOwner(change)).toBe("admin");
80
+ });
81
+
82
+ test("returns role.name for role type", () => {
83
+ const change = {
84
+ objectType: "role",
85
+ role: { name: "supabase_admin" },
86
+ } as unknown as Change;
87
+ expect(getOwner(change)).toBe("supabase_admin");
88
+ });
89
+
90
+ test("returns null for user_mapping", () => {
91
+ const change = { objectType: "user_mapping" } as unknown as Change;
92
+ expect(getOwner(change)).toBeNull();
93
+ });
94
+ });
95
+
96
+ describe("PROPERTY_EXTRACTORS", () => {
97
+ test("has all expected keys", () => {
98
+ const expectedKeys = [
99
+ "schema",
100
+ "owner",
101
+ "member",
102
+ "grantee",
103
+ "publication",
104
+ "extension",
105
+ "procedureLanguage",
106
+ "eventTriggerName",
107
+ "procedureBinaryPath",
108
+ "triggerFunctionSchema",
109
+ ];
110
+ expect(Object.keys(PROPERTY_EXTRACTORS).sort()).toEqual(
111
+ expectedKeys.sort(),
112
+ );
113
+ });
114
+
115
+ describe("member", () => {
116
+ test("returns member for membership scope", () => {
117
+ const change = {
118
+ scope: "membership",
119
+ member: "app_user",
120
+ } as unknown as Change;
121
+ expect(PROPERTY_EXTRACTORS.member(change)).toBe("app_user");
122
+ });
123
+
124
+ test("returns null for non-membership scope", () => {
125
+ const change = { scope: "object" } as unknown as Change;
126
+ expect(PROPERTY_EXTRACTORS.member(change)).toBeNull();
127
+ });
128
+ });
129
+
130
+ describe("grantee", () => {
131
+ test("returns grantee for privilege scope", () => {
132
+ const change = {
133
+ scope: "privilege",
134
+ grantee: "reader",
135
+ } as unknown as Change;
136
+ expect(PROPERTY_EXTRACTORS.grantee(change)).toBe("reader");
137
+ });
138
+
139
+ test("returns null for non-privilege scope", () => {
140
+ const change = { scope: "object" } as unknown as Change;
141
+ expect(PROPERTY_EXTRACTORS.grantee(change)).toBeNull();
142
+ });
143
+ });
144
+
145
+ describe("publication", () => {
146
+ test("returns name for publication type", () => {
147
+ const change = {
148
+ objectType: "publication",
149
+ publication: { name: "my_pub" },
150
+ } as unknown as Change;
151
+ expect(PROPERTY_EXTRACTORS.publication(change)).toBe("my_pub");
152
+ });
153
+
154
+ test("returns null for non-publication type", () => {
155
+ const change = { objectType: "table" } as unknown as Change;
156
+ expect(PROPERTY_EXTRACTORS.publication(change)).toBeNull();
157
+ });
158
+ });
159
+
160
+ describe("extension", () => {
161
+ test("returns name for extension type", () => {
162
+ const change = {
163
+ objectType: "extension",
164
+ extension: { name: "pgcrypto" },
165
+ } as unknown as Change;
166
+ expect(PROPERTY_EXTRACTORS.extension(change)).toBe("pgcrypto");
167
+ });
168
+
169
+ test("returns null for non-extension type", () => {
170
+ const change = { objectType: "table" } as unknown as Change;
171
+ expect(PROPERTY_EXTRACTORS.extension(change)).toBeNull();
172
+ });
173
+ });
174
+
175
+ describe("procedureLanguage", () => {
176
+ test("returns language for procedure type", () => {
177
+ const change = {
178
+ objectType: "procedure",
179
+ procedure: { language: "plpgsql" },
180
+ } as unknown as Change;
181
+ expect(PROPERTY_EXTRACTORS.procedureLanguage(change)).toBe("plpgsql");
182
+ });
183
+
184
+ test("returns null for non-procedure type", () => {
185
+ const change = { objectType: "table" } as unknown as Change;
186
+ expect(PROPERTY_EXTRACTORS.procedureLanguage(change)).toBeNull();
187
+ });
188
+ });
189
+
190
+ describe("eventTriggerName", () => {
191
+ test("returns name for event_trigger type", () => {
192
+ const change = {
193
+ objectType: "event_trigger",
194
+ eventTrigger: { name: "my_trigger" },
195
+ } as unknown as Change;
196
+ expect(PROPERTY_EXTRACTORS.eventTriggerName(change)).toBe("my_trigger");
197
+ });
198
+
199
+ test("returns null for non-event_trigger type", () => {
200
+ const change = { objectType: "table" } as unknown as Change;
201
+ expect(PROPERTY_EXTRACTORS.eventTriggerName(change)).toBeNull();
202
+ });
203
+ });
204
+
205
+ describe("procedureBinaryPath", () => {
206
+ test("returns binary_path for procedure type", () => {
207
+ const change = {
208
+ objectType: "procedure",
209
+ procedure: { binary_path: "/usr/bin/pg" },
210
+ } as unknown as Change;
211
+ expect(PROPERTY_EXTRACTORS.procedureBinaryPath(change)).toBe(
212
+ "/usr/bin/pg",
213
+ );
214
+ });
215
+
216
+ test("returns null when binary_path is undefined", () => {
217
+ const change = {
218
+ objectType: "procedure",
219
+ procedure: {},
220
+ } as unknown as Change;
221
+ expect(PROPERTY_EXTRACTORS.procedureBinaryPath(change)).toBeNull();
222
+ });
223
+
224
+ test("returns null for non-procedure type", () => {
225
+ const change = { objectType: "table" } as unknown as Change;
226
+ expect(PROPERTY_EXTRACTORS.procedureBinaryPath(change)).toBeNull();
227
+ });
228
+ });
229
+
230
+ describe("triggerFunctionSchema", () => {
231
+ test("returns function_schema for trigger type", () => {
232
+ const change = {
233
+ objectType: "trigger",
234
+ trigger: { function_schema: "public" },
235
+ } as unknown as Change;
236
+ expect(PROPERTY_EXTRACTORS.triggerFunctionSchema(change)).toBe("public");
237
+ });
238
+
239
+ test("returns null for non-trigger type", () => {
240
+ const change = { objectType: "table" } as unknown as Change;
241
+ expect(PROPERTY_EXTRACTORS.triggerFunctionSchema(change)).toBeNull();
242
+ });
243
+ });
244
+ });
@@ -18,6 +18,48 @@ export const PROPERTY_EXTRACTORS: Record<string, PropertyExtractor> = {
18
18
  }
19
19
  return null;
20
20
  },
21
+ grantee: (change: Change) => {
22
+ if (change.scope === "privilege" && "grantee" in change) {
23
+ return change.grantee;
24
+ }
25
+ return null;
26
+ },
27
+ publication: (change: Change) => {
28
+ if (change.objectType === "publication") {
29
+ return change.publication.name;
30
+ }
31
+ return null;
32
+ },
33
+ extension: (change: Change) => {
34
+ if (change.objectType === "extension") {
35
+ return change.extension.name;
36
+ }
37
+ return null;
38
+ },
39
+ procedureLanguage: (change: Change) => {
40
+ if (change.objectType === "procedure") {
41
+ return change.procedure.language;
42
+ }
43
+ return null;
44
+ },
45
+ eventTriggerName: (change: Change) => {
46
+ if (change.objectType === "event_trigger") {
47
+ return change.eventTrigger.name;
48
+ }
49
+ return null;
50
+ },
51
+ procedureBinaryPath: (change: Change) => {
52
+ if (change.objectType === "procedure") {
53
+ return change.procedure.binary_path ?? null;
54
+ }
55
+ return null;
56
+ },
57
+ triggerFunctionSchema: (change: Change) => {
58
+ if (change.objectType === "trigger") {
59
+ return change.trigger.function_schema;
60
+ }
61
+ return null;
62
+ },
21
63
  };
22
64
 
23
65
  export function getSchema(change: Change) {
@@ -4,6 +4,7 @@
4
4
  * Combines filter and serialization DSLs into a single serializable structure.
5
5
  */
6
6
 
7
+ import type { CatalogSnapshot } from "../catalog.snapshot.ts";
7
8
  import type { FilterDSL } from "./filter/dsl.ts";
8
9
  import type { SerializeDSL } from "./serialize/dsl.ts";
9
10
 
@@ -21,4 +22,13 @@ export type IntegrationDSL = {
21
22
  * If not provided, changes are serialized with default options.
22
23
  */
23
24
  serialize?: SerializeDSL;
25
+ /**
26
+ * Baseline catalog snapshot for this integration.
27
+ *
28
+ * When `--source` is omitted, this snapshot is deserialized and used as the
29
+ * source catalog instead of `createEmptyCatalog`. This lets integrations
30
+ * define what "empty" means for their platform (e.g. Supabase ships with
31
+ * pre-existing schemas, extensions, and roles).
32
+ */
33
+ emptyCatalog?: CatalogSnapshot;
24
34
  };