@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
@@ -1,4 +1,8 @@
1
- import { isUserDefinedTypeSchema, stableId } from "../../utils.ts";
1
+ import {
2
+ isUserDefinedTypeSchema,
3
+ parseTypeString,
4
+ stableId,
5
+ } from "../../utils.ts";
2
6
  import type { Domain } from "../domain.model.ts";
3
7
  import { CreateDomainChange } from "./domain.base.ts";
4
8
 
@@ -75,7 +79,9 @@ export class CreateDomain extends CreateDomainChange {
75
79
 
76
80
  // Base type (use formatted string for type+typmod and add schema if needed)
77
81
  let baseType = this.domain.base_type_str as string;
82
+ const alreadyQualified = parseTypeString(baseType);
78
83
  if (
84
+ !alreadyQualified &&
79
85
  this.domain.base_type_schema &&
80
86
  this.domain.base_type_schema !== "pg_catalog"
81
87
  ) {
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Domain } from "../domain.model.ts";
3
4
  import { DropDomain } from "./domain.drop.ts";
4
5
 
5
6
  describe("domain", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const domain = new Domain({
8
9
  schema: "public",
9
10
  name: "test_domain",
@@ -25,6 +26,8 @@ describe("domain", () => {
25
26
  domain,
26
27
  });
27
28
 
29
+ await assertValidSql(change.serialize());
30
+
28
31
  expect(change.serialize()).toBe("DROP DOMAIN public.test_domain");
29
32
  });
30
33
  });
@@ -1,11 +1,10 @@
1
- import type { DefaultPrivilegeState } from "../base.default-privileges.ts";
2
1
  import { diffObjects } from "../base.diff.ts";
3
2
  import {
4
3
  diffPrivileges,
4
+ emitObjectPrivilegeChanges,
5
5
  filterPublicBuiltInDefaults,
6
- groupPrivilegesByGrantable,
7
6
  } from "../base.privilege-diff.ts";
