@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.
- 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
|
@@ -21,7 +21,7 @@ export class AlterRlsPolicySetRoles extends AlterRlsPolicyChange {
|
|
|
21
21
|
const rolesSql = toPublic ? "PUBLIC" : targetRoles.join(", ");
|
|
22
22
|
return [
|
|
23
23
|
"ALTER POLICY",
|
|
24
|
-
|
|
24
|
+
this.policy.name,
|
|
25
25
|
"ON",
|
|
26
26
|
`${this.policy.schema}.${this.policy.table_name}`,
|
|
27
27
|
"TO",
|
|
@@ -48,7 +48,7 @@ export class AlterRlsPolicySetUsingExpression extends AlterRlsPolicyChange {
|
|
|
48
48
|
const expr = this.usingExpression ?? "true";
|
|
49
49
|
return [
|
|
50
50
|
"ALTER POLICY",
|
|
51
|
-
|
|
51
|
+
this.policy.name,
|
|
52
52
|
"ON",
|
|
53
53
|
`${this.policy.schema}.${this.policy.table_name}`,
|
|
54
54
|
"USING",
|
|
@@ -75,7 +75,7 @@ export class AlterRlsPolicySetWithCheckExpression extends AlterRlsPolicyChange {
|
|
|
75
75
|
const expr = this.withCheckExpression ?? "true";
|
|
76
76
|
return [
|
|
77
77
|
"ALTER POLICY",
|
|
78
|
-
|
|
78
|
+
this.policy.name,
|
|
79
79
|
"ON",
|
|
80
80
|
`${this.policy.schema}.${this.policy.table_name}`,
|
|
81
81
|
"WITH CHECK",
|
|
@@ -6,9 +6,9 @@ declare const rlsPolicyPropsSchema: z.ZodObject<{
|
|
|
6
6
|
name: z.ZodString;
|
|
7
7
|
table_name: z.ZodString;
|
|
8
8
|
command: z.ZodEnum<{
|
|
9
|
+
a: "a";
|
|
9
10
|
r: "r";
|
|
10
11
|
w: "w";
|
|
11
|
-
a: "a";
|
|
12
12
|
d: "d";
|
|
13
13
|
"*": "*";
|
|
14
14
|
}>;
|
|
@@ -39,7 +39,7 @@ export declare class RlsPolicy extends BasePgModel {
|
|
|
39
39
|
name: string;
|
|
40
40
|
};
|
|
41
41
|
get dataFields(): {
|
|
42
|
-
command: "
|
|
42
|
+
command: "a" | "r" | "w" | "d" | "*";
|
|
43
43
|
permissive: boolean;
|
|
44
44
|
roles: string[];
|
|
45
45
|
using_expression: string | null;
|
|
@@ -31,8 +31,15 @@ export function diffRoles(ctx, main, branch) {
|
|
|
31
31
|
if (role.comment !== null) {
|
|
32
32
|
changes.push(new CreateCommentOnRole({ role }));
|
|
33
33
|
}
|
|
34
|
-
// MEMBERSHIPS: Grant memberships immediately after role creation
|
|
34
|
+
// MEMBERSHIPS: Grant memberships immediately after role creation.
|
|
35
|
+
// Members are already deduplicated by the Role model constructor.
|
|
35
36
|
for (const membership of role.members) {
|
|
37
|
+
// Skip memberships where the member is the grantor (auto-created by
|
|
38
|
+
// CREATE ROLE — re-granting them, especially WITH ADMIN OPTION, fails
|
|
39
|
+
// with "ADMIN option cannot be granted back to your own grantor").
|
|
40
|
+
if (membership.grantor === membership.member) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
36
43
|
changes.push(new GrantRoleMembership({
|
|
37
44
|
role,
|
|
38
45
|
member: membership.member,
|
|
@@ -45,6 +52,8 @@ export function diffRoles(ctx, main, branch) {
|
|
|
45
52
|
}
|
|
46
53
|
// DEFAULT PRIVILEGES: Grant default privileges immediately after role creation
|
|
47
54
|
for (const defaultPriv of role.default_privileges) {
|
|
55
|
+
if (defaultPriv.is_implicit)
|
|
56
|
+
continue;
|
|
48
57
|
if (defaultPriv.privileges.length === 0)
|
|
49
58
|
continue;
|
|
50
59
|
const grantGroups = new Map();
|
|
@@ -163,11 +172,18 @@ export function diffRoles(ctx, main, branch) {
|
|
|
163
172
|
}
|
|
164
173
|
}
|
|
165
174
|
// MEMBERSHIPS
|
|
175
|
+
// Members are already deduplicated by the Role model constructor.
|
|
166
176
|
const mainMembers = new Map(mainRole.members.map((m) => [m.member, m]));
|
|
167
177
|
const branchMembers = new Map(branchRole.members.map((m) => [m.member, m]));
|
|
168
178
|
// Find new members to grant
|
|
169
179
|
for (const [member, membership] of branchMembers) {
|
|
170
180
|
if (!mainMembers.has(member)) {
|
|
181
|
+
// Skip memberships where the member is the grantor (auto-created by
|
|
182
|
+
// CREATE ROLE — re-granting them fails with "ADMIN option cannot be
|
|
183
|
+
// granted back to your own grantor").
|
|
184
|
+
if (membership.grantor === membership.member) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
171
187
|
changes.push(new GrantRoleMembership({
|
|
172
188
|
role: branchRole,
|
|
173
189
|
member: membership.member,
|
|
@@ -224,6 +240,11 @@ export function diffRoles(ctx, main, branch) {
|
|
|
224
240
|
}));
|
|
225
241
|
}
|
|
226
242
|
if (toGrant.admin || toGrant.inherit || toGrant.set) {
|
|
243
|
+
// Skip granting options back to the grantor (same restriction as
|
|
244
|
+
// for newly created roles).
|
|
245
|
+
if (branchMembership.grantor === branchMembership.member) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
227
248
|
changes.push(new GrantRoleMembership({
|
|
228
249
|
role: branchRole,
|
|
229
250
|
member: branchMembership.member,
|
|
@@ -23,17 +23,18 @@ declare const rolePropsSchema: z.ZodObject<{
|
|
|
23
23
|
default_privileges: z.ZodArray<z.ZodObject<{
|
|
24
24
|
in_schema: z.ZodNullable<z.ZodString>;
|
|
25
25
|
objtype: z.ZodEnum<{
|
|
26
|
+
n: "n";
|
|
26
27
|
r: "r";
|
|
27
|
-
S: "S";
|
|
28
28
|
f: "f";
|
|
29
|
+
S: "S";
|
|
29
30
|
T: "T";
|
|
30
|
-
n: "n";
|
|
31
31
|
}>;
|
|
32
32
|
grantee: z.ZodString;
|
|
33
33
|
privileges: z.ZodArray<z.ZodObject<{
|
|
34
34
|
privilege: z.ZodString;
|
|
35
35
|
grantable: z.ZodBoolean;
|
|
36
36
|
}, z.z.core.$strip>>;
|
|
37
|
+
is_implicit: z.ZodBoolean;
|
|
37
38
|
}, z.z.core.$strip>>;
|
|
38
39
|
}, z.z.core.$strip>;
|
|
39
40
|
export type RoleProps = z.infer<typeof rolePropsSchema>;
|
|
@@ -80,7 +81,7 @@ export declare class Role extends BasePgModel {
|
|
|
80
81
|
grantable: boolean;
|
|
81
82
|
}[];
|
|
82
83
|
in_schema: string | null;
|
|
83
|
-
objtype: "
|
|
84
|
+
objtype: "n" | "r" | "f" | "S" | "T";
|
|
84
85
|
grantee: string;
|
|
85
86
|
}[];
|
|
86
87
|
};
|
|
@@ -13,6 +13,7 @@ const defaultPrivilegeSchema = z.object({
|
|
|
13
13
|
objtype: z.enum(["r", "S", "f", "T", "n"]),
|
|
14
14
|
grantee: z.string(),
|
|
15
15
|
privileges: z.array(z.object({ privilege: z.string(), grantable: z.boolean() })),
|
|
16
|
+
is_implicit: z.boolean(),
|
|
16
17
|
});
|
|
17
18
|
const rolePropsSchema = z.object({
|
|
18
19
|
name: z.string(),
|
|
@@ -58,7 +59,7 @@ export class Role extends BasePgModel {
|
|
|
58
59
|
this.can_bypass_rls = props.can_bypass_rls;
|
|
59
60
|
this.config = props.config;
|
|
60
61
|
this.comment = props.comment;
|
|
61
|
-
this.members = props.members;
|
|
62
|
+
this.members = deduplicateMembers(props.members);
|
|
62
63
|
this.default_privileges = props.default_privileges;
|
|
63
64
|
}
|
|
64
65
|
get stableId() {
|
|
@@ -77,13 +78,16 @@ export class Role extends BasePgModel {
|
|
|
77
78
|
Number(a.inherit_option ?? false) - Number(b.inherit_option ?? false) ||
|
|
78
79
|
Number(a.set_option ?? false) - Number(b.set_option ?? false));
|
|
79
80
|
});
|
|
80
|
-
const sortedDefaultPrivs = [...this.default_privileges].map((dp) =>
|
|
81
|
-
...dp
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
const sortedDefaultPrivs = [...this.default_privileges].map((dp) => {
|
|
82
|
+
const { is_implicit: _, ...rest } = dp;
|
|
83
|
+
return {
|
|
84
|
+
...rest,
|
|
85
|
+
privileges: [...dp.privileges].sort((a, b) => {
|
|
86
|
+
return (a.privilege.localeCompare(b.privilege) ||
|
|
87
|
+
Number(a.grantable) - Number(b.grantable));
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
});
|
|
87
91
|
sortedDefaultPrivs.sort((a, b) => {
|
|
88
92
|
return ((a.in_schema ?? "").localeCompare(b.in_schema ?? "") ||
|
|
89
93
|
a.objtype.localeCompare(b.objtype) ||
|
|
@@ -105,6 +109,46 @@ export class Role extends BasePgModel {
|
|
|
105
109
|
};
|
|
106
110
|
}
|
|
107
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Deduplicate members by member name.
|
|
114
|
+
*
|
|
115
|
+
* In PostgreSQL 16+, `pg_auth_members` can have multiple rows for the same
|
|
116
|
+
* (roleid, member) pair with different grantors. Merge them into a single
|
|
117
|
+
* entry per member, combining options with OR so the most permissive wins.
|
|
118
|
+
*
|
|
119
|
+
* When merging, prefer a non-self grantor (grantor !== member) so that
|
|
120
|
+
* downstream code can detect true self-grants (auto-created by CREATE ROLE)
|
|
121
|
+
* by checking `grantor === member`.
|
|
122
|
+
*/
|
|
123
|
+
function deduplicateMembers(members) {
|
|
124
|
+
const map = new Map();
|
|
125
|
+
for (const m of members) {
|
|
126
|
+
const existing = map.get(m.member);
|
|
127
|
+
if (existing) {
|
|
128
|
+
// admin_option is always boolean (non-nullable in schema)
|
|
129
|
+
existing.admin_option = existing.admin_option || m.admin_option;
|
|
130
|
+
// inherit_option and set_option are nullish (only available in PG 16+)
|
|
131
|
+
if (m.inherit_option != null) {
|
|
132
|
+
existing.inherit_option =
|
|
133
|
+
(existing.inherit_option ?? false) || m.inherit_option;
|
|
134
|
+
}
|
|
135
|
+
if (m.set_option != null) {
|
|
136
|
+
existing.set_option = (existing.set_option ?? false) || m.set_option;
|
|
137
|
+
}
|
|
138
|
+
// Prefer a non-self grantor so diff can detect true self-grants.
|
|
139
|
+
// Once a non-self grantor is chosen the value is kept (the specific
|
|
140
|
+
// non-self grantor doesn't matter — only the self vs non-self
|
|
141
|
+
// distinction is used downstream).
|
|
142
|
+
if (existing.grantor === existing.member && m.grantor !== m.member) {
|
|
143
|
+
existing.grantor = m.grantor;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
map.set(m.member, { ...m });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return [...map.values()];
|
|
151
|
+
}
|
|
108
152
|
export async function extractRoles(pool) {
|
|
109
153
|
// Check PostgreSQL version capabilities for membership options
|
|
110
154
|
const { rows: capabilitiesRows } = await pool.query(sql `
|
|
@@ -172,13 +216,15 @@ export async function extractRoles(pool) {
|
|
|
172
216
|
THEN 'PUBLIC'
|
|
173
217
|
ELSE s.grantee::regrole::text
|
|
174
218
|
END,
|
|
175
|
-
'privileges', s.privileges
|
|
219
|
+
'privileges', s.privileges,
|
|
220
|
+
'is_implicit', s.is_implicit
|
|
176
221
|
)
|
|
177
222
|
ORDER BY s.defaclnamespace NULLS FIRST,
|
|
178
223
|
s.defaclobjtype,
|
|
179
224
|
s.grantee
|
|
180
225
|
)
|
|
181
226
|
FROM (
|
|
227
|
+
-- Explicit entries from pg_default_acl
|
|
182
228
|
SELECT
|
|
183
229
|
d.defaclnamespace,
|
|
184
230
|
d.defaclobjtype,
|
|
@@ -189,12 +235,41 @@ export async function extractRoles(pool) {
|
|
|
189
235
|
'grantable', x.is_grantable
|
|
190
236
|
)
|
|
191
237
|
ORDER BY x.privilege_type, x.is_grantable
|
|
192
|
-
) AS privileges
|
|
238
|
+
) AS privileges,
|
|
239
|
+
false AS is_implicit
|
|
193
240
|
FROM pg_default_acl d
|
|
194
241
|
CROSS JOIN LATERAL aclexplode(COALESCE(d.defaclacl, ARRAY[]::aclitem[]))
|
|
195
242
|
AS x(grantor, grantee, privilege_type, is_grantable)
|
|
196
243
|
WHERE d.defaclrole = r.oid
|
|
197
244
|
GROUP BY d.defaclnamespace, d.defaclobjtype, x.grantee
|
|
245
|
+
UNION ALL
|
|
246
|
+
-- Implicit defaults from acldefault() for objtypes without a
|
|
247
|
+
-- global pg_default_acl entry. PostgreSQL applies these implicit
|
|
248
|
+
-- defaults (e.g. PUBLIC gets EXECUTE on functions) when no
|
|
249
|
+
-- explicit ALTER DEFAULT PRIVILEGES has been issued. Including
|
|
250
|
+
-- them lets the diff detect REVOKEs of implicit grants.
|
|
251
|
+
SELECT
|
|
252
|
+
0 AS defaclnamespace,
|
|
253
|
+
v.t::"char" AS defaclobjtype,
|
|
254
|
+
x.grantee,
|
|
255
|
+
json_agg(
|
|
256
|
+
json_build_object(
|
|
257
|
+
'privilege', x.privilege_type,
|
|
258
|
+
'grantable', x.is_grantable
|
|
259
|
+
)
|
|
260
|
+
ORDER BY x.privilege_type, x.is_grantable
|
|
261
|
+
) AS privileges,
|
|
262
|
+
true AS is_implicit
|
|
263
|
+
FROM (VALUES ('r'), ('S'), ('f'), ('T'), ('n')) AS v(t)
|
|
264
|
+
CROSS JOIN LATERAL aclexplode(acldefault(v.t::"char", r.oid))
|
|
265
|
+
AS x(grantor, grantee, privilege_type, is_grantable)
|
|
266
|
+
WHERE NOT EXISTS (
|
|
267
|
+
SELECT 1 FROM pg_default_acl d2
|
|
268
|
+
WHERE d2.defaclrole = r.oid
|
|
269
|
+
AND d2.defaclobjtype = v.t::"char"
|
|
270
|
+
AND d2.defaclnamespace = 0
|
|
271
|
+
)
|
|
272
|
+
GROUP BY v.t, x.grantee
|
|
198
273
|
) AS s
|
|
199
274
|
),
|
|
200
275
|
'[]'
|
|
@@ -263,13 +338,15 @@ export async function extractRoles(pool) {
|
|
|
263
338
|
THEN 'PUBLIC'
|
|
264
339
|
ELSE s.grantee::regrole::text
|
|
265
340
|
END,
|
|
266
|
-
'privileges', s.privileges
|
|
341
|
+
'privileges', s.privileges,
|
|
342
|
+
'is_implicit', s.is_implicit
|
|
267
343
|
)
|
|
268
344
|
ORDER BY s.defaclnamespace NULLS FIRST,
|
|
269
345
|
s.defaclobjtype,
|
|
270
346
|
s.grantee
|
|
271
347
|
)
|
|
272
348
|
FROM (
|
|
349
|
+
-- Explicit entries from pg_default_acl
|
|
273
350
|
SELECT
|
|
274
351
|
d.defaclnamespace,
|
|
275
352
|
d.defaclobjtype,
|
|
@@ -280,12 +357,41 @@ export async function extractRoles(pool) {
|
|
|
280
357
|
'grantable', x.is_grantable
|
|
281
358
|
)
|
|
282
359
|
ORDER BY x.privilege_type, x.is_grantable
|
|
283
|
-
) AS privileges
|
|
360
|
+
) AS privileges,
|
|
361
|
+
false AS is_implicit
|
|
284
362
|
FROM pg_default_acl d
|
|
285
363
|
CROSS JOIN LATERAL aclexplode(COALESCE(d.defaclacl, ARRAY[]::aclitem[]))
|
|
286
364
|
AS x(grantor, grantee, privilege_type, is_grantable)
|
|
287
365
|
WHERE d.defaclrole = r.oid
|
|
288
366
|
GROUP BY d.defaclnamespace, d.defaclobjtype, x.grantee
|
|
367
|
+
UNION ALL
|
|
368
|
+
-- Implicit defaults from acldefault() for objtypes without a
|
|
369
|
+
-- global pg_default_acl entry. PostgreSQL applies these implicit
|
|
370
|
+
-- defaults (e.g. PUBLIC gets EXECUTE on functions) when no
|
|
371
|
+
-- explicit ALTER DEFAULT PRIVILEGES has been issued. Including
|
|
372
|
+
-- them lets the diff detect REVOKEs of implicit grants.
|
|
373
|
+
SELECT
|
|
374
|
+
0 AS defaclnamespace,
|
|
375
|
+
v.t::"char" AS defaclobjtype,
|
|
376
|
+
x.grantee,
|
|
377
|
+
json_agg(
|
|
378
|
+
json_build_object(
|
|
379
|
+
'privilege', x.privilege_type,
|
|
380
|
+
'grantable', x.is_grantable
|
|
381
|
+
)
|
|
382
|
+
ORDER BY x.privilege_type, x.is_grantable
|
|
383
|
+
) AS privileges,
|
|
384
|
+
true AS is_implicit
|
|
385
|
+
FROM (VALUES ('r'), ('S'), ('f'), ('T'), ('n')) AS v(t)
|
|
386
|
+
CROSS JOIN LATERAL aclexplode(acldefault(v.t::"char", r.oid))
|
|
387
|
+
AS x(grantor, grantee, privilege_type, is_grantable)
|
|
388
|
+
WHERE NOT EXISTS (
|
|
389
|
+
SELECT 1 FROM pg_default_acl d2
|
|
390
|
+
WHERE d2.defaclrole = r.oid
|
|
391
|
+
AND d2.defaclobjtype = v.t::"char"
|
|
392
|
+
AND d2.defaclnamespace = 0
|
|
393
|
+
)
|
|
394
|
+
GROUP BY v.t, x.grantee
|
|
289
395
|
) AS s
|
|
290
396
|
),
|
|
291
397
|
'[]'
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Role } from "../role/role.model.ts";
|
|
1
|
+
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
3
2
|
import type { SchemaChange } from "./changes/schema.types.ts";
|
|
4
3
|
import type { Schema } from "./schema.model.ts";
|
|
5
4
|
/**
|
|
@@ -10,9 +9,4 @@ import type { Schema } from "./schema.model.ts";
|
|
|
10
9
|
* @param branch - The schemas in the branch catalog.
|
|
11
10
|
* @returns A list of changes to apply to main to make it match branch.
|
|
12
11
|
*/
|
|
13
|
-
export declare function diffSchemas(ctx:
|
|
14
|
-
version: number;
|
|
15
|
-
currentUser: string;
|
|
16
|
-
defaultPrivilegeState: DefaultPrivilegeState;
|
|
17
|
-
mainRoles: Record<string, Role>;
|
|
18
|
-
}, main: Record<string, Schema>, branch: Record<string, Schema>): SchemaChange[];
|
|
12
|
+
export declare function diffSchemas(ctx: Pick<ObjectDiffContext, "version" | "currentUser" | "defaultPrivilegeState">, main: Record<string, Schema>, branch: Record<string, Schema>): SchemaChange[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.js";
|
|
2
|
-
import { diffPrivileges,
|
|
2
|
+
import { diffPrivileges, emitObjectPrivilegeChanges, } from "../base.privilege-diff.js";
|
|
3
3
|
import { AlterSchemaChangeOwner } from "./changes/schema.alter.js";
|
|
4
4
|
import { CreateCommentOnSchema, DropCommentOnSchema, } from "./changes/schema.comment.js";
|
|
5
5
|
import { CreateSchema } from "./changes/schema.create.js";
|
|
@@ -29,47 +29,18 @@ export function diffSchemas(ctx, main, branch) {
|
|
|
29
29
|
// needed to reach the final desired state.
|
|
30
30
|
// Note: Schemas don't have a schema property, so we pass empty string
|
|
31
31
|
const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(ctx.currentUser, "schema", "");
|
|
32
|
+
const creatorFilteredDefaults = sc.owner !== ctx.currentUser
|
|
33
|
+
? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
|
|
34
|
+
: effectiveDefaults;
|
|
32
35
|
const desiredPrivileges = sc.privileges;
|
|
33
36
|
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
34
37
|
// and shouldn't be compared. Use the schema owner as the reference.
|
|
35
|
-
const privilegeResults = diffPrivileges(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
void grantable;
|
|
42
|
-
changes.push(new GrantSchemaPrivileges({
|
|
43
|
-
schema: sc,
|
|
44
|
-
grantee,
|
|
45
|
-
privileges: list,
|
|
46
|
-
version: ctx.version,
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// Generate revoke changes
|
|
51
|
-
if (result.revokes.length > 0) {
|
|
52
|
-
const revokeGroups = groupPrivilegesByGrantable(result.revokes);
|
|
53
|
-
for (const [grantable, list] of revokeGroups) {
|
|
54
|
-
void grantable;
|
|
55
|
-
changes.push(new RevokeSchemaPrivileges({
|
|
56
|
-
schema: sc,
|
|
57
|
-
grantee,
|
|
58
|
-
privileges: list,
|
|
59
|
-
version: ctx.version,
|
|
60
|
-
}));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Generate revoke grant option changes
|
|
64
|
-
if (result.revokeGrantOption.length > 0) {
|
|
65
|
-
changes.push(new RevokeGrantOptionSchemaPrivileges({
|
|
66
|
-
schema: sc,
|
|
67
|
-
grantee,
|
|
68
|
-
privilegeNames: result.revokeGrantOption,
|
|
69
|
-
version: ctx.version,
|
|
70
|
-
}));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
38
|
+
const privilegeResults = diffPrivileges(creatorFilteredDefaults, desiredPrivileges, sc.owner);
|
|
39
|
+
changes.push(...emitObjectPrivilegeChanges(privilegeResults, sc, sc, "schema", {
|
|
40
|
+
Grant: GrantSchemaPrivileges,
|
|
41
|
+
Revoke: RevokeSchemaPrivileges,
|
|
42
|
+
RevokeGrantOption: RevokeGrantOptionSchemaPrivileges,
|
|
43
|
+
}, ctx.version));
|
|
73
44
|
}
|
|
74
45
|
for (const schemaId of dropped) {
|
|
75
46
|
changes.push(new DropSchema({ schema: main[schemaId] }));
|
|
@@ -96,44 +67,12 @@ export function diffSchemas(ctx, main, branch) {
|
|
|
96
67
|
// PRIVILEGES
|
|
97
68
|
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
98
69
|
// and shouldn't be compared. Use branch owner as the reference.
|
|
99
|
-
const privilegeResults = diffPrivileges(mainSchema.privileges, branchSchema.privileges, branchSchema.owner
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
void grantable;
|
|
106
|
-
changes.push(new GrantSchemaPrivileges({
|
|
107
|
-
schema: branchSchema,
|
|
108
|
-
grantee,
|
|
109
|
-
privileges: list,
|
|
110
|
-
version: ctx.version,
|
|
111
|
-
}));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
// Generate revoke changes
|
|
115
|
-
if (result.revokes.length > 0) {
|
|
116
|
-
const revokeGroups = groupPrivilegesByGrantable(result.revokes);
|
|
117
|
-
for (const [grantable, list] of revokeGroups) {
|
|
118
|
-
void grantable;
|
|
119
|
-
changes.push(new RevokeSchemaPrivileges({
|
|
120
|
-
schema: mainSchema,
|
|
121
|
-
grantee,
|
|
122
|
-
privileges: list,
|
|
123
|
-
version: ctx.version,
|
|
124
|
-
}));
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Generate revoke grant option changes
|
|
128
|
-
if (result.revokeGrantOption.length > 0) {
|
|
129
|
-
changes.push(new RevokeGrantOptionSchemaPrivileges({
|
|
130
|
-
schema: mainSchema,
|
|
131
|
-
grantee,
|
|
132
|
-
privilegeNames: result.revokeGrantOption,
|
|
133
|
-
version: ctx.version,
|
|
134
|
-
}));
|
|
135
|
-
}
|
|
136
|
-
}
|
|
70
|
+
const privilegeResults = diffPrivileges(mainSchema.privileges, branchSchema.privileges, branchSchema.owner);
|
|
71
|
+
changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchSchema, mainSchema, "schema", {
|
|
72
|
+
Grant: GrantSchemaPrivileges,
|
|
73
|
+
Revoke: RevokeSchemaPrivileges,
|
|
74
|
+
RevokeGrantOption: RevokeGrantOptionSchemaPrivileges,
|
|
75
|
+
}, ctx.version));
|
|
137
76
|
// Note: Schema renaming would also use ALTER SCHEMA ... RENAME TO ...
|
|
138
77
|
// But since our Schema model uses 'schema' as the identity field,
|
|
139
78
|
// a name change would be handled as drop + create by diffObjects()
|
|
@@ -70,7 +70,7 @@ export async function extractSchemas(pool) {
|
|
|
70
70
|
)
|
|
71
71
|
order by x.grantee, x.privilege_type
|
|
72
72
|
)
|
|
73
|
-
from lateral aclexplode(nspacl) as x(grantor, grantee, privilege_type, is_grantable)
|
|
73
|
+
from lateral aclexplode(COALESCE(nspacl, acldefault('n', nspowner))) as x(grantor, grantee, privilege_type, is_grantable)
|
|
74
74
|
), '[]'
|
|
75
75
|
) as privileges
|
|
76
76
|
from
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Role } from "../role/role.model.ts";
|
|
1
|
+
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
3
2
|
import type { Table } from "../table/table.model.ts";
|
|
4
3
|
import type { SequenceChange } from "./changes/sequence.types.ts";
|
|
5
4
|
import type { Sequence } from "./sequence.model.ts";
|
|
@@ -12,9 +11,4 @@ import type { Sequence } from "./sequence.model.ts";
|
|
|
12
11
|
* @param branchTables - The tables in the branch catalog (used to check if owning tables are being dropped).
|
|
13
12
|
* @returns A list of changes to apply to main to make it match branch.
|
|
14
13
|
*/
|
|
15
|
-
export declare function diffSequences(ctx:
|
|
16
|
-
version: number;
|
|
17
|
-
currentUser: string;
|
|
18
|
-
defaultPrivilegeState: DefaultPrivilegeState;
|
|
19
|
-
mainRoles: Record<string, Role>;
|
|
20
|
-
}, main: Record<string, Sequence>, branch: Record<string, Sequence>, branchTables?: Record<string, Table>): SequenceChange[];
|
|
14
|
+
export declare function diffSequences(ctx: Pick<ObjectDiffContext, "version" | "currentUser" | "defaultPrivilegeState">, main: Record<string, Sequence>, branch: Record<string, Sequence>, branchTables?: Record<string, Table>): SequenceChange[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.js";
|
|
2
|
-
import { diffPrivileges,
|
|
2
|
+
import { diffPrivileges, emitObjectPrivilegeChanges, } from "../base.privilege-diff.js";
|
|
3
3
|
import { hasNonAlterableChanges } from "../utils.js";
|
|
4
4
|
import { AlterSequenceSetOptions, AlterSequenceSetOwnedBy, } from "./changes/sequence.alter.js";
|
|
5
5
|
import { CreateCommentOnSequence, DropCommentOnSequence, } from "./changes/sequence.comment.js";
|
|
@@ -43,48 +43,18 @@ export function diffSequences(ctx, main, branch, branchTables = {}) {
|
|
|
43
43
|
// We compare default privileges against desired privileges to generate REVOKE/GRANT statements
|
|
44
44
|
// needed to reach the final desired state.
|
|
45
45
|
const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(ctx.currentUser, "sequence", createdSeq.schema ?? "");
|
|
46
|
+
const creatorFilteredDefaults = createdSeq.owner !== ctx.currentUser
|
|
47
|
+
? effectiveDefaults.filter((p) => p.grantee !== ctx.currentUser)
|
|
48
|
+
: effectiveDefaults;
|
|
46
49
|
const desiredPrivileges = createdSeq.privileges;
|
|
47
50
|
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
48
51
|
// and shouldn't be compared. Use the sequence owner as the reference.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
for (const [grantable, list] of grantGroups) {
|
|
56
|
-
void grantable;
|
|
57
|
-
changes.push(new GrantSequencePrivileges({
|
|
58
|
-
sequence: createdSeq,
|
|
59
|
-
grantee,
|
|
60
|
-
privileges: list,
|
|
61
|
-
version: ctx.version,
|
|
62
|
-
}));
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Generate revoke changes
|
|
66
|
-
if (result.revokes.length > 0) {
|
|
67
|
-
const revokeGroups = groupPrivilegesByGrantable(result.revokes);
|
|
68
|
-
for (const [grantable, list] of revokeGroups) {
|
|
69
|
-
void grantable;
|
|
70
|
-
changes.push(new RevokeSequencePrivileges({
|
|
71
|
-
sequence: createdSeq,
|
|
72
|
-
grantee,
|
|
73
|
-
privileges: list,
|
|
74
|
-
version: ctx.version,
|
|
75
|
-
}));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// Generate revoke grant option changes
|
|
79
|
-
if (result.revokeGrantOption.length > 0) {
|
|
80
|
-
changes.push(new RevokeGrantOptionSequencePrivileges({
|
|
81
|
-
sequence: createdSeq,
|
|
82
|
-
grantee,
|
|
83
|
-
privilegeNames: result.revokeGrantOption,
|
|
84
|
-
version: ctx.version,
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
52
|
+
const privilegeResults = diffPrivileges(creatorFilteredDefaults, desiredPrivileges, createdSeq.owner);
|
|
53
|
+
changes.push(...emitObjectPrivilegeChanges(privilegeResults, createdSeq, createdSeq, "sequence", {
|
|
54
|
+
Grant: GrantSequencePrivileges,
|
|
55
|
+
Revoke: RevokeSequencePrivileges,
|
|
56
|
+
RevokeGrantOption: RevokeGrantOptionSequencePrivileges,
|
|
57
|
+
}, ctx.version));
|
|
88
58
|
}
|
|
89
59
|
for (const sequenceId of dropped) {
|
|
90
60
|
const sequence = main[sequenceId];
|
|
@@ -210,45 +180,12 @@ export function diffSequences(ctx, main, branch, branchTables = {}) {
|
|
|
210
180
|
// PRIVILEGES
|
|
211
181
|
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
212
182
|
// and shouldn't be compared. Use branch owner as the reference.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
for (const [grantable, list] of grantGroups) {
|
|
220
|
-
void grantable;
|
|
221
|
-
changes.push(new GrantSequencePrivileges({
|
|
222
|
-
sequence: branchSequence,
|
|
223
|
-
grantee,
|
|
224
|
-
privileges: list,
|
|
225
|
-
version: ctx.version,
|
|
226
|
-
}));
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
// Generate revoke changes
|
|
230
|
-
if (result.revokes.length > 0) {
|
|
231
|
-
const revokeGroups = groupPrivilegesByGrantable(result.revokes);
|
|
232
|
-
for (const [grantable, list] of revokeGroups) {
|
|
233
|
-
void grantable;
|
|
234
|
-
changes.push(new RevokeSequencePrivileges({
|
|
235
|
-
sequence: mainSequence,
|
|
236
|
-
grantee,
|
|
237
|
-
privileges: list,
|
|
238
|
-
version: ctx.version,
|
|
239
|
-
}));
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
// Generate revoke grant option changes
|
|
243
|
-
if (result.revokeGrantOption.length > 0) {
|
|
244
|
-
changes.push(new RevokeGrantOptionSequencePrivileges({
|
|
245
|
-
sequence: mainSequence,
|
|
246
|
-
grantee,
|
|
247
|
-
privilegeNames: result.revokeGrantOption,
|
|
248
|
-
version: ctx.version,
|
|
249
|
-
}));
|
|
250
|
-
}
|
|
251
|
-
}
|
|
183
|
+
const privilegeResults = diffPrivileges(mainSequence.privileges, branchSequence.privileges, branchSequence.owner);
|
|
184
|
+
changes.push(...emitObjectPrivilegeChanges(privilegeResults, branchSequence, mainSequence, "sequence", {
|
|
185
|
+
Grant: GrantSequencePrivileges,
|
|
186
|
+
Revoke: RevokeSequencePrivileges,
|
|
187
|
+
RevokeGrantOption: RevokeGrantOptionSequencePrivileges,
|
|
188
|
+
}, ctx.version));
|
|
252
189
|
// Note: Sequence renaming would also use ALTER SEQUENCE ... RENAME TO ...
|
|
253
190
|
// But since our Sequence model uses 'name' as the identity field,
|
|
254
191
|
// a name change would be handled as drop + create by diffObjects()
|
|
@@ -132,7 +132,7 @@ select
|
|
|
132
132
|
)
|
|
133
133
|
order by x.grantee, x.privilege_type
|
|
134
134
|
)
|
|
135
|
-
from lateral aclexplode(c.relacl) as x(grantor, grantee, privilege_type, is_grantable)
|
|
135
|
+
from lateral aclexplode(COALESCE(c.relacl, acldefault('S', c.relowner))) as x(grantor, grantee, privilege_type, is_grantable)
|
|
136
136
|
), '[]'
|
|
137
137
|
) as privileges,
|
|
138
138
|
c.relowner::regrole::text as owner
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
+
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
1
2
|
import type { SubscriptionChange } from "./changes/subscription.types.ts";
|
|
2
3
|
import type { Subscription } from "./subscription.model.ts";
|
|
3
|
-
export declare function diffSubscriptions(ctx:
|
|
4
|
-
currentUser: string;
|
|
5
|
-
}, main: Record<string, Subscription>, branch: Record<string, Subscription>): SubscriptionChange[];
|
|
4
|
+
export declare function diffSubscriptions(ctx: Pick<ObjectDiffContext, "currentUser">, main: Record<string, Subscription>, branch: Record<string, Subscription>): SubscriptionChange[];
|