@supabase/pg-delta 1.0.0-alpha.22 → 1.0.0-alpha.23
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/dist/core/catalog.model.js +1 -0
- package/dist/core/integrations/filter/flatten.js +13 -0
- package/dist/core/objects/aggregate/aggregate.diff.js +16 -0
- package/dist/core/objects/aggregate/aggregate.model.d.ts +10 -0
- package/dist/core/objects/aggregate/aggregate.model.js +19 -1
- package/dist/core/objects/aggregate/changes/aggregate.base.d.ts +1 -1
- package/dist/core/objects/aggregate/changes/aggregate.security-label.d.ts +28 -0
- package/dist/core/objects/aggregate/changes/aggregate.security-label.js +64 -0
- package/dist/core/objects/aggregate/changes/aggregate.types.d.ts +2 -1
- package/dist/core/objects/base.model.d.ts +8 -0
- package/dist/core/objects/base.model.js +2 -0
- package/dist/core/objects/domain/changes/domain.base.d.ts +1 -1
- package/dist/core/objects/domain/changes/domain.security-label.d.ts +28 -0
- package/dist/core/objects/domain/changes/domain.security-label.js +61 -0
- package/dist/core/objects/domain/changes/domain.types.d.ts +2 -1
- package/dist/core/objects/domain/domain.diff.js +16 -0
- package/dist/core/objects/domain/domain.model.d.ts +10 -0
- package/dist/core/objects/domain/domain.model.js +19 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.base.d.ts +1 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.d.ts +28 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.js +61 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.types.d.ts +2 -1
- package/dist/core/objects/event-trigger/event-trigger.diff.js +16 -0
- package/dist/core/objects/event-trigger/event-trigger.model.d.ts +10 -0
- package/dist/core/objects/event-trigger/event-trigger.model.js +19 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.d.ts +1 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.d.ts +28 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.js +61 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.d.ts +2 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +22 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +20 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.base.d.ts +1 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.d.ts +28 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.js +61 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.types.d.ts +2 -1
- package/dist/core/objects/materialized-view/materialized-view.diff.js +18 -0
- package/dist/core/objects/materialized-view/materialized-view.model.d.ts +22 -0
- package/dist/core/objects/materialized-view/materialized-view.model.js +20 -1
- package/dist/core/objects/procedure/changes/procedure.base.d.ts +1 -1
- package/dist/core/objects/procedure/changes/procedure.security-label.d.ts +28 -0
- package/dist/core/objects/procedure/changes/procedure.security-label.js +69 -0
- package/dist/core/objects/procedure/changes/procedure.types.d.ts +2 -1
- package/dist/core/objects/procedure/procedure.diff.js +16 -0
- package/dist/core/objects/procedure/procedure.model.d.ts +10 -0
- package/dist/core/objects/procedure/procedure.model.js +19 -1
- package/dist/core/objects/publication/changes/publication.base.d.ts +1 -1
- package/dist/core/objects/publication/changes/publication.security-label.d.ts +28 -0
- package/dist/core/objects/publication/changes/publication.security-label.js +61 -0
- package/dist/core/objects/publication/changes/publication.types.d.ts +2 -1
- package/dist/core/objects/publication/publication.diff.js +16 -0
- package/dist/core/objects/publication/publication.model.d.ts +14 -0
- package/dist/core/objects/publication/publication.model.js +20 -1
- package/dist/core/objects/role/changes/role.base.d.ts +1 -1
- package/dist/core/objects/role/changes/role.security-label.d.ts +28 -0
- package/dist/core/objects/role/changes/role.security-label.js +61 -0
- package/dist/core/objects/role/changes/role.types.d.ts +2 -1
- package/dist/core/objects/role/role.diff.js +16 -0
- package/dist/core/objects/role/role.model.d.ts +10 -0
- package/dist/core/objects/role/role.model.js +29 -0
- package/dist/core/objects/schema/changes/schema.base.d.ts +1 -1
- package/dist/core/objects/schema/changes/schema.security-label.d.ts +28 -0
- package/dist/core/objects/schema/changes/schema.security-label.js +61 -0
- package/dist/core/objects/schema/changes/schema.types.d.ts +2 -1
- package/dist/core/objects/schema/schema.diff.js +24 -1
- package/dist/core/objects/schema/schema.model.d.ts +10 -0
- package/dist/core/objects/schema/schema.model.js +18 -1
- package/dist/core/objects/security-label.types.d.ts +20 -0
- package/dist/core/objects/security-label.types.js +46 -0
- package/dist/core/objects/sequence/changes/sequence.base.d.ts +1 -1
- package/dist/core/objects/sequence/changes/sequence.security-label.d.ts +28 -0
- package/dist/core/objects/sequence/changes/sequence.security-label.js +61 -0
- package/dist/core/objects/sequence/changes/sequence.types.d.ts +2 -1
- package/dist/core/objects/sequence/sequence.diff.js +16 -0
- package/dist/core/objects/sequence/sequence.model.d.ts +10 -0
- package/dist/core/objects/sequence/sequence.model.js +19 -1
- package/dist/core/objects/subscription/changes/subscription.base.d.ts +1 -1
- package/dist/core/objects/subscription/changes/subscription.security-label.d.ts +28 -0
- package/dist/core/objects/subscription/changes/subscription.security-label.js +61 -0
- package/dist/core/objects/subscription/changes/subscription.types.d.ts +2 -1
- package/dist/core/objects/subscription/subscription.diff.js +16 -0
- package/dist/core/objects/subscription/subscription.model.d.ts +10 -0
- package/dist/core/objects/subscription/subscription.model.js +19 -1
- package/dist/core/objects/table/changes/table.base.d.ts +1 -1
- package/dist/core/objects/table/changes/table.security-label.d.ts +63 -0
- package/dist/core/objects/table/changes/table.security-label.js +134 -0
- package/dist/core/objects/table/changes/table.types.d.ts +2 -1
- package/dist/core/objects/table/table.diff.js +49 -0
- package/dist/core/objects/table/table.model.d.ts +30 -0
- package/dist/core/objects/table/table.model.js +34 -2
- package/dist/core/objects/type/composite-type/changes/composite-type.base.d.ts +1 -1
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.d.ts +28 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.js +61 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.types.d.ts +2 -1
- package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -0
- package/dist/core/objects/type/composite-type/composite-type.model.d.ts +22 -0
- package/dist/core/objects/type/composite-type/composite-type.model.js +22 -2
- package/dist/core/objects/type/enum/changes/enum.base.d.ts +1 -1
- package/dist/core/objects/type/enum/changes/enum.security-label.d.ts +28 -0
- package/dist/core/objects/type/enum/changes/enum.security-label.js +61 -0
- package/dist/core/objects/type/enum/changes/enum.types.d.ts +2 -1
- package/dist/core/objects/type/enum/enum.diff.js +16 -0
- package/dist/core/objects/type/enum/enum.model.d.ts +10 -0
- package/dist/core/objects/type/enum/enum.model.js +20 -1
- package/dist/core/objects/type/range/changes/range.base.d.ts +1 -1
- package/dist/core/objects/type/range/changes/range.security-label.d.ts +28 -0
- package/dist/core/objects/type/range/changes/range.security-label.js +61 -0
- package/dist/core/objects/type/range/changes/range.types.d.ts +2 -1
- package/dist/core/objects/type/range/range.diff.js +16 -0
- package/dist/core/objects/type/range/range.model.d.ts +10 -0
- package/dist/core/objects/type/range/range.model.js +19 -1
- package/dist/core/objects/utils.d.ts +1 -0
- package/dist/core/objects/utils.js +3 -0
- package/dist/core/objects/view/changes/view.base.d.ts +1 -1
- package/dist/core/objects/view/changes/view.security-label.d.ts +28 -0
- package/dist/core/objects/view/changes/view.security-label.js +61 -0
- package/dist/core/objects/view/changes/view.types.d.ts +2 -1
- package/dist/core/objects/view/view.diff.js +13 -0
- package/dist/core/objects/view/view.model.d.ts +26 -0
- package/dist/core/objects/view/view.model.js +20 -1
- package/dist/core/plan/sql-format/fixtures.js +1 -0
- package/package.json +1 -1
- package/src/core/catalog.model.ts +1 -0
- package/src/core/integrations/filter/dsl.test.ts +27 -0
- package/src/core/integrations/filter/flatten.ts +16 -0
- package/src/core/objects/aggregate/aggregate.diff.ts +33 -0
- package/src/core/objects/aggregate/aggregate.model.ts +22 -1
- package/src/core/objects/aggregate/changes/aggregate.base.ts +5 -1
- package/src/core/objects/aggregate/changes/aggregate.security-label.ts +99 -0
- package/src/core/objects/aggregate/changes/aggregate.types.ts +3 -1
- package/src/core/objects/base.model.ts +2 -0
- package/src/core/objects/domain/changes/domain.base.ts +5 -1
- package/src/core/objects/domain/changes/domain.security-label.test.ts +56 -0
- package/src/core/objects/domain/changes/domain.security-label.ts +77 -0
- package/src/core/objects/domain/changes/domain.types.ts +3 -1
- package/src/core/objects/domain/domain.diff.ts +33 -0
- package/src/core/objects/domain/domain.model.ts +22 -1
- package/src/core/objects/event-trigger/changes/event-trigger.base.ts +1 -1
- package/src/core/objects/event-trigger/changes/event-trigger.security-label.ts +95 -0
- package/src/core/objects/event-trigger/changes/event-trigger.types.ts +3 -1
- package/src/core/objects/event-trigger/event-trigger.diff.ts +33 -0
- package/src/core/objects/event-trigger/event-trigger.model.ts +22 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.ts +95 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +3 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +33 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +24 -1
- package/src/core/objects/materialized-view/changes/materialized-view.base.ts +5 -1
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.test.ts +63 -0
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.ts +95 -0
- package/src/core/objects/materialized-view/changes/materialized-view.types.ts +3 -1
- package/src/core/objects/materialized-view/materialized-view.diff.ts +37 -0
- package/src/core/objects/materialized-view/materialized-view.model.ts +25 -4
- package/src/core/objects/procedure/changes/procedure.base.ts +5 -1
- package/src/core/objects/procedure/changes/procedure.security-label.ts +105 -0
- package/src/core/objects/procedure/changes/procedure.types.ts +3 -1
- package/src/core/objects/procedure/procedure.diff.ts +33 -0
- package/src/core/objects/procedure/procedure.model.ts +23 -2
- package/src/core/objects/publication/changes/publication.base.ts +1 -1
- package/src/core/objects/publication/changes/publication.security-label.ts +95 -0
- package/src/core/objects/publication/changes/publication.types.ts +3 -1
- package/src/core/objects/publication/publication.diff.ts +33 -0
- package/src/core/objects/publication/publication.model.ts +24 -1
- package/src/core/objects/role/changes/role.base.ts +2 -1
- package/src/core/objects/role/changes/role.security-label.ts +77 -0
- package/src/core/objects/role/changes/role.types.ts +3 -1
- package/src/core/objects/role/role.diff.ts +33 -0
- package/src/core/objects/role/role.model.ts +32 -0
- package/src/core/objects/schema/changes/schema.alter.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.base.ts +5 -1
- package/src/core/objects/schema/changes/schema.create.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.drop.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.security-label.test.ts +76 -0
- package/src/core/objects/schema/changes/schema.security-label.ts +77 -0
- package/src/core/objects/schema/changes/schema.types.ts +3 -1
- package/src/core/objects/schema/schema.diff.test.ts +1 -0
- package/src/core/objects/schema/schema.diff.ts +43 -1
- package/src/core/objects/schema/schema.model.ts +21 -1
- package/src/core/objects/security-label.types.test.ts +106 -0
- package/src/core/objects/security-label.types.ts +61 -0
- package/src/core/objects/sequence/changes/sequence.base.ts +5 -1
- package/src/core/objects/sequence/changes/sequence.security-label.test.ts +58 -0
- package/src/core/objects/sequence/changes/sequence.security-label.ts +92 -0
- package/src/core/objects/sequence/changes/sequence.types.ts +3 -1
- package/src/core/objects/sequence/sequence.diff.ts +33 -0
- package/src/core/objects/sequence/sequence.model.ts +22 -1
- package/src/core/objects/subscription/changes/subscription.base.ts +1 -1
- package/src/core/objects/subscription/changes/subscription.security-label.ts +95 -0
- package/src/core/objects/subscription/changes/subscription.types.ts +3 -1
- package/src/core/objects/subscription/subscription.diff.ts +33 -0
- package/src/core/objects/subscription/subscription.model.ts +22 -1
- package/src/core/objects/table/changes/table.base.ts +5 -1
- package/src/core/objects/table/changes/table.security-label.test.ts +140 -0
- package/src/core/objects/table/changes/table.security-label.ts +183 -0
- package/src/core/objects/table/changes/table.types.ts +3 -1
- package/src/core/objects/table/table.diff.ts +87 -0
- package/src/core/objects/table/table.model.ts +42 -2
- package/src/core/objects/type/composite-type/changes/composite-type.base.ts +5 -1
- package/src/core/objects/type/composite-type/changes/composite-type.security-label.ts +95 -0
- package/src/core/objects/type/composite-type/changes/composite-type.types.ts +3 -1
- package/src/core/objects/type/composite-type/composite-type.diff.ts +33 -0
- package/src/core/objects/type/composite-type/composite-type.model.ts +26 -2
- package/src/core/objects/type/enum/changes/enum.base.ts +5 -1
- package/src/core/objects/type/enum/changes/enum.security-label.ts +77 -0
- package/src/core/objects/type/enum/changes/enum.types.ts +3 -1
- package/src/core/objects/type/enum/enum.diff.ts +33 -0
- package/src/core/objects/type/enum/enum.model.ts +25 -1
- package/src/core/objects/type/range/changes/range.base.ts +5 -1
- package/src/core/objects/type/range/changes/range.security-label.ts +77 -0
- package/src/core/objects/type/range/changes/range.types.ts +3 -1
- package/src/core/objects/type/range/range.diff.ts +33 -0
- package/src/core/objects/type/range/range.model.ts +22 -1
- package/src/core/objects/utils.ts +3 -0
- package/src/core/objects/view/changes/view.base.ts +5 -1
- package/src/core/objects/view/changes/view.security-label.test.ts +64 -0
- package/src/core/objects/view/changes/view.security-label.ts +77 -0
- package/src/core/objects/view/changes/view.types.ts +3 -1
- package/src/core/objects/view/view.diff.ts +31 -0
- package/src/core/objects/view/view.model.ts +25 -2
- package/src/core/plan/sql-format/fixtures.ts +1 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
2
|
+
import type { Role } from "../role.model.ts";
|
|
3
|
+
import { CreateRoleChange, DropRoleChange } from "./role.base.ts";
|
|
4
|
+
export type SecurityLabelRole = CreateSecurityLabelOnRole | DropSecurityLabelOnRole;
|
|
5
|
+
export declare class CreateSecurityLabelOnRole extends CreateRoleChange {
|
|
6
|
+
readonly role: Role;
|
|
7
|
+
readonly securityLabel: SecurityLabelProps;
|
|
8
|
+
readonly scope: "security_label";
|
|
9
|
+
constructor(props: {
|
|
10
|
+
role: Role;
|
|
11
|
+
securityLabel: SecurityLabelProps;
|
|
12
|
+
});
|
|
13
|
+
get creates(): `securityLabel:${string}::provider:${string}`[];
|
|
14
|
+
get requires(): `role:${string}`[];
|
|
15
|
+
serialize(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare class DropSecurityLabelOnRole extends DropRoleChange {
|
|
18
|
+
readonly role: Role;
|
|
19
|
+
readonly securityLabel: SecurityLabelProps;
|
|
20
|
+
readonly scope: "security_label";
|
|
21
|
+
constructor(props: {
|
|
22
|
+
role: Role;
|
|
23
|
+
securityLabel: SecurityLabelProps;
|
|
24
|
+
});
|
|
25
|
+
get drops(): `securityLabel:${string}::provider:${string}`[];
|
|
26
|
+
get requires(): (`securityLabel:${string}::provider:${string}` | `role:${string}`)[];
|
|
27
|
+
serialize(): string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.js";
|
|
2
|
+
import { stableId } from "../../utils.js";
|
|
3
|
+
import { CreateRoleChange, DropRoleChange } from "./role.base.js";
|
|
4
|
+
export class CreateSecurityLabelOnRole extends CreateRoleChange {
|
|
5
|
+
role;
|
|
6
|
+
securityLabel;
|
|
7
|
+
scope = "security_label";
|
|
8
|
+
constructor(props) {
|
|
9
|
+
super();
|
|
10
|
+
this.role = props.role;
|
|
11
|
+
this.securityLabel = props.securityLabel;
|
|
12
|
+
}
|
|
13
|
+
get creates() {
|
|
14
|
+
return [
|
|
15
|
+
stableId.securityLabel(this.role.stableId, this.securityLabel.provider),
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
get requires() {
|
|
19
|
+
return [this.role.stableId];
|
|
20
|
+
}
|
|
21
|
+
serialize() {
|
|
22
|
+
return [
|
|
23
|
+
"SECURITY LABEL FOR",
|
|
24
|
+
this.securityLabel.provider,
|
|
25
|
+
"ON ROLE",
|
|
26
|
+
this.role.name,
|
|
27
|
+
"IS",
|
|
28
|
+
quoteLiteral(this.securityLabel.label),
|
|
29
|
+
].join(" ");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class DropSecurityLabelOnRole extends DropRoleChange {
|
|
33
|
+
role;
|
|
34
|
+
securityLabel;
|
|
35
|
+
scope = "security_label";
|
|
36
|
+
constructor(props) {
|
|
37
|
+
super();
|
|
38
|
+
this.role = props.role;
|
|
39
|
+
this.securityLabel = props.securityLabel;
|
|
40
|
+
}
|
|
41
|
+
get drops() {
|
|
42
|
+
return [
|
|
43
|
+
stableId.securityLabel(this.role.stableId, this.securityLabel.provider),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
get requires() {
|
|
47
|
+
return [
|
|
48
|
+
stableId.securityLabel(this.role.stableId, this.securityLabel.provider),
|
|
49
|
+
this.role.stableId,
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
serialize() {
|
|
53
|
+
return [
|
|
54
|
+
"SECURITY LABEL FOR",
|
|
55
|
+
this.securityLabel.provider,
|
|
56
|
+
"ON ROLE",
|
|
57
|
+
this.role.name,
|
|
58
|
+
"IS NULL",
|
|
59
|
+
].join(" ");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -3,5 +3,6 @@ import type { CommentRole } from "./role.comment.ts";
|
|
|
3
3
|
import type { CreateRole } from "./role.create.ts";
|
|
4
4
|
import type { DropRole } from "./role.drop.ts";
|
|
5
5
|
import type { RolePrivilege } from "./role.privilege.ts";
|
|
6
|
+
import type { SecurityLabelRole } from "./role.security-label.ts";
|
|
6
7
|
/** Union of all role-related change variants (`objectType: "role"`). @category Change Types */
|
|
7
|
-
export type RoleChange = AlterRole | CommentRole | CreateRole | DropRole | RolePrivilege;
|
|
8
|
+
export type RoleChange = AlterRole | CommentRole | CreateRole | DropRole | RolePrivilege | SecurityLabelRole;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.js";
|
|
2
|
+
import { diffSecurityLabels } from "../security-label.types.js";
|
|
2
3
|
import { AlterRoleSetConfig, AlterRoleSetOptions, } from "./changes/role.alter.js";
|
|
3
4
|
import { CreateCommentOnRole, DropCommentOnRole, } from "./changes/role.comment.js";
|
|
4
5
|
import { CreateRole } from "./changes/role.create.js";
|
|
5
6
|
import { DropRole } from "./changes/role.drop.js";
|
|
6
7
|
import { GrantRoleDefaultPrivileges, GrantRoleMembership, RevokeRoleDefaultPrivileges, RevokeRoleMembership, RevokeRoleMembershipOptions, } from "./changes/role.privilege.js";
|
|
8
|
+
import { CreateSecurityLabelOnRole, DropSecurityLabelOnRole, } from "./changes/role.security-label.js";
|
|
7
9
|
/**
|
|
8
10
|
* Diff two sets of roles from main and branch catalogs.
|
|
9
11
|
*
|
|
@@ -31,6 +33,12 @@ export function diffRoles(ctx, main, branch) {
|
|
|
31
33
|
if (role.comment !== null) {
|
|
32
34
|
changes.push(new CreateCommentOnRole({ role }));
|
|
33
35
|
}
|
|
36
|
+
for (const label of role.security_labels) {
|
|
37
|
+
changes.push(new CreateSecurityLabelOnRole({
|
|
38
|
+
role,
|
|
39
|
+
securityLabel: label,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
34
42
|
// MEMBERSHIPS: Grant memberships immediately after role creation.
|
|
35
43
|
// Members are already deduplicated by the Role model constructor.
|
|
36
44
|
for (const membership of role.members) {
|
|
@@ -171,6 +179,14 @@ export function diffRoles(ctx, main, branch) {
|
|
|
171
179
|
changes.push(new CreateCommentOnRole({ role: branchRole }));
|
|
172
180
|
}
|
|
173
181
|
}
|
|
182
|
+
// SECURITY LABELS
|
|
183
|
+
changes.push(...diffSecurityLabels(mainRole.security_labels, branchRole.security_labels, (securityLabel) => new CreateSecurityLabelOnRole({
|
|
184
|
+
role: branchRole,
|
|
185
|
+
securityLabel,
|
|
186
|
+
}), (securityLabel) => new DropSecurityLabelOnRole({
|
|
187
|
+
role: mainRole,
|
|
188
|
+
securityLabel,
|
|
189
|
+
})));
|
|
174
190
|
// MEMBERSHIPS
|
|
175
191
|
// Members are already deduplicated by the Role model constructor.
|
|
176
192
|
const mainMembers = new Map(mainRole.members.map((m) => [m.member, m]));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Pool } from "pg";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel } from "../base.model.ts";
|
|
4
|
+
import { type SecurityLabelProps } from "../security-label.types.ts";
|
|
4
5
|
declare const rolePropsSchema: z.ZodObject<{
|
|
5
6
|
name: z.ZodString;
|
|
6
7
|
is_superuser: z.ZodBoolean;
|
|
@@ -36,6 +37,10 @@ declare const rolePropsSchema: z.ZodObject<{
|
|
|
36
37
|
}, z.z.core.$strip>>;
|
|
37
38
|
is_implicit: z.ZodBoolean;
|
|
38
39
|
}, z.z.core.$strip>>;
|
|
40
|
+
security_labels: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
41
|
+
provider: z.ZodString;
|
|
42
|
+
label: z.ZodString;
|
|
43
|
+
}, z.z.core.$strip>>>>;
|
|
39
44
|
}, z.z.core.$strip>;
|
|
40
45
|
export type RoleProps = z.infer<typeof rolePropsSchema>;
|
|
41
46
|
export declare class Role extends BasePgModel {
|
|
@@ -52,6 +57,7 @@ export declare class Role extends BasePgModel {
|
|
|
52
57
|
readonly comment: RoleProps["comment"];
|
|
53
58
|
readonly members: RoleProps["members"];
|
|
54
59
|
readonly default_privileges: RoleProps["default_privileges"];
|
|
60
|
+
readonly security_labels: SecurityLabelProps[];
|
|
55
61
|
constructor(props: RoleProps);
|
|
56
62
|
get stableId(): `role:${string}`;
|
|
57
63
|
get identityFields(): {
|
|
@@ -84,6 +90,10 @@ export declare class Role extends BasePgModel {
|
|
|
84
90
|
objtype: "n" | "r" | "f" | "S" | "T";
|
|
85
91
|
grantee: string;
|
|
86
92
|
}[];
|
|
93
|
+
security_labels: {
|
|
94
|
+
provider: string;
|
|
95
|
+
label: string;
|
|
96
|
+
}[];
|
|
87
97
|
};
|
|
88
98
|
}
|
|
89
99
|
export declare function extractRoles(pool: Pool): Promise<Role[]>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sql } from "@ts-safeql/sql-tag";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel } from "../base.model.js";
|
|
4
|
+
import { securityLabelPropsSchema, } from "../security-label.types.js";
|
|
4
5
|
const membershipInfoSchema = z.object({
|
|
5
6
|
member: z.string(),
|
|
6
7
|
grantor: z.string(),
|
|
@@ -29,6 +30,7 @@ const rolePropsSchema = z.object({
|
|
|
29
30
|
comment: z.string().nullable(),
|
|
30
31
|
members: z.array(membershipInfoSchema),
|
|
31
32
|
default_privileges: z.array(defaultPrivilegeSchema),
|
|
33
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
32
34
|
});
|
|
33
35
|
export class Role extends BasePgModel {
|
|
34
36
|
name;
|
|
@@ -44,6 +46,7 @@ export class Role extends BasePgModel {
|
|
|
44
46
|
comment;
|
|
45
47
|
members;
|
|
46
48
|
default_privileges;
|
|
49
|
+
security_labels;
|
|
47
50
|
constructor(props) {
|
|
48
51
|
super();
|
|
49
52
|
// Identity fields
|
|
@@ -61,6 +64,7 @@ export class Role extends BasePgModel {
|
|
|
61
64
|
this.comment = props.comment;
|
|
62
65
|
this.members = deduplicateMembers(props.members);
|
|
63
66
|
this.default_privileges = props.default_privileges;
|
|
67
|
+
this.security_labels = props.security_labels ?? [];
|
|
64
68
|
}
|
|
65
69
|
get stableId() {
|
|
66
70
|
return `role:${this.name}`;
|
|
@@ -106,6 +110,7 @@ export class Role extends BasePgModel {
|
|
|
106
110
|
comment: this.comment,
|
|
107
111
|
members: sortedMembers,
|
|
108
112
|
default_privileges: sortedDefaultPrivs,
|
|
113
|
+
security_labels: this.security_labels,
|
|
109
114
|
};
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -200,6 +205,18 @@ export async function extractRoles(pool) {
|
|
|
200
205
|
r.rolbypassrls AS can_bypass_rls,
|
|
201
206
|
r.rolconfig AS config,
|
|
202
207
|
obj_description(r.oid, 'pg_authid') AS comment,
|
|
208
|
+
COALESCE(
|
|
209
|
+
(
|
|
210
|
+
SELECT json_agg(
|
|
211
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
212
|
+
ORDER BY sl.provider
|
|
213
|
+
)
|
|
214
|
+
FROM pg_catalog.pg_shseclabel sl
|
|
215
|
+
WHERE sl.objoid = r.oid
|
|
216
|
+
AND sl.classoid = 'pg_authid'::regclass
|
|
217
|
+
),
|
|
218
|
+
'[]'::json
|
|
219
|
+
) AS security_labels,
|
|
203
220
|
COALESCE(rm.members, '[]') AS members,
|
|
204
221
|
COALESCE(
|
|
205
222
|
(
|
|
@@ -322,6 +339,18 @@ export async function extractRoles(pool) {
|
|
|
322
339
|
r.rolbypassrls AS can_bypass_rls,
|
|
323
340
|
r.rolconfig AS config,
|
|
324
341
|
obj_description(r.oid, 'pg_authid') AS comment,
|
|
342
|
+
COALESCE(
|
|
343
|
+
(
|
|
344
|
+
SELECT json_agg(
|
|
345
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
346
|
+
ORDER BY sl.provider
|
|
347
|
+
)
|
|
348
|
+
FROM pg_catalog.pg_shseclabel sl
|
|
349
|
+
WHERE sl.objoid = r.oid
|
|
350
|
+
AND sl.classoid = 'pg_authid'::regclass
|
|
351
|
+
),
|
|
352
|
+
'[]'::json
|
|
353
|
+
) AS security_labels,
|
|
325
354
|
COALESCE(rm.members, '[]') AS members,
|
|
326
355
|
COALESCE(
|
|
327
356
|
(
|
|
@@ -2,7 +2,7 @@ import { BaseChange } from "../../base.change.ts";
|
|
|
2
2
|
import type { Schema } from "../schema.model.ts";
|
|
3
3
|
declare abstract class BaseSchemaChange extends BaseChange {
|
|
4
4
|
abstract readonly schema: Schema;
|
|
5
|
-
abstract readonly scope: "object" | "comment" | "privilege";
|
|
5
|
+
abstract readonly scope: "object" | "comment" | "privilege" | "security_label";
|
|
6
6
|
readonly objectType: "schema";
|
|
7
7
|
}
|
|
8
8
|
export declare abstract class CreateSchemaChange extends BaseSchemaChange {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
2
|
+
import type { Schema } from "../schema.model.ts";
|
|
3
|
+
import { CreateSchemaChange, DropSchemaChange } from "./schema.base.ts";
|
|
4
|
+
export type SecurityLabelSchema = CreateSecurityLabelOnSchema | DropSecurityLabelOnSchema;
|
|
5
|
+
export declare class CreateSecurityLabelOnSchema extends CreateSchemaChange {
|
|
6
|
+
readonly schema: Schema;
|
|
7
|
+
readonly securityLabel: SecurityLabelProps;
|
|
8
|
+
readonly scope: "security_label";
|
|
9
|
+
constructor(props: {
|
|
10
|
+
schema: Schema;
|
|
11
|
+
securityLabel: SecurityLabelProps;
|
|
12
|
+
});
|
|
13
|
+
get creates(): `securityLabel:${string}::provider:${string}`[];
|
|
14
|
+
get requires(): `schema:${string}`[];
|
|
15
|
+
serialize(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare class DropSecurityLabelOnSchema extends DropSchemaChange {
|
|
18
|
+
readonly schema: Schema;
|
|
19
|
+
readonly securityLabel: SecurityLabelProps;
|
|
20
|
+
readonly scope: "security_label";
|
|
21
|
+
constructor(props: {
|
|
22
|
+
schema: Schema;
|
|
23
|
+
securityLabel: SecurityLabelProps;
|
|
24
|
+
});
|
|
25
|
+
get drops(): `securityLabel:${string}::provider:${string}`[];
|
|
26
|
+
get requires(): (`schema:${string}` | `securityLabel:${string}::provider:${string}`)[];
|
|
27
|
+
serialize(): string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.js";
|
|
2
|
+
import { stableId } from "../../utils.js";
|
|
3
|
+
import { CreateSchemaChange, DropSchemaChange } from "./schema.base.js";
|
|
4
|
+
export class CreateSecurityLabelOnSchema extends CreateSchemaChange {
|
|
5
|
+
schema;
|
|
6
|
+
securityLabel;
|
|
7
|
+
scope = "security_label";
|
|
8
|
+
constructor(props) {
|
|
9
|
+
super();
|
|
10
|
+
this.schema = props.schema;
|
|
11
|
+
this.securityLabel = props.securityLabel;
|
|
12
|
+
}
|
|
13
|
+
get creates() {
|
|
14
|
+
return [
|
|
15
|
+
stableId.securityLabel(this.schema.stableId, this.securityLabel.provider),
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
get requires() {
|
|
19
|
+
return [this.schema.stableId];
|
|
20
|
+
}
|
|
21
|
+
serialize() {
|
|
22
|
+
return [
|
|
23
|
+
"SECURITY LABEL FOR",
|
|
24
|
+
this.securityLabel.provider,
|
|
25
|
+
"ON SCHEMA",
|
|
26
|
+
this.schema.name,
|
|
27
|
+
"IS",
|
|
28
|
+
quoteLiteral(this.securityLabel.label),
|
|
29
|
+
].join(" ");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class DropSecurityLabelOnSchema extends DropSchemaChange {
|
|
33
|
+
schema;
|
|
34
|
+
securityLabel;
|
|
35
|
+
scope = "security_label";
|
|
36
|
+
constructor(props) {
|
|
37
|
+
super();
|
|
38
|
+
this.schema = props.schema;
|
|
39
|
+
this.securityLabel = props.securityLabel;
|
|
40
|
+
}
|
|
41
|
+
get drops() {
|
|
42
|
+
return [
|
|
43
|
+
stableId.securityLabel(this.schema.stableId, this.securityLabel.provider),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
get requires() {
|
|
47
|
+
return [
|
|
48
|
+
stableId.securityLabel(this.schema.stableId, this.securityLabel.provider),
|
|
49
|
+
this.schema.stableId,
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
serialize() {
|
|
53
|
+
return [
|
|
54
|
+
"SECURITY LABEL FOR",
|
|
55
|
+
this.securityLabel.provider,
|
|
56
|
+
"ON SCHEMA",
|
|
57
|
+
this.schema.name,
|
|
58
|
+
"IS NULL",
|
|
59
|
+
].join(" ");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -3,5 +3,6 @@ import type { CommentSchema } from "./schema.comment.ts";
|
|
|
3
3
|
import type { CreateSchema } from "./schema.create.ts";
|
|
4
4
|
import type { DropSchema } from "./schema.drop.ts";
|
|
5
5
|
import type { SchemaPrivilege } from "./schema.privilege.ts";
|
|
6
|
+
import type { SecurityLabelSchema } from "./schema.security-label.ts";
|
|
6
7
|
/** Union of all schema-related change variants (`objectType: "schema"`). @category Change Types */
|
|
7
|
-
export type SchemaChange = AlterSchema | CommentSchema | CreateSchema | DropSchema | SchemaPrivilege;
|
|
8
|
+
export type SchemaChange = AlterSchema | CommentSchema | CreateSchema | DropSchema | SchemaPrivilege | SecurityLabelSchema;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.js";
|
|
2
2
|
import { diffPrivileges, emitObjectPrivilegeChanges, } from "../base.privilege-diff.js";
|
|
3
|
+
import { diffSecurityLabels } from "../security-label.types.js";
|
|
3
4
|
import { AlterSchemaChangeOwner } from "./changes/schema.alter.js";
|
|
4
5
|
import { CreateCommentOnSchema, DropCommentOnSchema, } from "./changes/schema.comment.js";
|
|
5
6
|
import { CreateSchema } from "./changes/schema.create.js";
|
|
6
7
|
import { DropSchema } from "./changes/schema.drop.js";
|
|
7
8
|
import { GrantSchemaPrivileges, RevokeGrantOptionSchemaPrivileges, RevokeSchemaPrivileges, } from "./changes/schema.privilege.js";
|
|
9
|
+
import { CreateSecurityLabelOnSchema, DropSecurityLabelOnSchema, } from "./changes/schema.security-label.js";
|
|
8
10
|
/**
|
|
9
11
|
* Diff two sets of schemas from main and branch catalogs.
|
|
10
12
|
*
|
|
@@ -22,6 +24,12 @@ export function diffSchemas(ctx, main, branch) {
|
|
|
22
24
|
if (sc.comment !== null) {
|
|
23
25
|
changes.push(new CreateCommentOnSchema({ schema: sc }));
|
|
24
26
|
}
|
|
27
|
+
for (const label of sc.security_labels) {
|
|
28
|
+
changes.push(new CreateSecurityLabelOnSchema({
|
|
29
|
+
schema: sc,
|
|
30
|
+
securityLabel: label,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
25
33
|
// PRIVILEGES: For created objects, compare against default privileges state
|
|
26
34
|
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
27
35
|
// so objects are created with the default privileges state in effect.
|
|
@@ -43,7 +51,14 @@ export function diffSchemas(ctx, main, branch) {
|
|
|
43
51
|
}, ctx.version));
|
|
44
52
|
}
|
|
45
53
|
for (const schemaId of dropped) {
|
|
46
|
-
|
|
54
|
+
const mainSchema = main[schemaId];
|
|
55
|
+
for (const label of mainSchema.security_labels) {
|
|
56
|
+
changes.push(new DropSecurityLabelOnSchema({
|
|
57
|
+
schema: mainSchema,
|
|
58
|
+
securityLabel: label,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
changes.push(new DropSchema({ schema: mainSchema }));
|
|
47
62
|
}
|
|
48
63
|
for (const schemaId of altered) {
|
|
49
64
|
const mainSchema = main[schemaId];
|
|
@@ -64,6 +79,14 @@ export function diffSchemas(ctx, main, branch) {
|
|
|
64
79
|
changes.push(new CreateCommentOnSchema({ schema: branchSchema }));
|
|
65
80
|
}
|
|
66
81
|
}
|
|
82
|
+
// SECURITY LABELS
|
|
83
|
+
changes.push(...diffSecurityLabels(mainSchema.security_labels, branchSchema.security_labels, (securityLabel) => new CreateSecurityLabelOnSchema({
|
|
84
|
+
schema: branchSchema,
|
|
85
|
+
securityLabel,
|
|
86
|
+
}), (securityLabel) => new DropSecurityLabelOnSchema({
|
|
87
|
+
schema: mainSchema,
|
|
88
|
+
securityLabel,
|
|
89
|
+
})));
|
|
67
90
|
// PRIVILEGES
|
|
68
91
|
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
69
92
|
// and shouldn't be compared. Use branch owner as the reference.
|
|
@@ -2,6 +2,7 @@ import type { Pool } from "pg";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel } from "../base.model.ts";
|
|
4
4
|
import { type PrivilegeProps } from "../base.privilege-diff.ts";
|
|
5
|
+
import { type SecurityLabelProps } from "../security-label.types.ts";
|
|
5
6
|
/**
|
|
6
7
|
* All properties exposed by CREATE SCHEMA statement are included in diff output.
|
|
7
8
|
* https://www.postgresql.org/docs/current/sql-createschema.html
|
|
@@ -19,6 +20,10 @@ declare const schemaPropsSchema: z.ZodObject<{
|
|
|
19
20
|
grantable: z.ZodBoolean;
|
|
20
21
|
columns: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
21
22
|
}, z.z.core.$strip>>;
|
|
23
|
+
security_labels: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
24
|
+
provider: z.ZodString;
|
|
25
|
+
label: z.ZodString;
|
|
26
|
+
}, z.z.core.$strip>>>>;
|
|
22
27
|
}, z.z.core.$strip>;
|
|
23
28
|
type SchemaPrivilegeProps = PrivilegeProps;
|
|
24
29
|
export type SchemaProps = z.infer<typeof schemaPropsSchema>;
|
|
@@ -27,6 +32,7 @@ export declare class Schema extends BasePgModel {
|
|
|
27
32
|
readonly owner: SchemaProps["owner"];
|
|
28
33
|
readonly comment: SchemaProps["comment"];
|
|
29
34
|
readonly privileges: SchemaPrivilegeProps[];
|
|
35
|
+
readonly security_labels: SecurityLabelProps[];
|
|
30
36
|
constructor(props: SchemaProps);
|
|
31
37
|
get stableId(): `schema:${string}`;
|
|
32
38
|
get identityFields(): {
|
|
@@ -41,6 +47,10 @@ export declare class Schema extends BasePgModel {
|
|
|
41
47
|
grantable: boolean;
|
|
42
48
|
columns?: string[] | null | undefined;
|
|
43
49
|
}[];
|
|
50
|
+
security_labels: {
|
|
51
|
+
provider: string;
|
|
52
|
+
label: string;
|
|
53
|
+
}[];
|
|
44
54
|
};
|
|
45
55
|
}
|
|
46
56
|
export declare function extractSchemas(pool: Pool): Promise<Schema[]>;
|
|
@@ -2,6 +2,7 @@ import { sql } from "@ts-safeql/sql-tag";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel } from "../base.model.js";
|
|
4
4
|
import { privilegePropsSchema, } from "../base.privilege-diff.js";
|
|
5
|
+
import { securityLabelPropsSchema, } from "../security-label.types.js";
|
|
5
6
|
/**
|
|
6
7
|
* All properties exposed by CREATE SCHEMA statement are included in diff output.
|
|
7
8
|
* https://www.postgresql.org/docs/current/sql-createschema.html
|
|
@@ -14,12 +15,14 @@ const schemaPropsSchema = z.object({
|
|
|
14
15
|
owner: z.string(),
|
|
15
16
|
comment: z.string().nullable(),
|
|
16
17
|
privileges: z.array(privilegePropsSchema),
|
|
18
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
17
19
|
});
|
|
18
20
|
export class Schema extends BasePgModel {
|
|
19
21
|
name;
|
|
20
22
|
owner;
|
|
21
23
|
comment;
|
|
22
24
|
privileges;
|
|
25
|
+
security_labels;
|
|
23
26
|
constructor(props) {
|
|
24
27
|
super();
|
|
25
28
|
// Identity fields
|
|
@@ -28,6 +31,7 @@ export class Schema extends BasePgModel {
|
|
|
28
31
|
this.owner = props.owner;
|
|
29
32
|
this.comment = props.comment;
|
|
30
33
|
this.privileges = props.privileges;
|
|
34
|
+
this.security_labels = props.security_labels ?? [];
|
|
31
35
|
}
|
|
32
36
|
get stableId() {
|
|
33
37
|
return `schema:${this.name}`;
|
|
@@ -42,6 +46,7 @@ export class Schema extends BasePgModel {
|
|
|
42
46
|
owner: this.owner,
|
|
43
47
|
comment: this.comment,
|
|
44
48
|
privileges: this.privileges,
|
|
49
|
+
security_labels: this.security_labels,
|
|
45
50
|
};
|
|
46
51
|
}
|
|
47
52
|
}
|
|
@@ -72,7 +77,19 @@ export async function extractSchemas(pool) {
|
|
|
72
77
|
)
|
|
73
78
|
from lateral aclexplode(COALESCE(nspacl, acldefault('n', nspowner))) as x(grantor, grantee, privilege_type, is_grantable)
|
|
74
79
|
), '[]'
|
|
75
|
-
) as privileges
|
|
80
|
+
) as privileges,
|
|
81
|
+
coalesce(
|
|
82
|
+
(
|
|
83
|
+
select json_agg(
|
|
84
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
85
|
+
order by sl.provider
|
|
86
|
+
)
|
|
87
|
+
from pg_catalog.pg_seclabel sl
|
|
88
|
+
where sl.objoid = pg_namespace.oid
|
|
89
|
+
and sl.classoid = 'pg_namespace'::regclass
|
|
90
|
+
and sl.objsubid = 0
|
|
91
|
+
), '[]'
|
|
92
|
+
) as security_labels
|
|
76
93
|
from
|
|
77
94
|
pg_catalog.pg_namespace
|
|
78
95
|
left outer join extension_oids e on e.objid = oid
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const securityLabelPropsSchema: z.ZodObject<{
|
|
3
|
+
provider: z.ZodString;
|
|
4
|
+
label: z.ZodString;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
export type SecurityLabelProps = z.infer<typeof securityLabelPropsSchema>;
|
|
7
|
+
export declare function normalizeSecurityLabels(labels: readonly SecurityLabelProps[]): SecurityLabelProps[];
|
|
8
|
+
/**
|
|
9
|
+
* Pure helper: compares two arrays of security labels keyed by provider and
|
|
10
|
+
* returns a deterministic list of create/drop changes.
|
|
11
|
+
*
|
|
12
|
+
* - Labels present only on `branch` → emit create (via makeCreate).
|
|
13
|
+
* - Labels present only on `main` → emit drop (via makeDrop).
|
|
14
|
+
* - Labels with differing `label` under the same provider → emit create
|
|
15
|
+
* (PostgreSQL's SECURITY LABEL … IS '…' overwrites, so no separate alter).
|
|
16
|
+
* - Unchanged labels → nothing.
|
|
17
|
+
*
|
|
18
|
+
* Output order: by provider ascending.
|
|
19
|
+
*/
|
|
20
|
+
export declare function diffSecurityLabels<C>(main: readonly SecurityLabelProps[], branch: readonly SecurityLabelProps[], makeCreate: (props: SecurityLabelProps) => C, makeDrop: (props: SecurityLabelProps) => C): C[];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const securityLabelPropsSchema = z.object({
|
|
3
|
+
provider: z.string(),
|
|
4
|
+
label: z.string(),
|
|
5
|
+
});
|
|
6
|
+
export function normalizeSecurityLabels(labels) {
|
|
7
|
+
return [...labels].sort((a, b) => a.provider.localeCompare(b.provider));
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Pure helper: compares two arrays of security labels keyed by provider and
|
|
11
|
+
* returns a deterministic list of create/drop changes.
|
|
12
|
+
*
|
|
13
|
+
* - Labels present only on `branch` → emit create (via makeCreate).
|
|
14
|
+
* - Labels present only on `main` → emit drop (via makeDrop).
|
|
15
|
+
* - Labels with differing `label` under the same provider → emit create
|
|
16
|
+
* (PostgreSQL's SECURITY LABEL … IS '…' overwrites, so no separate alter).
|
|
17
|
+
* - Unchanged labels → nothing.
|
|
18
|
+
*
|
|
19
|
+
* Output order: by provider ascending.
|
|
20
|
+
*/
|
|
21
|
+
export function diffSecurityLabels(main, branch, makeCreate, makeDrop) {
|
|
22
|
+
const mainByProvider = new Map(main.map((l) => [l.provider, l.label]));
|
|
23
|
+
const branchByProvider = new Map(branch.map((l) => [l.provider, l.label]));
|
|
24
|
+
const providers = new Set([
|
|
25
|
+
...mainByProvider.keys(),
|
|
26
|
+
...branchByProvider.keys(),
|
|
27
|
+
]);
|
|
28
|
+
const sortedProviders = [...providers].sort();
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const provider of sortedProviders) {
|
|
31
|
+
const mainLabel = mainByProvider.get(provider);
|
|
32
|
+
const branchLabel = branchByProvider.get(provider);
|
|
33
|
+
if (mainLabel === undefined && branchLabel !== undefined) {
|
|
34
|
+
out.push(makeCreate({ provider, label: branchLabel }));
|
|
35
|
+
}
|
|
36
|
+
else if (mainLabel !== undefined && branchLabel === undefined) {
|
|
37
|
+
out.push(makeDrop({ provider, label: mainLabel }));
|
|
38
|
+
}
|
|
39
|
+
else if (mainLabel !== undefined &&
|
|
40
|
+
branchLabel !== undefined &&
|
|
41
|
+
mainLabel !== branchLabel) {
|
|
42
|
+
out.push(makeCreate({ provider, label: branchLabel }));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
@@ -2,7 +2,7 @@ import { BaseChange } from "../../base.change.ts";
|
|
|
2
2
|
import type { Sequence } from "../sequence.model.ts";
|
|
3
3
|
declare abstract class BaseSequenceChange extends BaseChange {
|
|
4
4
|
abstract readonly sequence: Sequence;
|
|
5
|
-
abstract readonly scope: "object" | "comment" | "privilege";
|
|
5
|
+
abstract readonly scope: "object" | "comment" | "privilege" | "security_label";
|
|
6
6
|
readonly objectType: "sequence";
|
|
7
7
|
}
|
|
8
8
|
export declare abstract class CreateSequenceChange extends BaseSequenceChange {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
2
|
+
import type { Sequence } from "../sequence.model.ts";
|
|
3
|
+
import { CreateSequenceChange, DropSequenceChange } from "./sequence.base.ts";
|
|
4
|
+
export type SecurityLabelSequence = CreateSecurityLabelOnSequence | DropSecurityLabelOnSequence;
|
|
5
|
+
export declare class CreateSecurityLabelOnSequence extends CreateSequenceChange {
|
|
6
|
+
readonly sequence: Sequence;
|
|
7
|
+
readonly securityLabel: SecurityLabelProps;
|
|
8
|
+
readonly scope: "security_label";
|
|
9
|
+
constructor(props: {
|
|
10
|
+
sequence: Sequence;
|
|
11
|
+
securityLabel: SecurityLabelProps;
|
|
12
|
+
});
|
|
13
|
+
get creates(): `securityLabel:${string}::provider:${string}`[];
|
|
14
|
+
get requires(): `sequence:${string}`[];
|
|
15
|
+
serialize(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare class DropSecurityLabelOnSequence extends DropSequenceChange {
|
|
18
|
+
readonly sequence: Sequence;
|
|
19
|
+
readonly securityLabel: SecurityLabelProps;
|
|
20
|
+
readonly scope: "security_label";
|
|
21
|
+
constructor(props: {
|
|
22
|
+
sequence: Sequence;
|
|
23
|
+
securityLabel: SecurityLabelProps;
|
|
24
|
+
});
|
|
25
|
+
get drops(): `securityLabel:${string}::provider:${string}`[];
|
|
26
|
+
get requires(): (`securityLabel:${string}::provider:${string}` | `sequence:${string}`)[];
|
|
27
|
+
serialize(): string;
|
|
28
|
+
}
|