8
- import type { Role } from "../role/role.model.ts";
7
+ import type { ObjectDiffContext } from "../diff-context.ts";
9
8
  import {
10
9
  AlterDomainAddConstraint,
11
10
  AlterDomainChangeOwner,
@@ -39,12 +38,10 @@ import type { Domain } from "./domain.model.ts";
39
38
  * @returns A list of changes to apply to main to make it match branch.
40
39
  */
41
40
  export function diffDomains(
42
- ctx: {
43
- version: number;
44
- currentUser: string;
45
- defaultPrivilegeState: DefaultPrivilegeState;
46
- mainRoles: Record<string, Role>;
47
- },
41
+ ctx: Pick<
42
+ ObjectDiffContext,
43
+ "version" | "currentUser" | "defaultPrivilegeState"
44
+ >,
48
45
  main: Record<string, Domain>,
49
46
  branch: Record<string, Domain>,
50
47
  ): DomainChange[] {
@@ -99,6 +96,10 @@ export function diffDomains(
99
96
  "domain",
100
97
  newDomain.schema ?? "",
101
98
  );
99
+ const creatorFilteredDefaults =
100
+ newDomain.owner !== ctx.currentUser
101
+ ? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
102
+ : effectiveDefaults;
102
103
  // Filter out PUBLIC's built-in default USAGE privilege (PostgreSQL grants it automatically)
103
104
  // Reference: https://www.postgresql.org/docs/17/ddl-priv.html Table 5.2
104
105
  // This prevents generating unnecessary "GRANT USAGE TO PUBLIC" statements
@@ -109,57 +110,25 @@ export function diffDomains(
109
110
  // Filter out owner privileges - owner always has ALL privileges implicitly
110
111
  // and shouldn't be compared. Use the domain owner as the reference.
111
112
  const privilegeResults = diffPrivileges(
112
- effectiveDefaults,
113
+ filterPublicBuiltInDefaults("domain", creatorFilteredDefaults),
113
114
  desiredPrivileges,
114
115
  newDomain.owner,
115
- ctx.mainRoles,
116
116
  );
117
117
 
118
- // Generate grant changes
119
- for (const [grantee, result] of privilegeResults) {
120
- if (result.grants.length > 0) {
121
- const grantGroups = groupPrivilegesByGrantable(result.grants);
122
- for (const [grantable, list] of grantGroups) {
123
- void grantable;
124
- changes.push(
125
- new GrantDomainPrivileges({
126
- domain: newDomain,
127
- grantee,
128
- privileges: list,
129
- version: ctx.version,
130
- }),
131
- );
132
- }
133
- }
134
-
135
- // Generate revoke changes
136
- if (result.revokes.length > 0) {
137
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
138
- for (const [grantable, list] of revokeGroups) {
139
- void grantable;
140
- changes.push(
141
- new RevokeDomainPrivileges({
142
- domain: newDomain,
143
- grantee,
144
- privileges: list,
145
- version: ctx.version,
146
- }),
147
- );
148
- }
149
- }
150
-
151
- // Generate revoke grant option changes
152
- if (result.revokeGrantOption.length > 0) {
153
- changes.push(
154
- new RevokeGrantOptionDomainPrivileges({
155
- domain: newDomain,
156
- grantee,
157
- privilegeNames: result.revokeGrantOption,
158
- version: ctx.version,
159
- }),
160
- );
161
- }
162
- }
118
+ changes.push(
119
+ ...(emitObjectPrivilegeChanges(
120
+ privilegeResults,
121
+ newDomain,
122
+ newDomain,
123
+ "domain",
124
+ {
125
+ Grant: GrantDomainPrivileges,
126
+ Revoke: RevokeDomainPrivileges,
127
+ RevokeGrantOption: RevokeGrantOptionDomainPrivileges,
128
+ },
129
+ ctx.version,
130
+ ) as DomainChange[]),
131
+ );
163
132
  }
164
133
 
165
134
  for (const domainId of dropped) {
@@ -304,54 +273,22 @@ export function diffDomains(
304
273
  mainPrivilegesFiltered,
305
274
  branchPrivilegesFiltered,
306
275
  branchDomain.owner,
307
- ctx.mainRoles,
308
276
  );
309
277
 
310
- for (const [grantee, result] of privilegeResults) {
311
- // Generate grant changes
312
- if (result.grants.length > 0) {
313
- const grantGroups = groupPrivilegesByGrantable(result.grants);
314
- for (const [grantable, list] of grantGroups) {
315
- void grantable;
316
- changes.push(
317
- new GrantDomainPrivileges({
318
- domain: branchDomain,
319
- grantee,
320
- privileges: list,
321
- version: ctx.version,
322
- }),
323
- );
324
- }
325
- }
326
-
327
- // Generate revoke changes
328
- if (result.revokes.length > 0) {
329
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
330
- for (const [grantable, list] of revokeGroups) {
331
- void grantable;
332
- changes.push(
333
- new RevokeDomainPrivileges({
334
- domain: mainDomain,
335
- grantee,
336
- privileges: list,
337
- version: ctx.version,
338
- }),
339
- );
340
- }
341
- }
342
-
343
- // Generate revoke grant option changes
344
- if (result.revokeGrantOption.length > 0) {
345
- changes.push(
346
- new RevokeGrantOptionDomainPrivileges({
347
- domain: mainDomain,
348
- grantee,
349
- privilegeNames: result.revokeGrantOption,
350
- version: ctx.version,
351
- }),
352
- );
353
- }
354
- }
278
+ changes.push(
279
+ ...(emitObjectPrivilegeChanges(
280
+ privilegeResults,
281
+ branchDomain,
282
+ mainDomain,
283
+ "domain",
284
+ {
285
+ Grant: GrantDomainPrivileges,
286
+ Revoke: RevokeDomainPrivileges,
287
+ RevokeGrantOption: RevokeGrantOptionDomainPrivileges,
288
+ },
289
+ ctx.version,
290
+ ) as DomainChange[]),
291
+ );
355
292
  }
356
293
 
357
294
  return changes;
@@ -168,7 +168,7 @@ export async function extractDomains(pool: Pool): Promise<Domain[]> {
168
168
  )
169
169
  order by x.grantee, x.privilege_type
170
170
  )
171
- from lateral aclexplode(t.typacl) as x(grantor, grantee, privilege_type, is_grantable)
171
+ from lateral aclexplode(COALESCE(t.typacl, acldefault('T', t.typowner))) as x(grantor, grantee, privilege_type, is_grantable)
172
172
  ), '[]'
173
173
  ) as privileges
