@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.
- package/README.md +40 -23
- package/dist/cli/app.js +26 -3
- package/dist/cli/bin/cli.js +5 -0
- package/dist/cli/commands/catalog-export.d.ts +5 -0
- package/dist/cli/commands/catalog-export.js +64 -0
- package/dist/cli/commands/declarative-apply.d.ts +6 -0
- package/dist/cli/commands/declarative-apply.js +288 -0
- package/dist/cli/commands/declarative-export.d.ts +5 -0
- package/dist/cli/commands/declarative-export.js +245 -0
- package/dist/cli/commands/plan.js +19 -6
- package/dist/cli/exit-code.d.ts +2 -0
- package/dist/cli/exit-code.js +7 -0
- package/dist/cli/formatters/tree/tree.js +3 -2
- package/dist/cli/utils/apply-display.d.ts +52 -0
- package/dist/cli/utils/apply-display.js +183 -0
- package/dist/cli/utils/export-display.d.ts +43 -0
- package/dist/cli/utils/export-display.js +202 -0
- package/dist/cli/utils/resolve-input.d.ts +7 -0
- package/dist/cli/utils/resolve-input.js +13 -0
- package/dist/core/catalog-export/index.d.ts +11 -0
- package/dist/core/catalog-export/index.js +10 -0
- package/dist/core/catalog.diff.d.ts +1 -0
- package/dist/core/catalog.diff.js +64 -48
- package/dist/core/catalog.model.d.ts +14 -1
- package/dist/core/catalog.model.js +103 -1
- package/dist/core/catalog.snapshot.d.ts +66 -0
- package/dist/core/catalog.snapshot.js +206 -0
- package/dist/core/declarative-apply/discover-sql.d.ts +18 -0
- package/dist/core/declarative-apply/discover-sql.js +86 -0
- package/dist/core/declarative-apply/extract-catalog-providers.d.ts +23 -0
- package/dist/core/declarative-apply/extract-catalog-providers.js +159 -0
- package/dist/core/declarative-apply/index.d.ts +49 -0
- package/dist/core/declarative-apply/index.js +134 -0
- package/dist/core/declarative-apply/round-apply.d.ts +100 -0
- package/dist/core/declarative-apply/round-apply.js +378 -0
- package/dist/core/export/file-mapper.d.ts +71 -0
- package/dist/core/export/file-mapper.js +474 -0
- package/dist/core/export/grouper.d.ts +13 -0
- package/dist/core/export/grouper.js +76 -0
- package/dist/core/export/index.d.ts +45 -0
- package/dist/core/export/index.js +63 -0
- package/dist/core/export/types.d.ts +84 -0
- package/dist/core/export/types.js +25 -0
- package/dist/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
- package/dist/core/integrations/filter/dsl.d.ts +38 -1
- package/dist/core/integrations/filter/dsl.js +20 -2
- package/dist/core/integrations/filter/extractors.js +42 -0
- package/dist/core/integrations/integration-dsl.d.ts +10 -0
- package/dist/core/integrations/supabase.d.ts +8 -0
- package/dist/core/integrations/supabase.js +9 -0
- package/dist/core/objects/aggregate/aggregate.diff.d.ts +2 -8
- package/dist/core/objects/aggregate/aggregate.diff.js +16 -70
- package/dist/core/objects/aggregate/aggregate.model.d.ts +8 -8
- package/dist/core/objects/aggregate/aggregate.model.js +1 -1
- package/dist/core/objects/aggregate/changes/aggregate.create.js +1 -1
- package/dist/core/objects/aggregate/changes/aggregate.drop.js +1 -1
- package/dist/core/objects/base.privilege-diff.d.ts +38 -13
- package/dist/core/objects/base.privilege-diff.js +104 -22
- package/dist/core/objects/base.privilege.d.ts +1 -0
- package/dist/core/objects/base.privilege.js +9 -2
- package/dist/core/objects/collation/collation.diff.d.ts +2 -3
- package/dist/core/objects/diff-context.d.ts +15 -0
- package/dist/core/objects/diff-context.js +1 -0
- package/dist/core/objects/domain/changes/domain.create.js +4 -2
- package/dist/core/objects/domain/domain.diff.d.ts +2 -8
- package/dist/core/objects/domain/domain.diff.js +16 -77
- package/dist/core/objects/domain/domain.model.js +1 -1
- package/dist/core/objects/event-trigger/event-trigger.diff.d.ts +2 -3
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.d.ts +2 -8
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.js +13 -77
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +2 -2
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.d.ts +2 -8
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -77
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +1 -1
- package/dist/core/objects/foreign-data-wrapper/server/server.diff.d.ts +2 -8
- package/dist/core/objects/foreign-data-wrapper/server/server.diff.js +13 -77
- package/dist/core/objects/language/language.diff.d.ts +2 -5
- package/dist/core/objects/language/language.diff.js +7 -39
- package/dist/core/objects/materialized-view/materialized-view.diff.d.ts +2 -8
- package/dist/core/objects/materialized-view/materialized-view.diff.js +16 -158
- package/dist/core/objects/materialized-view/materialized-view.model.d.ts +3 -3
- package/dist/core/objects/materialized-view/materialized-view.model.js +1 -1
- package/dist/core/objects/procedure/changes/procedure.alter.js +12 -12
- package/dist/core/objects/procedure/procedure.diff.d.ts +2 -8
- package/dist/core/objects/procedure/procedure.diff.js +16 -77
- package/dist/core/objects/procedure/procedure.model.d.ts +9 -9
- package/dist/core/objects/procedure/procedure.model.js +1 -1
- package/dist/core/objects/publication/changes/publication.alter.d.ts +0 -9
- package/dist/core/objects/publication/changes/publication.alter.js +0 -14
- package/dist/core/objects/publication/changes/publication.types.d.ts +2 -2
- package/dist/core/objects/publication/publication.diff.d.ts +2 -3
- package/dist/core/objects/publication/publication.diff.js +8 -13
- package/dist/core/objects/rls-policy/changes/rls-policy.alter.js +3 -3
- package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
- package/dist/core/objects/role/role.diff.js +22 -1
- package/dist/core/objects/role/role.model.d.ts +4 -3
- package/dist/core/objects/role/role.model.js +118 -12
- package/dist/core/objects/rule/rule.model.d.ts +1 -1
- package/dist/core/objects/schema/schema.diff.d.ts +2 -8
- package/dist/core/objects/schema/schema.diff.js +16 -77
- package/dist/core/objects/schema/schema.model.js +1 -1
- package/dist/core/objects/sequence/sequence.diff.d.ts +2 -8
- package/dist/core/objects/sequence/sequence.diff.js +16 -79
- package/dist/core/objects/sequence/sequence.model.js +1 -1
- package/dist/core/objects/subscription/subscription.diff.d.ts +2 -3
- package/dist/core/objects/table/changes/table.create.js +3 -0
- package/dist/core/objects/table/table.diff.d.ts +2 -8
- package/dist/core/objects/table/table.diff.js +26 -157
- package/dist/core/objects/table/table.model.d.ts +23 -22
- package/dist/core/objects/table/table.model.js +1 -1
- package/dist/core/objects/trigger/changes/trigger.create.js +2 -4
- package/dist/core/objects/trigger/trigger.model.d.ts +8 -0
- package/dist/core/objects/trigger/trigger.model.js +11 -0
- package/dist/core/objects/type/composite-type/composite-type.diff.d.ts +2 -8
- package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -77
- package/dist/core/objects/type/composite-type/composite-type.model.d.ts +3 -3
- package/dist/core/objects/type/composite-type/composite-type.model.js +2 -1
- package/dist/core/objects/type/enum/enum.diff.d.ts +2 -8
- package/dist/core/objects/type/enum/enum.diff.js +25 -112
- package/dist/core/objects/type/enum/enum.model.js +1 -1
- package/dist/core/objects/type/range/changes/range.create.js +6 -3
- package/dist/core/objects/type/range/range.diff.d.ts +2 -8
- package/dist/core/objects/type/range/range.diff.js +16 -77
- package/dist/core/objects/type/range/range.model.js +1 -1
- package/dist/core/objects/view/view.diff.d.ts +2 -8
- package/dist/core/objects/view/view.diff.js +16 -158
- package/dist/core/objects/view/view.model.d.ts +18 -4
- package/dist/core/objects/view/view.model.js +3 -13
- package/dist/core/plan/apply.js +9 -26
- package/dist/core/plan/create.d.ts +19 -6
- package/dist/core/plan/create.js +134 -174
- package/dist/core/plan/serialize.js +16 -4
- package/dist/core/plan/sql-format/fixtures.js +3 -5
- package/dist/core/plan/sql-format/keyword-case.js +26 -1
- package/dist/core/plan/ssl-config.d.ts +32 -0
- package/dist/core/plan/ssl-config.js +115 -0
- package/dist/core/plan/types.d.ts +6 -0
- package/dist/core/postgres-config.d.ts +14 -0
- package/dist/core/postgres-config.js +53 -2
- package/dist/core/sort/graph-builder.js +10 -0
- package/dist/core/sort/logical-sort.js +31 -23
- package/dist/core/test-utils/assert-valid-sql.d.ts +10 -0
- package/dist/core/test-utils/assert-valid-sql.js +19 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -1
- package/package.json +21 -4
- package/src/cli/app.ts +27 -3
- package/src/cli/bin/cli.ts +6 -0
- package/src/cli/commands/catalog-export.ts +78 -0
- package/src/cli/commands/declarative-apply.diagnostics.test.ts +77 -0
- package/src/cli/commands/declarative-apply.ts +380 -0
- package/src/cli/commands/declarative-export.ts +330 -0
- package/src/cli/commands/plan.ts +28 -7
- package/src/cli/exit-code.test.ts +19 -0
- package/src/cli/exit-code.ts +7 -0
- package/src/cli/formatters/tree/tree.ts +3 -2
- package/src/cli/utils/apply-display.test.ts +348 -0
- package/src/cli/utils/apply-display.ts +238 -0
- package/src/cli/utils/export-display.test.ts +103 -0
- package/src/cli/utils/export-display.ts +275 -0
- package/src/cli/utils/integrations.test.ts +44 -0
- package/src/cli/utils/resolve-input.test.ts +38 -0
- package/src/cli/utils/resolve-input.ts +17 -0
- package/src/core/catalog-export/index.ts +20 -0
- package/src/core/catalog.diff.ts +79 -78
- package/src/core/catalog.model.test.ts +122 -0
- package/src/core/catalog.model.ts +127 -1
- package/src/core/catalog.snapshot.test.ts +464 -0
- package/src/core/catalog.snapshot.ts +289 -0
- package/src/core/declarative-apply/discover-sql.test.ts +103 -0
- package/src/core/declarative-apply/discover-sql.ts +107 -0
- package/src/core/declarative-apply/extract-catalog-providers.ts +220 -0
- package/src/core/declarative-apply/index.test.ts +67 -0
- package/src/core/declarative-apply/index.ts +205 -0
- package/src/core/declarative-apply/round-apply.test.ts +504 -0
- package/src/core/declarative-apply/round-apply.ts +562 -0
- package/src/core/expand-replace-dependencies.test.ts +70 -0
- package/src/core/export/file-mapper.test.ts +816 -0
- package/src/core/export/file-mapper.ts +574 -0
- package/src/core/export/grouper.ts +108 -0
- package/src/core/export/index.ts +129 -0
- package/src/core/export/types.ts +104 -0
- package/src/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
- package/src/core/integrations/filter/dsl.test.ts +211 -0
- package/src/core/integrations/filter/dsl.ts +65 -3
- package/src/core/integrations/filter/extractors.test.ts +244 -0
- package/src/core/integrations/filter/extractors.ts +42 -0
- package/src/core/integrations/integration-dsl.ts +10 -0
- package/src/core/integrations/serialize/dsl.test.ts +91 -0
- package/src/core/integrations/supabase.ts +9 -0
- package/src/core/objects/aggregate/aggregate.diff.ts +39 -95
- package/src/core/objects/aggregate/aggregate.model.ts +1 -1
- package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +3 -1
- package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +5 -2
- package/src/core/objects/aggregate/changes/aggregate.create.test.ts +6 -3
- package/src/core/objects/aggregate/changes/aggregate.create.ts +1 -1
- package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +7 -3
- package/src/core/objects/aggregate/changes/aggregate.drop.ts +1 -1
- package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +9 -3
- package/src/core/objects/base.privilege-diff.ts +178 -30
- package/src/core/objects/base.privilege.ts +9 -2
- package/src/core/objects/collation/changes/collation.alter.test.ts +7 -2
- package/src/core/objects/collation/changes/collation.create.test.ts +7 -2
- package/src/core/objects/collation/changes/collation.drop.test.ts +4 -1
- package/src/core/objects/collation/collation.diff.test.ts +9 -12
- package/src/core/objects/collation/collation.diff.ts +2 -1
- package/src/core/objects/diff-context.ts +16 -0
- package/src/core/objects/domain/changes/domain.alter.test.ts +28 -9
- package/src/core/objects/domain/changes/domain.create.test.ts +32 -2
- package/src/core/objects/domain/changes/domain.create.ts +7 -1
- package/src/core/objects/domain/changes/domain.drop.test.ts +4 -1
- package/src/core/objects/domain/domain.diff.ts +39 -102
- package/src/core/objects/domain/domain.model.ts +1 -1
- package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +10 -3
- package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +4 -1
- package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +4 -1
- package/src/core/objects/event-trigger/event-trigger.diff.test.ts +12 -7
- package/src/core/objects/event-trigger/event-trigger.diff.ts +2 -1
- package/src/core/objects/extension/changes/extension.alter.test.ts +7 -2
- package/src/core/objects/extension/changes/extension.create.test.ts +4 -1
- package/src/core/objects/extension/changes/extension.drop.test.ts +4 -1
- package/src/core/objects/extension/extension.model.test.ts +98 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +16 -5
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +51 -16
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +4 -1
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +111 -4
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +31 -101
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +2 -2
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +46 -15
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +13 -4
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +4 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +39 -102
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +1 -1
- package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +22 -7
- package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +19 -6
- package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +4 -1
- package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +95 -0
- package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +31 -101
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +13 -4
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +16 -5
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +10 -3
- package/src/core/objects/index/changes/index.alter.test.ts +13 -4
- package/src/core/objects/index/changes/index.create.test.ts +4 -1
- package/src/core/objects/index/changes/index.drop.test.ts +4 -1
- package/src/core/objects/language/changes/language.alter.test.ts +4 -1
- package/src/core/objects/language/changes/language.create.test.ts +4 -1
- package/src/core/objects/language/changes/language.drop.test.ts +4 -1
- package/src/core/objects/language/language.diff.test.ts +86 -4
- package/src/core/objects/language/language.diff.ts +17 -49
- package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +10 -3
- package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +7 -2
- package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +4 -1
- package/src/core/objects/materialized-view/materialized-view.diff.test.ts +162 -0
- package/src/core/objects/materialized-view/materialized-view.diff.ts +41 -191
- package/src/core/objects/materialized-view/materialized-view.model.ts +1 -1
- package/src/core/objects/procedure/changes/procedure.alter.test.ts +121 -49
- package/src/core/objects/procedure/changes/procedure.alter.ts +15 -12
- package/src/core/objects/procedure/changes/procedure.create.test.ts +4 -1
- package/src/core/objects/procedure/changes/procedure.drop.test.ts +7 -2
- package/src/core/objects/procedure/procedure.diff.ts +39 -102
- package/src/core/objects/procedure/procedure.model.ts +1 -1
- package/src/core/objects/publication/changes/publication.alter.test.ts +15 -21
- package/src/core/objects/publication/changes/publication.alter.ts +0 -18
- package/src/core/objects/publication/changes/publication.comment.test.ts +5 -2
- package/src/core/objects/publication/changes/publication.create.test.ts +5 -2
- package/src/core/objects/publication/changes/publication.drop.test.ts +3 -1
- package/src/core/objects/publication/changes/publication.types.ts +0 -2
- package/src/core/objects/publication/publication.diff.test.ts +24 -19
- package/src/core/objects/publication/publication.diff.ts +9 -15
- package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +31 -14
- package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +3 -3
- package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +10 -3
- package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +4 -1
- package/src/core/objects/role/changes/role.alter.test.ts +31 -15
- package/src/core/objects/role/changes/role.create.test.ts +6 -2
- package/src/core/objects/role/changes/role.drop.test.ts +4 -1
- package/src/core/objects/role/role.diff.test.ts +235 -0
- package/src/core/objects/role/role.diff.ts +21 -1
- package/src/core/objects/role/role.model.ts +122 -14
- package/src/core/objects/rule/changes/rule.alter.test.ts +7 -3
- package/src/core/objects/rule/changes/rule.comment.test.ts +5 -2
- package/src/core/objects/rule/changes/rule.create.test.ts +6 -2
- package/src/core/objects/rule/changes/rule.drop.test.ts +3 -1
- package/src/core/objects/schema/changes/schema.alter.test.ts +4 -1
- package/src/core/objects/schema/changes/schema.create.test.ts +4 -1
- package/src/core/objects/schema/changes/schema.drop.test.ts +4 -1
- package/src/core/objects/schema/schema.diff.ts +39 -102
- package/src/core/objects/schema/schema.model.ts +1 -1
- package/src/core/objects/sequence/changes/sequence.alter.test.ts +11 -5
- package/src/core/objects/sequence/changes/sequence.create.test.ts +8 -3
- package/src/core/objects/sequence/changes/sequence.drop.test.ts +4 -1
- package/src/core/objects/sequence/sequence.diff.test.ts +114 -0
- package/src/core/objects/sequence/sequence.diff.ts +39 -104
- package/src/core/objects/sequence/sequence.model.ts +1 -1
- package/src/core/objects/subscription/changes/subscription.alter.test.ts +15 -5
- package/src/core/objects/subscription/changes/subscription.comment.test.ts +5 -2
- package/src/core/objects/subscription/changes/subscription.create.test.ts +5 -2
- package/src/core/objects/subscription/changes/subscription.drop.test.ts +3 -1
- package/src/core/objects/subscription/subscription.diff.test.ts +16 -11
- package/src/core/objects/subscription/subscription.diff.ts +2 -1
- package/src/core/objects/table/changes/table.alter.test.ts +38 -15
- package/src/core/objects/table/changes/table.create.test.ts +41 -3
- package/src/core/objects/table/changes/table.create.ts +4 -0
- package/src/core/objects/table/changes/table.drop.test.ts +3 -1
- package/src/core/objects/table/table.diff.test.ts +157 -0
- package/src/core/objects/table/table.diff.ts +54 -190
- package/src/core/objects/table/table.model.ts +1 -1
- package/src/core/objects/trigger/changes/trigger.alter.test.ts +8 -4
- package/src/core/objects/trigger/changes/trigger.create.test.ts +5 -1
- package/src/core/objects/trigger/changes/trigger.create.ts +7 -4
- package/src/core/objects/trigger/changes/trigger.drop.test.ts +5 -1
- package/src/core/objects/trigger/trigger.diff.test.ts +1 -0
- package/src/core/objects/trigger/trigger.model.ts +12 -0
- package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +10 -4
- package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +7 -2
- package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +4 -1
- package/src/core/objects/type/composite-type/composite-type.diff.test.ts +78 -0
- package/src/core/objects/type/composite-type/composite-type.diff.ts +39 -101
- package/src/core/objects/type/composite-type/composite-type.model.ts +2 -1
- package/src/core/objects/type/enum/changes/enum.alter.test.ts +14 -5
- package/src/core/objects/type/enum/changes/enum.create.test.ts +4 -1
- package/src/core/objects/type/enum/changes/enum.drop.test.ts +4 -1
- package/src/core/objects/type/enum/enum.diff.test.ts +181 -0
- package/src/core/objects/type/enum/enum.diff.ts +58 -146
- package/src/core/objects/type/enum/enum.model.ts +1 -1
- package/src/core/objects/type/range/changes/range.alter.test.ts +3 -1
- package/src/core/objects/type/range/changes/range.create.test.ts +5 -2
- package/src/core/objects/type/range/changes/range.create.ts +6 -2
- package/src/core/objects/type/range/changes/range.drop.test.ts +3 -1
- package/src/core/objects/type/range/range.diff.test.ts +77 -0
- package/src/core/objects/type/range/range.diff.ts +39 -101
- package/src/core/objects/type/range/range.model.ts +1 -1
- package/src/core/objects/view/changes/view.alter.test.ts +8 -3
- package/src/core/objects/view/changes/view.create.test.ts +7 -2
- package/src/core/objects/view/changes/view.drop.test.ts +4 -1
- package/src/core/objects/view/view.diff.test.ts +82 -0
- package/src/core/objects/view/view.diff.ts +41 -191
- package/src/core/objects/view/view.model.ts +3 -17
- package/src/core/plan/apply.ts +9 -27
- package/src/core/plan/create.ts +173 -237
- package/src/core/plan/serialize.test.ts +317 -0
- package/src/core/plan/serialize.ts +18 -4
- package/src/core/plan/sql-format/fixtures.ts +2 -5
- package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +52 -0
- package/src/core/plan/sql-format/format-off.test.ts +14 -17
- package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +27 -22
- package/src/core/plan/sql-format/format-pretty-narrow.test.ts +17 -21
- package/src/core/plan/sql-format/format-pretty-preserve.test.ts +25 -20
- package/src/core/plan/sql-format/format-pretty-upper.test.ts +23 -20
- package/src/core/plan/sql-format/keyword-case.ts +36 -1
- package/src/core/plan/ssl-config.ts +172 -0
- package/src/core/plan/types.ts +6 -0
- package/src/core/postgres-config.ts +71 -2
- package/src/core/sort/graph-builder.ts +12 -0
- package/src/core/sort/logical-sort.test.ts +371 -0
- package/src/core/sort/logical-sort.ts +32 -25
- package/src/core/sort/topological-sort.test.ts +275 -0
- package/src/core/test-utils/assert-valid-sql.ts +20 -0
- package/src/index.ts +26 -2
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import z from "zod";
|
|
2
2
|
import type { Change } from "../change.types.ts";
|
|
3
|
-
import type {
|
|
4
|
-
import { stableId } from "./utils.ts";
|
|
3
|
+
import type { BaseChange } from "./base.change.ts";
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Privilege properties that all privilege objects share.
|
|
@@ -118,7 +117,7 @@ function checkStillHasBase<T extends PrivilegeProps>(
|
|
|
118
117
|
/**
|
|
119
118
|
* Groups privileges by grantable flag for efficient SQL generation
|
|
120
119
|
*/
|
|
121
|
-
|
|
120
|
+
function groupPrivilegesByGrantable<T extends PrivilegeProps>(
|
|
122
121
|
privileges: T[],
|
|
123
122
|
): Map<boolean, T[]> {
|
|
124
123
|
const groups = new Map<boolean, T[]>();
|
|
@@ -135,7 +134,7 @@ export function groupPrivilegesByGrantable<T extends PrivilegeProps>(
|
|
|
135
134
|
/**
|
|
136
135
|
* Groups privileges by columns and grantable flag
|
|
137
136
|
*/
|
|
138
|
-
|
|
137
|
+
function groupPrivilegesByColumns<T extends PrivilegeProps>(
|
|
139
138
|
privileges: T[],
|
|
140
139
|
): Map<string, { columns?: string[]; byGrant: Map<boolean, Set<string>> }> {
|
|
141
140
|
const groups = new Map<
|
|
@@ -236,22 +235,6 @@ function filterOwnerPrivileges<T extends PrivilegeProps>(
|
|
|
236
235
|
return privileges.filter((p) => p.grantee !== owner);
|
|
237
236
|
}
|
|
238
237
|
|
|
239
|
-
/**
|
|
240
|
-
* Filter out privileges for superuser roles, as PostgreSQL doesn't store
|
|
241
|
-
* GRANTs to superusers in relacl (they already have all privileges implicitly).
|
|
242
|
-
* Reference: https://www.postgresql.org/docs/current/role-attributes.html
|
|
243
|
-
*/
|
|
244
|
-
function filterSuperuserPrivileges<T extends PrivilegeProps>(
|
|
245
|
-
privileges: T[],
|
|
246
|
-
mainRoles?: Record<string, Role>,
|
|
247
|
-
): T[] {
|
|
248
|
-
if (!mainRoles) return privileges;
|
|
249
|
-
return privileges.filter((priv) => {
|
|
250
|
-
const role = mainRoles[stableId.role(priv.grantee)];
|
|
251
|
-
return !role?.is_superuser;
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
238
|
/**
|
|
256
239
|
* Generic privilege diffing function that works for any object type
|
|
257
240
|
*/
|
|
@@ -259,22 +242,14 @@ export function diffPrivileges<T extends PrivilegeProps>(
|
|
|
259
242
|
mainPrivileges: T[],
|
|
260
243
|
branchPrivileges: T[],
|
|
261
244
|
owner?: string,
|
|
262
|
-
mainRoles?: Record<string, Role>,
|
|
263
245
|
): Map<string, PrivilegeDiffResult<T>> {
|
|
264
|
-
// Filter out superuser privileges from branch - PostgreSQL doesn't store GRANTs
|
|
265
|
-
// to superusers in relacl because they already have all privileges implicitly
|
|
266
|
-
const branchPrivilegesFiltered = filterSuperuserPrivileges(
|
|
267
|
-
branchPrivileges,
|
|
268
|
-
mainRoles,
|
|
269
|
-
);
|
|
270
|
-
|
|
271
246
|
// Filter out owner privileges if owner is provided
|
|
272
247
|
const mainFiltered = owner
|
|
273
248
|
? filterOwnerPrivileges(mainPrivileges, owner)
|
|
274
249
|
: mainPrivileges;
|
|
275
250
|
const branchFiltered = owner
|
|
276
|
-
? filterOwnerPrivileges(
|
|
277
|
-
:
|
|
251
|
+
? filterOwnerPrivileges(branchPrivileges, owner)
|
|
252
|
+
: branchPrivileges;
|
|
278
253
|
|
|
279
254
|
const mainByGrantee = groupPrivilegesByGrantee(mainFiltered);
|
|
280
255
|
const branchByGrantee = groupPrivilegesByGrantee(branchFiltered);
|
|
@@ -297,3 +272,176 @@ export function diffPrivileges<T extends PrivilegeProps>(
|
|
|
297
272
|
|
|
298
273
|
return results;
|
|
299
274
|
}
|
|
275
|
+
|
|
276
|
+
// ==== Privilege Change Emission Helpers ====
|
|
277
|
+
//
|
|
278
|
+
// These helpers convert the output of `diffPrivileges` (per-grantee grant /
|
|
279
|
+
// revoke / revoke-grant-option lists) into concrete Change instances so that
|
|
280
|
+
// individual object diffs don't have to repeat the same iteration and grouping
|
|
281
|
+
// logic.
|
|
282
|
+
//
|
|
283
|
+
// Callers pass a `PrivilegeChangeFactories` bag containing the three class
|
|
284
|
+
// constructors (Grant, Revoke, RevokeGrantOption) for their object type. The
|
|
285
|
+
// helpers instantiate them with a common props shape: an object reference keyed
|
|
286
|
+
// by `objectKey`, a `grantee`, `privileges` or `privilegeNames`, an optional
|
|
287
|
+
// `version`, and (for column-level privileges) optional `columns`.
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Factory constructors for Grant / Revoke / RevokeGrantOption change classes.
|
|
291
|
+
* Every object type provides its own concrete classes. The `any` props type
|
|
292
|
+
* is intentional: the helpers build props with a computed `[objectKey]` key
|
|
293
|
+
* whose name varies per object type, so no single concrete type can unify
|
|
294
|
+
* all call sites without an unsafe cast elsewhere.
|
|
295
|
+
*/
|
|
296
|
+
interface PrivilegeChangeFactories {
|
|
297
|
+
Grant: new (
|
|
298
|
+
// biome-ignore lint/suspicious/noExplicitAny: factory accepts heterogeneous prop bags keyed by object type
|
|
299
|
+
props: any,
|
|
300
|
+
) => BaseChange;
|
|
301
|
+
Revoke: new (
|
|
302
|
+
// biome-ignore lint/suspicious/noExplicitAny: factory accepts heterogeneous prop bags keyed by object type
|
|
303
|
+
props: any,
|
|
304
|
+
) => BaseChange;
|
|
305
|
+
RevokeGrantOption: new (
|
|
306
|
+
// biome-ignore lint/suspicious/noExplicitAny: factory accepts heterogeneous prop bags keyed by object type
|
|
307
|
+
props: any,
|
|
308
|
+
) => BaseChange;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Emit privilege changes for object-level privileges (schema, sequence,
|
|
313
|
+
* procedure, etc.).
|
|
314
|
+
*
|
|
315
|
+
* For each grantee in `privilegeResults` the function groups grants and revokes
|
|
316
|
+
* by the `grantable` flag and pushes one change per group. Revoke-grant-option
|
|
317
|
+
* entries produce a single change carrying `privilegeNames`.
|
|
318
|
+
*
|
|
319
|
+
* `grantTarget` is the *branch* object (the desired state) while `revokeTarget`
|
|
320
|
+
* is the *main* object (the current state), so that GRANTs reference the
|
|
321
|
+
* newly-created/altered object and REVOKEs reference the existing one.
|
|
322
|
+
*/
|
|
323
|
+
export function emitObjectPrivilegeChanges(
|
|
324
|
+
privilegeResults: Map<string, PrivilegeDiffResult<PrivilegeProps>>,
|
|
325
|
+
grantTarget: unknown,
|
|
326
|
+
revokeTarget: unknown,
|
|
327
|
+
objectKey: string,
|
|
328
|
+
factories: PrivilegeChangeFactories,
|
|
329
|
+
version?: number,
|
|
330
|
+
): BaseChange[] {
|
|
331
|
+
const changes: BaseChange[] = [];
|
|
332
|
+
|
|
333
|
+
for (const [grantee, result] of privilegeResults) {
|
|
334
|
+
for (const [, revokes] of groupPrivilegesByGrantable(result.revokes)) {
|
|
335
|
+
changes.push(
|
|
336
|
+
new factories.Revoke({
|
|
337
|
+
[objectKey]: revokeTarget,
|
|
338
|
+
privileges: revokes,
|
|
339
|
+
grantee,
|
|
340
|
+
version,
|
|
341
|
+
}),
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
if (result.revokeGrantOption.length > 0) {
|
|
345
|
+
changes.push(
|
|
346
|
+
new factories.RevokeGrantOption({
|
|
347
|
+
[objectKey]: revokeTarget,
|
|
348
|
+
privilegeNames: result.revokeGrantOption,
|
|
349
|
+
grantee,
|
|
350
|
+
version,
|
|
351
|
+
}),
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
for (const [, grants] of groupPrivilegesByGrantable(result.grants)) {
|
|
355
|
+
changes.push(
|
|
356
|
+
new factories.Grant({
|
|
357
|
+
[objectKey]: grantTarget,
|
|
358
|
+
privileges: grants,
|
|
359
|
+
grantee,
|
|
360
|
+
version,
|
|
361
|
+
}),
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return changes;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Emit privilege changes for column-level privileges (table, view,
|
|
371
|
+
* materialized view).
|
|
372
|
+
*
|
|
373
|
+
* Like {@link emitObjectPrivilegeChanges} but groups by column set (via
|
|
374
|
+
* `groupPrivilegesByColumns`) instead of only by grantable. For
|
|
375
|
+
* revoke-grant-option the column sets come from `sourcePrivileges` so that
|
|
376
|
+
* `REVOKE GRANT OPTION FOR` is emitted per column set that originally carried
|
|
377
|
+
* the privilege.
|
|
378
|
+
*/
|
|
379
|
+
export function emitColumnPrivilegeChanges(
|
|
380
|
+
privilegeResults: Map<string, PrivilegeDiffResult<PrivilegeProps>>,
|
|
381
|
+
grantTarget: unknown,
|
|
382
|
+
revokeTarget: unknown,
|
|
383
|
+
objectKey: string,
|
|
384
|
+
factories: PrivilegeChangeFactories,
|
|
385
|
+
sourcePrivileges: PrivilegeProps[],
|
|
386
|
+
version?: number,
|
|
387
|
+
): BaseChange[] {
|
|
388
|
+
const changes: BaseChange[] = [];
|
|
389
|
+
|
|
390
|
+
for (const [grantee, result] of privilegeResults) {
|
|
391
|
+
for (const [, group] of groupPrivilegesByColumns(result.revokes)) {
|
|
392
|
+
const allPrivileges = new Set<string>();
|
|
393
|
+
for (const [, privSet] of group.byGrant) {
|
|
394
|
+
for (const priv of privSet) {
|
|
395
|
+
allPrivileges.add(priv);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
changes.push(
|
|
399
|
+
new factories.Revoke({
|
|
400
|
+
[objectKey]: revokeTarget,
|
|
401
|
+
privileges: [...allPrivileges].map((p) => ({
|
|
402
|
+
privilege: p,
|
|
403
|
+
grantable: false,
|
|
404
|
+
})),
|
|
405
|
+
grantee,
|
|
406
|
+
columns: group.columns,
|
|
407
|
+
version,
|
|
408
|
+
}),
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
if (result.revokeGrantOption.length > 0) {
|
|
412
|
+
const sourcePrivsForGrantee = sourcePrivileges.filter(
|
|
413
|
+
(p) => p.grantee === grantee,
|
|
414
|
+
);
|
|
415
|
+
for (const [, group] of groupPrivilegesByColumns(
|
|
416
|
+
sourcePrivsForGrantee.filter((p) =>
|
|
417
|
+
result.revokeGrantOption.includes(p.privilege),
|
|
418
|
+
),
|
|
419
|
+
)) {
|
|
420
|
+
changes.push(
|
|
421
|
+
new factories.RevokeGrantOption({
|
|
422
|
+
[objectKey]: revokeTarget,
|
|
423
|
+
privilegeNames: result.revokeGrantOption,
|
|
424
|
+
grantee,
|
|
425
|
+
columns: group.columns,
|
|
426
|
+
version,
|
|
427
|
+
}),
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
for (const [, group] of groupPrivilegesByColumns(result.grants)) {
|
|
432
|
+
for (const [grantable, privSet] of group.byGrant) {
|
|
433
|
+
changes.push(
|
|
434
|
+
new factories.Grant({
|
|
435
|
+
[objectKey]: grantTarget,
|
|
436
|
+
privileges: [...privSet].map((p) => ({ privilege: p, grantable })),
|
|
437
|
+
grantee,
|
|
438
|
+
columns: group.columns,
|
|
439
|
+
version,
|
|
440
|
+
}),
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return changes;
|
|
447
|
+
}
|
|
@@ -164,7 +164,7 @@ export function getObjectKindPrefix(objectKind: string): string {
|
|
|
164
164
|
case "TYPE":
|
|
165
165
|
return "ON TYPE";
|
|
166
166
|
case "FOREIGN TABLE":
|
|
167
|
-
return "ON
|
|
167
|
+
return "ON TABLE";
|
|
168
168
|
default:
|
|
169
169
|
return "ON";
|
|
170
170
|
}
|
|
@@ -176,9 +176,16 @@ export function normalizePrivileges(privileges: PrivilegeProps[]) {
|
|
|
176
176
|
grantee: privilege.grantee,
|
|
177
177
|
privilege: privilege.privilege,
|
|
178
178
|
grantable: privilege.grantable,
|
|
179
|
+
columns: privilege.columns
|
|
180
|
+
? [...privilege.columns].sort()
|
|
181
|
+
: privilege.columns,
|
|
179
182
|
}))
|
|
180
183
|
.sort((a, b) => {
|
|
181
184
|
if (a.grantee !== b.grantee) return a.grantee.localeCompare(b.grantee);
|
|
182
|
-
|
|
185
|
+
if (a.privilege !== b.privilege)
|
|
186
|
+
return a.privilege.localeCompare(b.privilege);
|
|
187
|
+
const colA = a.columns?.join(",") ?? "";
|
|
188
|
+
const colB = b.columns?.join(",") ?? "";
|
|
189
|
+
return colA.localeCompare(colB);
|
|
183
190
|
});
|
|
184
191
|
}
|
|
@@ -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 { Collation } from "../collation.model.ts";
|
|
3
4
|
import {
|
|
4
5
|
AlterCollationChangeOwner,
|
|
@@ -7,7 +8,7 @@ import {
|
|
|
7
8
|
|
|
8
9
|
describe.concurrent("collation", () => {
|
|
9
10
|
describe("alter", () => {
|
|
10
|
-
test("change owner", () => {
|
|
11
|
+
test("change owner", async () => {
|
|
11
12
|
const collation = new Collation({
|
|
12
13
|
schema: "public",
|
|
13
14
|
name: "test",
|
|
@@ -28,12 +29,14 @@ describe.concurrent("collation", () => {
|
|
|
28
29
|
owner: "new_owner",
|
|
29
30
|
});
|
|
30
31
|
|
|
32
|
+
await assertValidSql(change.serialize());
|
|
33
|
+
|
|
31
34
|
expect(change.serialize()).toBe(
|
|
32
35
|
"ALTER COLLATION public.test OWNER TO new_owner",
|
|
33
36
|
);
|
|
34
37
|
});
|
|
35
38
|
|
|
36
|
-
test("refresh version", () => {
|
|
39
|
+
test("refresh version", async () => {
|
|
37
40
|
const collation = new Collation({
|
|
38
41
|
schema: "public",
|
|
39
42
|
name: "test",
|
|
@@ -53,6 +56,8 @@ describe.concurrent("collation", () => {
|
|
|
53
56
|
collation,
|
|
54
57
|
});
|
|
55
58
|
|
|
59
|
+
await assertValidSql(change.serialize());
|
|
60
|
+
|
|
56
61
|
expect(change.serialize()).toBe(
|
|
57
62
|
"ALTER COLLATION public.test REFRESH VERSION",
|
|
58
63
|
);
|
|
@@ -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 { Collation } from "../collation.model.ts";
|
|
3
4
|
import { CreateCollation } from "./collation.create.ts";
|
|
4
5
|
|
|
5
6
|
describe("collation", () => {
|
|
6
|
-
test("create minimal", () => {
|
|
7
|
+
test("create minimal", async () => {
|
|
7
8
|
const collation = new Collation({
|
|
8
9
|
schema: "public",
|
|
9
10
|
name: "test",
|
|
@@ -21,12 +22,14 @@ describe("collation", () => {
|
|
|
21
22
|
|
|
22
23
|
const change = new CreateCollation({ collation });
|
|
23
24
|
|
|
25
|
+
await assertValidSql(change.serialize());
|
|
26
|
+
|
|
24
27
|
expect(change.serialize()).toBe(
|
|
25
28
|
`CREATE COLLATION public.test (LC_COLLATE = 'C', LC_CTYPE = 'C')`,
|
|
26
29
|
);
|
|
27
30
|
});
|
|
28
31
|
|
|
29
|
-
test("create with all options", () => {
|
|
32
|
+
test("create with all options", async () => {
|
|
30
33
|
const collation = new Collation({
|
|
31
34
|
schema: "public",
|
|
32
35
|
name: "test",
|
|
@@ -44,6 +47,8 @@ describe("collation", () => {
|
|
|
44
47
|
|
|
45
48
|
const change = new CreateCollation({ collation });
|
|
46
49
|
|
|
50
|
+
await assertValidSql(change.serialize());
|
|
51
|
+
|
|
47
52
|
expect(change.serialize()).toBe(
|
|
48
53
|
`CREATE COLLATION public.test (LOCALE = 'en_US', LC_COLLATE = 'en_US', LC_CTYPE = 'en_US', PROVIDER = icu, DETERMINISTIC = false, RULES = '& A < a <<< à', VERSION = '1.0')`,
|
|
49
54
|
);
|
|
@@ -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 { Collation } from "../collation.model.ts";
|
|
3
4
|
import { DropCollation } from "./collation.drop.ts";
|
|
4
5
|
|
|
5
6
|
describe("collation", () => {
|
|
6
|
-
test("drop", () => {
|
|
7
|
+
test("drop", async () => {
|
|
7
8
|
const collation = new Collation({
|
|
8
9
|
schema: "public",
|
|
9
10
|
name: "test",
|
|
@@ -23,6 +24,8 @@ describe("collation", () => {
|
|
|
23
24
|
collation,
|
|
24
25
|
});
|
|
25
26
|
|
|
27
|
+
await assertValidSql(change.serialize());
|
|
28
|
+
|
|
26
29
|
expect(change.serialize()).toBe("DROP COLLATION public.test");
|
|
27
30
|
});
|
|
28
31
|
});
|
|
@@ -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
|
AlterCollationChangeOwner,
|
|
4
5
|
AlterCollationRefreshVersion,
|
|
@@ -8,6 +9,10 @@ import { DropCollation } from "./changes/collation.drop.ts";
|
|
|
8
9
|
import { diffCollations } from "./collation.diff.ts";
|
|
9
10
|
import { Collation, type CollationProps } from "./collation.model.ts";
|
|
10
11
|
|
|
12
|
+
const ctx: Pick<ObjectDiffContext, "currentUser"> = {
|
|
13
|
+
currentUser: "postgres",
|
|
14
|
+
};
|
|
15
|
+
|
|
11
16
|
describe.concurrent("collation.diff", () => {
|
|
12
17
|
test("create and drop", () => {
|
|
13
18
|
const props: CollationProps = {
|
|
@@ -26,19 +31,11 @@ describe.concurrent("collation.diff", () => {
|
|
|
26
31
|
};
|
|
27
32
|
const c = new Collation(props);
|
|
28
33
|
|
|
29
|
-
const created = diffCollations(
|
|
30
|
-
{ currentUser: "postgres" },
|
|
31
|
-
{},
|
|
32
|
-
{ [c.stableId]: c },
|
|
33
|
-
);
|
|
34
|
+
const created = diffCollations(ctx, {}, { [c.stableId]: c });
|
|
34
35
|
expect(created).toHaveLength(1);
|
|
35
36
|
expect(created[0]).toBeInstanceOf(CreateCollation);
|
|
36
37
|
|
|
37
|
-
const dropped = diffCollations(
|
|
38
|
-
{ currentUser: "postgres" },
|
|
39
|
-
{ [c.stableId]: c },
|
|
40
|
-
{},
|
|
41
|
-
);
|
|
38
|
+
const dropped = diffCollations(ctx, { [c.stableId]: c }, {});
|
|
42
39
|
expect(dropped).toHaveLength(1);
|
|
43
40
|
expect(dropped[0]).toBeInstanceOf(DropCollation);
|
|
44
41
|
});
|
|
@@ -60,7 +57,7 @@ describe.concurrent("collation.diff", () => {
|
|
|
60
57
|
const branch = new Collation({ ...base, version: "2.0", owner: "o2" });
|
|
61
58
|
|
|
62
59
|
const changes = diffCollations(
|
|
63
|
-
|
|
60
|
+
ctx,
|
|
64
61
|
{ [main.stableId]: main },
|
|
65
62
|
{ [branch.stableId]: branch },
|
|
66
63
|
);
|
|
@@ -89,7 +86,7 @@ describe.concurrent("collation.diff", () => {
|
|
|
89
86
|
const main = new Collation({ ...base, provider: "c" });
|
|
90
87
|
const branch = new Collation({ ...base, provider: "i" });
|
|
91
88
|
const changes = diffCollations(
|
|
92
|
-
|
|
89
|
+
ctx,
|
|
93
90
|
{ [main.stableId]: main },
|
|
94
91
|
{ [branch.stableId]: branch },
|
|
95
92
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.ts";
|
|
2
|
+
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
2
3
|
import { hasNonAlterableChanges } from "../utils.ts";
|
|
3
4
|
import {
|
|
4
5
|
AlterCollationChangeOwner,
|
|
@@ -22,7 +23,7 @@ import type { Collation } from "./collation.model.ts";
|
|
|
22
23
|
* @returns A list of changes to apply to main to make it match branch.
|
|
23
24
|
*/
|
|
24
25
|
export function diffCollations(
|
|
25
|
-
ctx:
|
|
26
|
+
ctx: Pick<ObjectDiffContext, "currentUser">,
|
|
26
27
|
main: Record<string, Collation>,
|
|
27
28
|
branch: Record<string, Collation>,
|
|
28
29
|
): CollationChange[] {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DefaultPrivilegeState } from "./base.default-privileges.ts";
|
|
2
|
+
import type { Role } from "./role/role.model.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Unified context built by `diffCatalogs` and passed to per-object diff
|
|
6
|
+
* functions. Each diff declares only the keys it reads via
|
|
7
|
+
* `Pick<ObjectDiffContext, …>`, so every signature documents its actual
|
|
8
|
+
* requirements. The full object is always assignable to every narrower Pick.
|
|
9
|
+
*/
|
|
10
|
+
export interface ObjectDiffContext {
|
|
11
|
+
version: number;
|
|
12
|
+
currentUser: string;
|
|
13
|
+
defaultPrivilegeState: DefaultPrivilegeState;
|
|
14
|
+
mainRoles: Record<string, Role>;
|
|
15
|
+
skipDefaultPrivilegeSubtraction?: boolean;
|
|
16
|
+
}
|
|
@@ -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 { Domain, type DomainProps } from "../domain.model.ts";
|
|
3
4
|
import {
|
|
4
5
|
AlterDomainAddConstraint,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
|
|
14
15
|
describe.concurrent("domain", () => {
|
|
15
16
|
describe("alter", () => {
|
|
16
|
-
test("set default", () => {
|
|
17
|
+
test("set default", async () => {
|
|
17
18
|
const props: Omit<DomainProps, "default_value"> = {
|
|
18
19
|
schema: "public",
|
|
19
20
|
name: "test_domain",
|
|
@@ -39,12 +40,14 @@ describe.concurrent("domain", () => {
|
|
|
39
40
|
defaultValue: "42",
|
|
40
41
|
});
|
|
41
42
|
|
|
43
|
+
await assertValidSql(change.serialize());
|
|
44
|
+
|
|
42
45
|
expect(change.serialize()).toBe(
|
|
43
46
|
"ALTER DOMAIN public.test_domain SET DEFAULT 42",
|
|
44
47
|
);
|
|
45
48
|
});
|
|
46
49
|
|
|
47
|
-
test("drop default", () => {
|
|
50
|
+
test("drop default", async () => {
|
|
48
51
|
const props: Omit<DomainProps, "default_value"> = {
|
|
49
52
|
schema: "public",
|
|
50
53
|
name: "test_domain",
|
|
@@ -70,12 +73,14 @@ describe.concurrent("domain", () => {
|
|
|
70
73
|
domain,
|
|
71
74
|
});
|
|
72
75
|
|
|
76
|
+
await assertValidSql(change.serialize());
|
|
77
|
+
|
|
73
78
|
expect(change.serialize()).toBe(
|
|
74
79
|
"ALTER DOMAIN public.test_domain DROP DEFAULT",
|
|
75
80
|
);
|
|
76
81
|
});
|
|
77
82
|
|
|
78
|
-
test("set not null", () => {
|
|
83
|
+
test("set not null", async () => {
|
|
79
84
|
const props: Omit<DomainProps, "not_null"> = {
|
|
80
85
|
schema: "public",
|
|
81
86
|
name: "test_domain",
|
|
@@ -101,12 +106,14 @@ describe.concurrent("domain", () => {
|
|
|
101
106
|
domain,
|
|
102
107
|
});
|
|
103
108
|
|
|
109
|
+
await assertValidSql(change.serialize());
|
|
110
|
+
|
|
104
111
|
expect(change.serialize()).toBe(
|
|
105
112
|
"ALTER DOMAIN public.test_domain SET NOT NULL",
|
|
106
113
|
);
|
|
107
114
|
});
|
|
108
115
|
|
|
109
|
-
test("drop not null", () => {
|
|
116
|
+
test("drop not null", async () => {
|
|
110
117
|
const props: Omit<DomainProps, "not_null"> = {
|
|
111
118
|
schema: "public",
|
|
112
119
|
name: "test_domain",
|
|
@@ -132,12 +139,14 @@ describe.concurrent("domain", () => {
|
|
|
132
139
|
domain,
|
|
133
140
|
});
|
|
134
141
|
|
|
142
|
+
await assertValidSql(change.serialize());
|
|
143
|
+
|
|
135
144
|
expect(change.serialize()).toBe(
|
|
136
145
|
"ALTER DOMAIN public.test_domain DROP NOT NULL",
|
|
137
146
|
);
|
|
138
147
|
});
|
|
139
148
|
|
|
140
|
-
test("change owner", () => {
|
|
149
|
+
test("change owner", async () => {
|
|
141
150
|
const props: Omit<DomainProps, "owner"> = {
|
|
142
151
|
schema: "public",
|
|
143
152
|
name: "test_domain",
|
|
@@ -164,12 +173,14 @@ describe.concurrent("domain", () => {
|
|
|
164
173
|
owner: "new_owner",
|
|
165
174
|
});
|
|
166
175
|
|
|
176
|
+
await assertValidSql(change.serialize());
|
|
177
|
+
|
|
167
178
|
expect(change.serialize()).toBe(
|
|
168
179
|
"ALTER DOMAIN public.test_domain OWNER TO new_owner",
|
|
169
180
|
);
|
|
170
181
|
});
|
|
171
182
|
|
|
172
|
-
test("add constraint", () => {
|
|
183
|
+
test("add constraint", async () => {
|
|
173
184
|
const props: DomainProps = {
|
|
174
185
|
schema: "public",
|
|
175
186
|
name: "test_domain",
|
|
@@ -200,12 +211,14 @@ describe.concurrent("domain", () => {
|
|
|
200
211
|
},
|
|
201
212
|
});
|
|
202
213
|
|
|
214
|
+
await assertValidSql(change.serialize());
|
|
215
|
+
|
|
203
216
|
expect(change.serialize()).toBe(
|
|
204
217
|
"ALTER DOMAIN public.test_domain ADD CONSTRAINT test_check CHECK (VALUE > 0)",
|
|
205
218
|
);
|
|
206
219
|
});
|
|
207
220
|
|
|
208
|
-
test("add constraint not valid", () => {
|
|
221
|
+
test("add constraint not valid", async () => {
|
|
209
222
|
const props: DomainProps = {
|
|
210
223
|
schema: "public",
|
|
211
224
|
name: "test_domain",
|
|
@@ -236,12 +249,14 @@ describe.concurrent("domain", () => {
|
|
|
236
249
|
},
|
|
237
250
|
});
|
|
238
251
|
|
|
252
|
+
await assertValidSql(change.serialize());
|
|
253
|
+
|
|
239
254
|
expect(change.serialize()).toBe(
|
|
240
255
|
"ALTER DOMAIN public.test_domain ADD CONSTRAINT test_check CHECK (VALUE > 0) NOT VALID",
|
|
241
256
|
);
|
|
242
257
|
});
|
|
243
258
|
|
|
244
|
-
test("drop constraint", () => {
|
|
259
|
+
test("drop constraint", async () => {
|
|
245
260
|
const props: DomainProps = {
|
|
246
261
|
schema: "public",
|
|
247
262
|
name: "test_domain",
|
|
@@ -272,12 +287,14 @@ describe.concurrent("domain", () => {
|
|
|
272
287
|
},
|
|
273
288
|
});
|
|
274
289
|
|
|
290
|
+
await assertValidSql(change.serialize());
|
|
291
|
+
|
|
275
292
|
expect(change.serialize()).toBe(
|
|
276
293
|
"ALTER DOMAIN public.test_domain DROP CONSTRAINT test_check",
|
|
277
294
|
);
|
|
278
295
|
});
|
|
279
296
|
|
|
280
|
-
test("validate constraint", () => {
|
|
297
|
+
test("validate constraint", async () => {
|
|
281
298
|
const props: DomainProps = {
|
|
282
299
|
schema: "public",
|
|
283
300
|
name: "test_domain",
|
|
@@ -308,6 +325,8 @@ describe.concurrent("domain", () => {
|
|
|
308
325
|
},
|
|
309
326
|
});
|
|
310
327
|
|
|
328
|
+
await assertValidSql(change.serialize());
|
|
329
|
+
|
|
311
330
|
expect(change.serialize()).toBe(
|
|
312
331
|
"ALTER DOMAIN public.test_domain VALIDATE CONSTRAINT test_check",
|
|
313
332
|
);
|
|
@@ -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 { CreateDomain } from "./domain.create.ts";
|
|
4
5
|
|
|
5
6
|
describe("domain", () => {
|
|
6
|
-
test("create minimal", () => {
|
|
7
|
+
test("create minimal", async () => {
|
|
7
8
|
const domain = new Domain({
|
|
8
9
|
schema: "public",
|
|
9
10
|
name: "test_domain",
|
|
@@ -24,12 +25,14 @@ describe("domain", () => {
|
|
|
24
25
|
|
|
25
26
|
const change = new CreateDomain({ domain });
|
|
26
27
|
|
|
28
|
+
await assertValidSql(change.serialize());
|
|
29
|
+
|
|
27
30
|
expect(change.serialize()).toBe(
|
|
28
31
|
"CREATE DOMAIN public.test_domain AS integer",
|
|
29
32
|
);
|
|
30
33
|
});
|
|
31
34
|
|
|
32
|
-
test("create with all options", () => {
|
|
35
|
+
test("create with all options", async () => {
|
|
33
36
|
const domain = new Domain({
|
|
34
37
|
schema: "public",
|
|
35
38
|
name: "test_domain_all",
|
|
@@ -58,8 +61,35 @@ describe("domain", () => {
|
|
|
58
61
|
|
|
59
62
|
const change = new CreateDomain({ domain });
|
|
60
63
|
|
|
64
|
+
await assertValidSql(change.serialize());
|
|
65
|
+
|
|
61
66
|
expect(change.serialize()).toBe(
|
|
62
67
|
`CREATE DOMAIN public.test_domain_all AS custom.text[][] COLLATE mycoll DEFAULT 'hello' NOT NULL CHECK (VALUE <> '')`,
|
|
63
68
|
);
|
|
64
69
|
});
|
|
70
|
+
|
|
71
|
+
test("create with already schema-qualified base type (format_type)", async () => {
|
|
72
|
+
const domain = new Domain({
|
|
73
|
+
schema: "app",
|
|
74
|
+
name: "email_address",
|
|
75
|
+
base_type: "citext",
|
|
76
|
+
base_type_schema: "extensions",
|
|
77
|
+
base_type_str: "extensions.citext",
|
|
78
|
+
not_null: false,
|
|
79
|
+
type_modifier: null,
|
|
80
|
+
array_dimensions: null,
|
|
81
|
+
collation: null,
|
|
82
|
+
default_bin: null,
|
|
83
|
+
default_value: null,
|
|
84
|
+
owner: "test",
|
|
85
|
+
comment: null,
|
|
86
|
+
constraints: [],
|
|
87
|
+
privileges: [],
|
|
88
|
+
});
|
|
89
|
+
const change = new CreateDomain({ domain });
|
|
90
|
+
await assertValidSql(change.serialize());
|
|
91
|
+
expect(change.serialize()).toBe(
|
|
92
|
+
"CREATE DOMAIN app.email_address AS extensions.citext",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
65
95
|
});
|