174
174
  from
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { EventTrigger } from "../event-trigger.model.ts";
3
4
  import {
4
5
  AlterEventTriggerChangeOwner,
@@ -17,32 +18,38 @@ describe("event trigger alter change", () => {
17
18
  comment: null,
18
19
  });
19
20
 
20
- test("serialize owner change", () => {
21
+ test("serialize owner change", async () => {
21
22
  const change = new AlterEventTriggerChangeOwner({
22
23
  eventTrigger: baseEventTrigger,
23
24
  owner: "new_owner",
24
25
  });
25
26
 
27
+ await assertValidSql(change.serialize());
28
+
26
29
  expect(change.serialize()).toBe(
27
30
  "ALTER EVENT TRIGGER ddl_logger OWNER TO new_owner",
28
31
  );
29
32
  });
30
33
 
31
- test("serialize disable", () => {
34
+ test("serialize disable", async () => {
32
35
  const change = new AlterEventTriggerSetEnabled({
33
36
  eventTrigger: baseEventTrigger,
34
37
  enabled: "D",
35
38
  });
36
39
 
40
+ await assertValidSql(change.serialize());
41
+
37
42
  expect(change.serialize()).toBe("ALTER EVENT TRIGGER ddl_logger DISABLE");
38
43
  });
39
44
 
40
- test("serialize enable always", () => {
45
+ test("serialize enable always", async () => {
41
46
  const change = new AlterEventTriggerSetEnabled({
42
47
  eventTrigger: baseEventTrigger,
43
48
  enabled: "A",
44
49
  });
45
50
 
51
+ await assertValidSql(change.serialize());
52
+
46
53
  expect(change.serialize()).toBe(
47
54
  "ALTER EVENT TRIGGER ddl_logger ENABLE ALWAYS",
48
55
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { EventTrigger } from "../event-trigger.model.ts";
3
4
  import { CreateEventTrigger } from "./event-trigger.create.ts";
4
5
 
5
6
  describe("event trigger create change", () => {
6
- test("serialize create event trigger", () => {
7
+ test("serialize create event trigger", async () => {
7
8
  const eventTrigger = new EventTrigger({
8
9
  name: "ddl_logger",
9
10
  event: "ddl_command_start",
@@ -17,6 +18,8 @@ describe("event trigger create change", () => {
17
18
 
18
19
  const change = new CreateEventTrigger({ eventTrigger });
19
20
 
21
+ await assertValidSql(change.serialize());
22
+
20
23
  expect(change.serialize()).toBe(
21
24
  "CREATE EVENT TRIGGER ddl_logger ON ddl_command_start WHEN TAG IN ('CREATE TABLE', 'ALTER TABLE') EXECUTE FUNCTION public.log_ddl()",
22
25
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { EventTrigger } from "../event-trigger.model.ts";
3
4
  import { DropEventTrigger } from "./event-trigger.drop.ts";
4
5
 
5
6
  describe("event trigger drop change", () => {
6
- test("serialize drop event trigger", () => {
7
+ test("serialize drop event trigger", async () => {
7
8
  const eventTrigger = new EventTrigger({
8
9
  name: "ddl_logger",
9
10
  event: "ddl_command_start",
@@ -17,6 +18,8 @@ describe("event trigger drop change", () => {
17
18
 
18
19
  const change = new DropEventTrigger({ eventTrigger });
19
20
 
21
+ await assertValidSql(change.serialize());
22
+
20
23
  expect(change.serialize()).toBe("DROP EVENT TRIGGER ddl_logger");
21
24
  });
22
25
  });
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import type { ObjectDiffContext } from "../diff-context.ts";
2
3
  import {
3
4
  AlterEventTriggerChangeOwner,
4
5
  AlterEventTriggerSetEnabled,
@@ -12,6 +13,10 @@ import { DropEventTrigger } from "./changes/event-trigger.drop.ts";
12
13
  import { diffEventTriggers } from "./event-trigger.diff.ts";
13
14
  import { EventTrigger, type EventTriggerProps } from "./event-trigger.model.ts";
14
15
 
16
+ const ctx: Pick<ObjectDiffContext, "currentUser"> = {
17
+ currentUser: "postgres",
18
+ };
19
+
15
20
  const base: EventTriggerProps = {
16
21
  name: "ddl_logger",
17
22
  event: "ddl_command_start",
@@ -28,7 +33,7 @@ describe.concurrent("event-trigger.diff", () => {
28
33
  const eventTrigger = new EventTrigger(base);
29
34
 
30
35
  const created = diffEventTriggers(
31
- { currentUser: "postgres" },
36
+ ctx,
32
37
  {},
33
38
  { [eventTrigger.stableId]: eventTrigger },
34
39
  );
@@ -36,7 +41,7 @@ describe.concurrent("event-trigger.diff", () => {
36
41
  expect(created[0]).toBeInstanceOf(CreateEventTrigger);
37
42
 
38
43
  const dropped = diffEventTriggers(
39
- { currentUser: "postgres" },
44
+ ctx,
40
45
  { [eventTrigger.stableId]: eventTrigger },
41
46
  {},
42
47
  );
@@ -52,7 +57,7 @@ describe.concurrent("event-trigger.diff", () => {
52
57
  });
53
58
 
54
59
  const changes = diffEventTriggers(
55
- { currentUser: "postgres" },
60
+ ctx,
56
61
  { [mainEventTrigger.stableId]: mainEventTrigger },
57
62
  { [branchEventTrigger.stableId]: branchEventTrigger },
58
63
  );
@@ -70,7 +75,7 @@ describe.concurrent("event-trigger.diff", () => {
70
75
  });
71
76
 
72
77
  const changes = diffEventTriggers(
73
- { currentUser: "postgres" },
78
+ ctx,
74
79
  { [mainEventTrigger.stableId]: mainEventTrigger },
75
80
  { [branchEventTrigger.stableId]: branchEventTrigger },
76
81
  );
@@ -87,7 +92,7 @@ describe.concurrent("event-trigger.diff", () => {
87
92
  });
88
93
 
89
94
  const changes = diffEventTriggers(
90
- { currentUser: "postgres" },
95
+ ctx,
91
96
  { [mainEventTrigger.stableId]: mainEventTrigger },
92
97
  { [branchEventTrigger.stableId]: branchEventTrigger },
93
98
  );
@@ -108,7 +113,7 @@ describe.concurrent("event-trigger.diff", () => {
108
113
  });
109
114
 
110
115
  const createCommentChanges = diffEventTriggers(
111
- { currentUser: "postgres" },
116
+ ctx,
112
117
  { [mainEventTrigger.stableId]: mainEventTrigger },
113
118
  { [branchWithComment.stableId]: branchWithComment },
114
119
  );
@@ -116,7 +121,7 @@ describe.concurrent("event-trigger.diff", () => {
116
121
  expect(createCommentChanges[0]).toBeInstanceOf(CreateCommentOnEventTrigger);
117
122
 
118
123
  const dropCommentChanges = diffEventTriggers(
119
- { currentUser: "postgres" },
124
+ ctx,
120
125
  { [branchWithComment.stableId]: branchWithComment },
121
126
  { [branchWithoutComment.stableId]: branchWithoutComment },
122
127
  );
@@ -1,4 +1,5 @@
1
1
  import { diffObjects } from "../base.diff.ts";
2
+ import type { ObjectDiffContext } from "../diff-context.ts";
2
3
  import { deepEqual, hasNonAlterableChanges } from "../utils.ts";
3
4
  import {
4
5
  AlterEventTriggerChangeOwner,
@@ -22,7 +23,7 @@ import type { EventTrigger } from "./event-trigger.model.ts";
22
23
  * @returns A list of changes to apply to main to make it match branch.
23
24
  */
24
25
  export function diffEventTriggers(
25
- ctx: { currentUser: string },
26
+ ctx: Pick<ObjectDiffContext, "currentUser">,
26
27
  main: Record<string, EventTrigger>,
27
28
  branch: Record<string, EventTrigger>,
28
29
  ): EventTriggerChange[] {
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Extension, type ExtensionProps } from "../extension.model.ts";
3
4
  import {
4
5
  AlterExtensionSetSchema,
@@ -7,7 +8,7 @@ import {
7
8
 
8
9
  describe.concurrent("extension", () => {
9
10
  describe("alter", () => {
10
- test("update version", () => {
11
+ test("update version", async () => {
11
12
  const props: Omit<ExtensionProps, "version"> = {
12
13
  name: "test_extension",
13
14
  schema: "public",
@@ -26,12 +27,14 @@ describe.concurrent("extension", () => {
26
27
  version: "2.0",
27
28
  });
28
29
 
30
+ await assertValidSql(change.serialize());
31
+
29
32
  expect(change.serialize()).toBe(
30
33
  "ALTER EXTENSION test_extension UPDATE TO '2.0'",
31
34
  );
32
35
  });
33
36
 
34
- test("set schema", () => {
37
+ test("set schema", async () => {
35
38
  const props: Omit<ExtensionProps, "schema"> = {
36
39
  name: "test_extension",
37
40
  relocatable: true,
@@ -50,6 +53,8 @@ describe.concurrent("extension", () => {
50
53
  schema: "extensions",
51
54
  });
52
55
 
56
+ await assertValidSql(change.serialize());
57
+
53
58
  expect(change.serialize()).toBe(
54
59
  "ALTER EXTENSION test_extension SET SCHEMA extensions",
55
60
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Extension } from "../extension.model.ts";
3
4
  import { CreateExtension } from "./extension.create.ts";
4
5
 
5
6
  describe("extension", () => {
6
- test("create", () => {
7
+ test("create", async () => {
7
8
  const extension = new Extension({
8
9
  name: "test_extension",
9
10
  schema: "public",
@@ -18,6 +19,8 @@ describe("extension", () => {
18
19
  extension,
19
20
  });
20
21
 
22
+ await assertValidSql(change.serialize());
23
+
21
24
  expect(change.serialize()).toBe(
22
25
  `CREATE EXTENSION test_extension WITH SCHEMA public`,
23
26
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Extension } from "../extension.model.ts";
3
4
  import { DropExtension } from "./extension.drop.ts";
4
5
 
5
6
  describe("extension", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const extension = new Extension({
8
9
  name: "test_extension",
9
10
  schema: "public",
@@ -18,6 +19,8 @@ describe("extension", () => {
18
19
  extension,
19
20
  });
20
21
 
22
+ await assertValidSql(change.serialize());
23
+
21
24
  expect(change.serialize()).toBe("DROP EXTENSION test_extension");
22
25
  });
23
26
  });
@@ -0,0 +1,98 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import type { Pool } from "pg";
3
+ import { Extension, extractExtensions } from "./extension.model.ts";
4
+
5
+ describe("Extension", () => {
6
+ test("stableId returns extension:<name>", () => {
7
+ const ext = new Extension({
8
+ name: "plpgsql",
9
+ schema: "pg_catalog",
10
+ relocatable: false,
11
+ version: "1.0",
12
+ owner: "postgres",
13
+ comment: null,
14
+ members: [],
15
+ });
16
+ expect(ext.stableId).toBe("extension:plpgsql");
17
+ });
18
+
19
+ test("identityFields returns name", () => {
20
+ const ext = new Extension({
21
+ name: "vector",
22
+ schema: "extensions",
23
+ relocatable: true,
24
+ version: "0.7.0",
25
+ owner: "postgres",
26
+ comment: "vector type",
27
+ members: ["type:extensions.vector"],
28
+ });
29
+ expect(ext.identityFields).toEqual({ name: "vector" });
30
+ });
31
+
32
+ test("dataFields returns schema, relocatable, version, owner, comment", () => {
33
+ const ext = new Extension({
34
+ name: "pgcrypto",
35
+ schema: "public",
36
+ relocatable: false,
37
+ version: "1.3",
38
+ owner: "postgres",
39
+ comment: "cryptographic functions",
40
+ members: ["procedure:public.gen_random_uuid()"],
41
+ });
42
+ expect(ext.dataFields).toEqual({
43
+ schema: "public",
44
+ relocatable: false,
45
+ version: "1.3",
46
+ owner: "postgres",
47
+ comment: "cryptographic functions",
48
+ });
49
+ });
50
+ });
51
+
52
+ describe("extractExtensions", () => {
53
+ test("returns empty array when pool returns no rows", async () => {
54
+ const pool = {
55
+ query: async () => ({ rows: [] }),
56
+ } as unknown as Pool;
57
+ const result = await extractExtensions(pool);
58
+ expect(result).toEqual([]);
59
+ });
60
+
61
+ test("returns Extension instances for valid rows", async () => {
62
+ const pool = {
63
+ query: async () => ({
64
+ rows: [
65
+ {
66
+ name: "plpgsql",
67
+ schema: "pg_catalog",
68
+ relocatable: false,
69
+ version: "1.0",
70
+ owner: "postgres",
71
+ comment: null,
72
+ members: [],
73
+ },
74
+ {
75
+ name: "vector",
76
+ schema: "extensions",
77
+ relocatable: true,
78
+ version: "0.7.0",
79
+ owner: "postgres",
80
+ comment: null,
81
+ members: ["type:extensions.vector", "table:extensions.vector"],
82
+ },
83
+ ],
84
+ }),
85
+ } as unknown as Pool;
86
+ const result = await extractExtensions(pool);
87
+ expect(result).toHaveLength(2);
88
+ expect(result[0]).toBeInstanceOf(Extension);
89
+ expect(result[0].name).toBe("plpgsql");
90
+ expect(result[0].stableId).toBe("extension:plpgsql");
91
+ expect(result[0].members).toEqual([]);
92
+ expect(result[1].name).toBe("vector");
93
+ expect(result[1].members).toEqual([
94
+ "type:extensions.vector",
95
+ "table:extensions.vector",
96
+ ]);
97
+ });
98
+ });